LCOV - code coverage report
Current view: top level - docshell/base - nsDocShell.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 2240 6592 34.0 %
Date: 2017-07-14 16:53:18 Functions: 213 461 46.2 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
       3             : /* This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #include "nsDocShell.h"
       8             : 
       9             : #include <algorithm>
      10             : 
      11             : #include "mozilla/ArrayUtils.h"
      12             : #include "mozilla/Attributes.h"
      13             : #include "mozilla/AutoRestore.h"
      14             : #include "mozilla/BasePrincipal.h"
      15             : #include "mozilla/Casting.h"
      16             : #include "mozilla/dom/ContentChild.h"
      17             : #include "mozilla/dom/Element.h"
      18             : #include "mozilla/dom/PendingGlobalHistoryEntry.h"
      19             : #include "mozilla/dom/TabChild.h"
      20             : #include "mozilla/dom/ProfileTimelineMarkerBinding.h"
      21             : #include "mozilla/dom/ScreenOrientation.h"
      22             : #include "mozilla/dom/ToJSValue.h"
      23             : #include "mozilla/dom/PermissionMessageUtils.h"
      24             : #include "mozilla/dom/workers/ServiceWorkerManager.h"
      25             : #include "mozilla/EventStateManager.h"
      26             : #include "mozilla/LoadInfo.h"
      27             : #include "mozilla/Preferences.h"
      28             : #include "mozilla/Services.h"
      29             : #include "mozilla/StartupTimeline.h"
      30             : #include "mozilla/Telemetry.h"
      31             : #include "mozilla/Unused.h"
      32             : #include "Navigator.h"
      33             : #include "URIUtils.h"
      34             : #include "mozilla/dom/DocGroup.h"
      35             : #include "mozilla/dom/TabGroup.h"
      36             : 
      37             : #include "nsIContent.h"
      38             : #include "nsIContentInlines.h"
      39             : #include "nsIDocument.h"
      40             : #include "nsIDOMDocument.h"
      41             : #include "nsIDOMElement.h"
      42             : 
      43             : #include "nsArray.h"
      44             : #include "nsArrayUtils.h"
      45             : #include "nsICaptivePortalService.h"
      46             : #include "nsIDOMStorage.h"
      47             : #include "nsIContentViewer.h"
      48             : #include "nsIDocumentLoaderFactory.h"
      49             : #include "nsCURILoader.h"
      50             : #include "nsDocShellCID.h"
      51             : #include "nsDOMCID.h"
      52             : #include "nsNetCID.h"
      53             : #include "nsNetUtil.h"
      54             : #include "mozilla/net/ReferrerPolicy.h"
      55             : #include "nsRect.h"
      56             : #include "prenv.h"
      57             : #include "nsIDOMWindow.h"
      58             : #include "nsIGlobalObject.h"
      59             : #include "nsIViewSourceChannel.h"
      60             : #include "nsIWebBrowserChrome.h"
      61             : #include "nsPoint.h"
      62             : #include "nsIObserverService.h"
      63             : #include "nsIPrompt.h"
      64             : #include "nsIAuthPrompt.h"
      65             : #include "nsIAuthPrompt2.h"
      66             : #include "nsIChannelEventSink.h"
      67             : #include "nsIAsyncVerifyRedirectCallback.h"
      68             : #include "nsIScriptSecurityManager.h"
      69             : #include "nsIScriptObjectPrincipal.h"
      70             : #include "nsIScrollableFrame.h"
      71             : #include "nsContentPolicyUtils.h" // NS_CheckContentLoadPolicy(...)
      72             : #include "nsISeekableStream.h"
      73             : #include "nsAutoPtr.h"
      74             : #include "nsQueryObject.h"
      75             : #include "nsIWritablePropertyBag2.h"
      76             : #include "nsIAppShell.h"
      77             : #include "nsWidgetsCID.h"
      78             : #include "nsIInterfaceRequestorUtils.h"
      79             : #include "nsView.h"
      80             : #include "nsViewManager.h"
      81             : #include "nsIScriptChannel.h"
      82             : #include "nsITimedChannel.h"
      83             : #include "nsIPrivacyTransitionObserver.h"
      84             : #include "nsIReflowObserver.h"
      85             : #include "nsIScrollObserver.h"
      86             : #include "nsIDocShellTreeItem.h"
      87             : #include "nsIChannel.h"
      88             : #include "IHistory.h"
      89             : #include "nsViewSourceHandler.h"
      90             : #include "nsWhitespaceTokenizer.h"
      91             : #include "nsICookieService.h"
      92             : #include "nsIConsoleReportCollector.h"
      93             : #include "nsObjectLoadingContent.h"
      94             : 
      95             : // we want to explore making the document own the load group
      96             : // so we can associate the document URI with the load group.
      97             : // until this point, we have an evil hack:
      98             : #include "nsIHttpChannelInternal.h"
      99             : #include "nsPILoadGroupInternal.h"
     100             : 
     101             : // Local Includes
     102             : #include "nsDocShellLoadInfo.h"
     103             : #include "nsCDefaultURIFixup.h"
     104             : #include "nsDocShellEnumerator.h"
     105             : #include "nsSHistory.h"
     106             : #include "nsDocShellEditorData.h"
     107             : #include "GeckoProfiler.h"
     108             : #include "timeline/JavascriptTimelineMarker.h"
     109             : 
     110             : // Helper Classes
     111             : #include "nsError.h"
     112             : #include "nsEscape.h"
     113             : 
     114             : // Interfaces Needed
     115             : #include "nsIFormPOSTActionChannel.h"
     116             : #include "nsIUploadChannel.h"
     117             : #include "nsIUploadChannel2.h"
     118             : #include "nsIWebProgress.h"
     119             : #include "nsILayoutHistoryState.h"
     120             : #include "nsITimer.h"
     121             : #include "nsISHistoryInternal.h"
     122             : #include "nsIPrincipal.h"
     123             : #include "NullPrincipal.h"
     124             : #include "nsISHEntry.h"
     125             : #include "nsIWindowWatcher.h"
     126             : #include "nsIPromptFactory.h"
     127             : #include "nsITransportSecurityInfo.h"
     128             : #include "nsINode.h"
     129             : #include "nsINSSErrorsService.h"
     130             : #include "nsIApplicationCacheChannel.h"
     131             : #include "nsIApplicationCacheContainer.h"
     132             : #include "nsStreamUtils.h"
     133             : #include "nsIController.h"
     134             : #include "nsPICommandUpdater.h"
     135             : #include "nsIDOMHTMLAnchorElement.h"
     136             : #include "nsIWebBrowserChrome3.h"
     137             : #include "nsITabChild.h"
     138             : #include "nsISiteSecurityService.h"
     139             : #include "nsStructuredCloneContainer.h"
     140             : #include "nsIStructuredCloneContainer.h"
     141             : #include "nsISupportsPrimitives.h"
     142             : #ifdef MOZ_PLACES
     143             : #include "nsIFaviconService.h"
     144             : #include "mozIPlacesPendingOperation.h"
     145             : #include "mozIAsyncFavicons.h"
     146             : #endif
     147             : #include "nsINetworkPredictor.h"
     148             : 
     149             : // Editor-related
     150             : #include "nsIEditingSession.h"
     151             : 
     152             : #include "nsPIDOMWindow.h"
     153             : #include "nsGlobalWindow.h"
     154             : #include "nsPIWindowRoot.h"
     155             : #include "nsICachingChannel.h"
     156             : #include "nsIMultiPartChannel.h"
     157             : #include "nsIWyciwygChannel.h"
     158             : 
     159             : // For reporting errors with the console service.
     160             : // These can go away if error reporting is propagated up past nsDocShell.
     161             : #include "nsIScriptError.h"
     162             : 
     163             : // used to dispatch urls to default protocol handlers
     164             : #include "nsCExternalHandlerService.h"
     165             : #include "nsIExternalProtocolService.h"
     166             : 
     167             : #include "nsFocusManager.h"
     168             : 
     169             : #include "nsITextToSubURI.h"
     170             : 
     171             : #include "nsIJARChannel.h"
     172             : 
     173             : #include "mozilla/Logging.h"
     174             : 
     175             : #include "nsISelectionDisplay.h"
     176             : 
     177             : #include "nsIGlobalHistory2.h"
     178             : 
     179             : #include "nsIFrame.h"
     180             : #include "nsSubDocumentFrame.h"
     181             : 
     182             : // for embedding
     183             : #include "nsIWebBrowserChromeFocus.h"
     184             : 
     185             : #if NS_PRINT_PREVIEW
     186             : #include "nsIDocumentViewerPrint.h"
     187             : #include "nsIWebBrowserPrint.h"
     188             : #endif
     189             : 
     190             : #include "nsContentUtils.h"
     191             : #include "nsIContentSecurityPolicy.h"
     192             : #include "nsILoadInfo.h"
     193             : #include "nsSandboxFlags.h"
     194             : #include "nsXULAppAPI.h"
     195             : #include "nsDOMNavigationTiming.h"
     196             : #include "nsISecurityUITelemetry.h"
     197             : #include "nsDSURIContentListener.h"
     198             : #include "nsDocShellLoadTypes.h"
     199             : #include "nsDocShellTransferableHooks.h"
     200             : #include "nsICommandManager.h"
     201             : #include "nsIDOMNode.h"
     202             : #include "nsIClassOfService.h"
     203             : #include "nsIDocShellTreeOwner.h"
     204             : #include "nsIHttpChannel.h"
     205             : #include "nsIIDNService.h"
     206             : #include "nsIInputStreamChannel.h"
     207             : #include "nsINestedURI.h"
     208             : #include "nsIOService.h"
     209             : #include "nsISHContainer.h"
     210             : #include "nsISHistory.h"
     211             : #include "nsISecureBrowserUI.h"
     212             : #include "nsISocketProvider.h"
     213             : #include "nsIStringBundle.h"
     214             : #include "nsIURIFixup.h"
     215             : #include "nsIURILoader.h"
     216             : #include "nsIURL.h"
     217             : #include "nsIWebBrowserFind.h"
     218             : #include "nsIWidget.h"
     219             : #include "mozilla/dom/PerformanceNavigation.h"
     220             : #include "mozilla/dom/ScriptSettings.h"
     221             : #include "mozilla/Encoding.h"
     222             : 
     223             : #ifdef MOZ_TOOLKIT_SEARCH
     224             : #include "nsIBrowserSearchService.h"
     225             : #endif
     226             : 
     227             : #include "mozIThirdPartyUtil.h"
     228             : 
     229             : static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID);
     230             : 
     231             : #if defined(DEBUG_bryner) || defined(DEBUG_chb)
     232             : //#define DEBUG_DOCSHELL_FOCUS
     233             : #define DEBUG_PAGE_CACHE
     234             : #endif
     235             : 
     236             : #ifdef XP_WIN
     237             : #include <process.h>
     238             : #define getpid _getpid
     239             : #else
     240             : #include <unistd.h> // for getpid()
     241             : #endif
     242             : 
     243             : using namespace mozilla;
     244             : using namespace mozilla::dom;
     245             : using mozilla::dom::workers::ServiceWorkerManager;
     246             : 
     247             : // True means sUseErrorPages has been added to
     248             : // preferences var cache.
     249             : static bool gAddedPreferencesVarCache = false;
     250             : 
     251             : bool nsDocShell::sUseErrorPages = false;
     252             : 
     253             : // Number of documents currently loading
     254             : static int32_t gNumberOfDocumentsLoading = 0;
     255             : 
     256             : // Global count of existing docshells.
     257             : static int32_t gDocShellCount = 0;
     258             : 
     259             : // Global count of docshells with the private attribute set
     260             : static uint32_t gNumberOfPrivateDocShells = 0;
     261             : 
     262             : // Global reference to the URI fixup service.
     263             : nsIURIFixup* nsDocShell::sURIFixup = 0;
     264             : 
     265             : // True means we validate window targets to prevent frameset
     266             : // spoofing. Initialize this to a non-bolean value so we know to check
     267             : // the pref on the creation of the first docshell.
     268             : static uint32_t gValidateOrigin = 0xffffffff;
     269             : 
     270             : // Hint for native dispatch of events on how long to delay after
     271             : // all documents have loaded in milliseconds before favoring normal
     272             : // native event dispatch priorites over performance
     273             : // Can be overridden with docshell.event_starvation_delay_hint pref.
     274             : #define NS_EVENT_STARVATION_DELAY_HINT 2000
     275             : 
     276             : #ifdef DEBUG
     277             : static mozilla::LazyLogModule gDocShellLog("nsDocShell");
     278             : #endif
     279             : static mozilla::LazyLogModule gDocShellLeakLog("nsDocShellLeak");;
     280             : 
     281             : const char kBrandBundleURL[]      = "chrome://branding/locale/brand.properties";
     282             : const char kAppstringsBundleURL[] = "chrome://global/locale/appstrings.properties";
     283             : 
     284             : static void
     285           4 : FavorPerformanceHint(bool aPerfOverStarvation)
     286             : {
     287           8 :   nsCOMPtr<nsIAppShell> appShell = do_GetService(kAppShellCID);
     288           4 :   if (appShell) {
     289           8 :     appShell->FavorPerformanceHint(
     290             :       aPerfOverStarvation,
     291             :       Preferences::GetUint("docshell.event_starvation_delay_hint",
     292           8 :                            NS_EVENT_STARVATION_DELAY_HINT));
     293             :   }
     294           4 : }
     295             : 
     296             : //*****************************************************************************
     297             : // <a ping> support
     298             : //*****************************************************************************
     299             : 
     300             : #define PREF_PINGS_ENABLED           "browser.send_pings"
     301             : #define PREF_PINGS_MAX_PER_LINK      "browser.send_pings.max_per_link"
     302             : #define PREF_PINGS_REQUIRE_SAME_HOST "browser.send_pings.require_same_host"
     303             : 
     304             : // Check prefs to see if pings are enabled and if so what restrictions might
     305             : // be applied.
     306             : //
     307             : // @param maxPerLink
     308             : //   This parameter returns the number of pings that are allowed per link click
     309             : //
     310             : // @param requireSameHost
     311             : //   This parameter returns true if pings are restricted to the same host as
     312             : //   the document in which the click occurs.  If the same host restriction is
     313             : //   imposed, then we still allow for pings to cross over to different
     314             : //   protocols and ports for flexibility and because it is not possible to send
     315             : //   a ping via FTP.
     316             : //
     317             : // @returns
     318             : //   true if pings are enabled and false otherwise.
     319             : //
     320             : static bool
     321           0 : PingsEnabled(int32_t* aMaxPerLink, bool* aRequireSameHost)
     322             : {
     323           0 :   bool allow = Preferences::GetBool(PREF_PINGS_ENABLED, false);
     324             : 
     325           0 :   *aMaxPerLink = 1;
     326           0 :   *aRequireSameHost = true;
     327             : 
     328           0 :   if (allow) {
     329           0 :     Preferences::GetInt(PREF_PINGS_MAX_PER_LINK, aMaxPerLink);
     330           0 :     Preferences::GetBool(PREF_PINGS_REQUIRE_SAME_HOST, aRequireSameHost);
     331             :   }
     332             : 
     333           0 :   return allow;
     334             : }
     335             : 
     336             : typedef void (*ForEachPingCallback)(void* closure, nsIContent* content,
     337             :                                     nsIURI* uri, nsIIOService* ios);
     338             : 
     339             : static bool
     340           0 : IsElementAnchor(nsIContent* aContent)
     341             : {
     342             :   // Make sure we are dealing with either an <A> or <AREA> element in the HTML
     343             :   // or XHTML namespace.
     344           0 :   return aContent->IsAnyOfHTMLElements(nsGkAtoms::a, nsGkAtoms::area);
     345             : }
     346             : 
     347             : static void
     348           0 : ForEachPing(nsIContent* aContent, ForEachPingCallback aCallback, void* aClosure)
     349             : {
     350             :   // NOTE: Using nsIDOMHTMLAnchorElement::GetPing isn't really worth it here
     351             :   //       since we'd still need to parse the resulting string.  Instead, we
     352             :   //       just parse the raw attribute.  It might be nice if the content node
     353             :   //       implemented an interface that exposed an enumeration of nsIURIs.
     354             : 
     355             :   // Make sure we are dealing with either an <A> or <AREA> element in the HTML
     356             :   // or XHTML namespace.
     357           0 :   if (!IsElementAnchor(aContent)) {
     358           0 :     return;
     359             :   }
     360             : 
     361           0 :   nsCOMPtr<nsIAtom> pingAtom = NS_Atomize("ping");
     362           0 :   if (!pingAtom) {
     363           0 :     return;
     364             :   }
     365             : 
     366           0 :   nsAutoString value;
     367           0 :   aContent->GetAttr(kNameSpaceID_None, pingAtom, value);
     368           0 :   if (value.IsEmpty()) {
     369           0 :     return;
     370             :   }
     371             : 
     372           0 :   nsCOMPtr<nsIIOService> ios = do_GetIOService();
     373           0 :   if (!ios) {
     374           0 :     return;
     375             :   }
     376             : 
     377           0 :   nsIDocument* doc = aContent->OwnerDoc();
     378           0 :   nsAutoCString charset;
     379           0 :   doc->GetDocumentCharacterSet()->Name(charset);
     380             : 
     381           0 :   nsWhitespaceTokenizer tokenizer(value);
     382             : 
     383           0 :   while (tokenizer.hasMoreTokens()) {
     384           0 :     nsCOMPtr<nsIURI> uri, baseURI = aContent->GetBaseURI();
     385           0 :     ios->NewURI(NS_ConvertUTF16toUTF8(tokenizer.nextToken()),
     386           0 :                 charset.get(), baseURI, getter_AddRefs(uri));
     387             :     // if we can't generate a valid URI, then there is nothing to do
     388           0 :     if (!uri) {
     389           0 :       continue;
     390             :     }
     391             :     // Explicitly not allow loading data: URIs
     392             :     bool isDataScheme =
     393           0 :       (NS_SUCCEEDED(uri->SchemeIs("data", &isDataScheme)) && isDataScheme);
     394             : 
     395           0 :     if (!isDataScheme) {
     396           0 :       aCallback(aClosure, aContent, uri, ios);
     397             :     }
     398             :   }
     399             : }
     400             : 
     401             : //----------------------------------------------------------------------
     402             : 
     403             : // We wait this many milliseconds before killing the ping channel...
     404             : #define PING_TIMEOUT 10000
     405             : 
     406             : static void
     407           0 : OnPingTimeout(nsITimer* aTimer, void* aClosure)
     408             : {
     409           0 :   nsILoadGroup* loadGroup = static_cast<nsILoadGroup*>(aClosure);
     410           0 :   if (loadGroup) {
     411           0 :     loadGroup->Cancel(NS_ERROR_ABORT);
     412             :   }
     413           0 : }
     414             : 
     415             : class nsPingListener final
     416             :   : public nsIStreamListener
     417             : {
     418             : public:
     419             :   NS_DECL_ISUPPORTS
     420             :   NS_DECL_NSIREQUESTOBSERVER
     421             :   NS_DECL_NSISTREAMLISTENER
     422             : 
     423           0 :   nsPingListener()
     424           0 :   {
     425           0 :   }
     426             : 
     427           0 :   void SetLoadGroup(nsILoadGroup* aLoadGroup) {
     428           0 :     mLoadGroup = aLoadGroup;
     429           0 :   }
     430             : 
     431             :   nsresult StartTimeout(DocGroup* aDocGroup);
     432             : 
     433             : private:
     434             :   ~nsPingListener();
     435             : 
     436             :   nsCOMPtr<nsILoadGroup> mLoadGroup;
     437             :   nsCOMPtr<nsITimer> mTimer;
     438             : };
     439             : 
     440           0 : NS_IMPL_ISUPPORTS(nsPingListener, nsIStreamListener, nsIRequestObserver)
     441             : 
     442           0 : nsPingListener::~nsPingListener()
     443             : {
     444           0 :   if (mTimer) {
     445           0 :     mTimer->Cancel();
     446           0 :     mTimer = nullptr;
     447             :   }
     448           0 : }
     449             : 
     450             : nsresult
     451           0 : nsPingListener::StartTimeout(DocGroup* aDocGroup)
     452             : {
     453           0 :   NS_ENSURE_ARG(aDocGroup);
     454             : 
     455           0 :   nsCOMPtr<nsITimer> timer = do_CreateInstance(NS_TIMER_CONTRACTID);
     456           0 :   timer->SetTarget(aDocGroup->EventTargetFor(TaskCategory::Network));
     457             : 
     458           0 :   if (timer) {
     459             :     nsresult rv =
     460           0 :       timer->InitWithNamedFuncCallback(OnPingTimeout,
     461             :                                        mLoadGroup,
     462             :                                        PING_TIMEOUT,
     463             :                                        nsITimer::TYPE_ONE_SHOT,
     464           0 :                                        "nsPingListener::StartTimeout");
     465           0 :     if (NS_SUCCEEDED(rv)) {
     466           0 :       mTimer = timer;
     467           0 :       return NS_OK;
     468             :     }
     469             :   }
     470             : 
     471           0 :   return NS_ERROR_OUT_OF_MEMORY;
     472             : }
     473             : 
     474             : NS_IMETHODIMP
     475           0 : nsPingListener::OnStartRequest(nsIRequest* aRequest, nsISupports* aContext)
     476             : {
     477           0 :   return NS_OK;
     478             : }
     479             : 
     480             : NS_IMETHODIMP
     481           0 : nsPingListener::OnDataAvailable(nsIRequest* aRequest, nsISupports* aContext,
     482             :                                 nsIInputStream* aStream, uint64_t aOffset,
     483             :                                 uint32_t aCount)
     484             : {
     485             :   uint32_t result;
     486           0 :   return aStream->ReadSegments(NS_DiscardSegment, nullptr, aCount, &result);
     487             : }
     488             : 
     489             : NS_IMETHODIMP
     490           0 : nsPingListener::OnStopRequest(nsIRequest* aRequest, nsISupports* aContext,
     491             :                               nsresult aStatus)
     492             : {
     493           0 :   mLoadGroup = nullptr;
     494             : 
     495           0 :   if (mTimer) {
     496           0 :     mTimer->Cancel();
     497           0 :     mTimer = nullptr;
     498             :   }
     499             : 
     500           0 :   return NS_OK;
     501             : }
     502             : 
     503             : struct MOZ_STACK_CLASS SendPingInfo
     504             : {
     505             :   int32_t numPings;
     506             :   int32_t maxPings;
     507             :   bool requireSameHost;
     508             :   nsIURI* target;
     509             :   nsIURI* referrer;
     510             :   nsIDocShell* docShell;
     511             :   uint32_t referrerPolicy;
     512             : };
     513             : 
     514             : static void
     515           0 : SendPing(void* aClosure, nsIContent* aContent, nsIURI* aURI,
     516             :          nsIIOService* aIOService)
     517             : {
     518           0 :   SendPingInfo* info = static_cast<SendPingInfo*>(aClosure);
     519           0 :   if (info->maxPings > -1 && info->numPings >= info->maxPings) {
     520           0 :     return;
     521             :   }
     522             : 
     523           0 :   nsIDocument* doc = aContent->OwnerDoc();
     524             : 
     525           0 :   nsCOMPtr<nsIChannel> chan;
     526           0 :   NS_NewChannel(getter_AddRefs(chan),
     527             :                 aURI,
     528             :                 doc,
     529           0 :                 info->requireSameHost
     530             :                   ? nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_IS_BLOCKED
     531             :                   : nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
     532             :                 nsIContentPolicy::TYPE_PING,
     533             :                 nullptr, // aLoadGroup
     534             :                 nullptr, // aCallbacks
     535             :                 nsIRequest::LOAD_NORMAL, // aLoadFlags,
     536           0 :                 aIOService);
     537             : 
     538           0 :   if (!chan) {
     539           0 :     return;
     540             :   }
     541             : 
     542             :   // Don't bother caching the result of this URI load, but do not exempt
     543             :   // it from Safe Browsing.
     544           0 :   chan->SetLoadFlags(nsIRequest::INHIBIT_CACHING | nsIChannel::LOAD_CLASSIFY_URI);
     545             : 
     546           0 :   nsCOMPtr<nsIHttpChannel> httpChan = do_QueryInterface(chan);
     547           0 :   if (!httpChan) {
     548           0 :     return;
     549             :   }
     550             : 
     551             :   // This is needed in order for 3rd-party cookie blocking to work.
     552           0 :   nsCOMPtr<nsIHttpChannelInternal> httpInternal = do_QueryInterface(httpChan);
     553             :   nsresult rv;
     554           0 :   if (httpInternal) {
     555           0 :     rv = httpInternal->SetDocumentURI(doc->GetDocumentURI());
     556           0 :     MOZ_ASSERT(NS_SUCCEEDED(rv));
     557             :   }
     558             : 
     559           0 :   rv = httpChan->SetRequestMethod(NS_LITERAL_CSTRING("POST"));
     560           0 :   MOZ_ASSERT(NS_SUCCEEDED(rv));
     561             : 
     562             :   // Remove extraneous request headers (to reduce request size)
     563           0 :   rv = httpChan->SetRequestHeader(NS_LITERAL_CSTRING("accept"),
     564           0 :                                   EmptyCString(), false);
     565           0 :   MOZ_ASSERT(NS_SUCCEEDED(rv));
     566           0 :   rv = httpChan->SetRequestHeader(NS_LITERAL_CSTRING("accept-language"),
     567           0 :                                   EmptyCString(), false);
     568           0 :   MOZ_ASSERT(NS_SUCCEEDED(rv));
     569           0 :   rv = httpChan->SetRequestHeader(NS_LITERAL_CSTRING("accept-encoding"),
     570           0 :                                   EmptyCString(), false);
     571           0 :   MOZ_ASSERT(NS_SUCCEEDED(rv));
     572             : 
     573             :   // Always send a Ping-To header.
     574           0 :   nsAutoCString pingTo;
     575           0 :   if (NS_SUCCEEDED(info->target->GetSpec(pingTo))) {
     576           0 :     rv = httpChan->SetRequestHeader(NS_LITERAL_CSTRING("Ping-To"), pingTo, false);
     577           0 :     MOZ_ASSERT(NS_SUCCEEDED(rv));
     578             :   }
     579             : 
     580             :   nsCOMPtr<nsIScriptSecurityManager> sm =
     581           0 :     do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID);
     582             : 
     583           0 :   if (sm && info->referrer) {
     584             :     bool referrerIsSecure;
     585           0 :     uint32_t flags = nsIProtocolHandler::URI_SAFE_TO_LOAD_IN_SECURE_CONTEXT;
     586           0 :     rv = NS_URIChainHasFlags(info->referrer, flags, &referrerIsSecure);
     587             : 
     588             :     // Default to sending less data if NS_URIChainHasFlags() fails.
     589           0 :     referrerIsSecure = NS_FAILED(rv) || referrerIsSecure;
     590             : 
     591             :     bool sameOrigin =
     592           0 :       NS_SUCCEEDED(sm->CheckSameOriginURI(info->referrer, aURI, false));
     593             : 
     594             :     // If both the address of the document containing the hyperlink being
     595             :     // audited and "ping URL" have the same origin or the document containing
     596             :     // the hyperlink being audited was not retrieved over an encrypted
     597             :     // connection, send a Ping-From header.
     598           0 :     if (sameOrigin || !referrerIsSecure) {
     599           0 :       nsAutoCString pingFrom;
     600           0 :       if (NS_SUCCEEDED(info->referrer->GetSpec(pingFrom))) {
     601           0 :         rv = httpChan->SetRequestHeader(NS_LITERAL_CSTRING("Ping-From"),
     602           0 :                                         pingFrom, false);
     603           0 :         MOZ_ASSERT(NS_SUCCEEDED(rv));
     604             :       }
     605             :     }
     606             : 
     607             :     // If the document containing the hyperlink being audited was not retrieved
     608             :     // over an encrypted connection and its address does not have the same
     609             :     // origin as "ping URL", send a referrer.
     610           0 :     if (!sameOrigin && !referrerIsSecure) {
     611           0 :       rv = httpChan->SetReferrerWithPolicy(info->referrer, info->referrerPolicy);
     612           0 :       MOZ_ASSERT(NS_SUCCEEDED(rv));
     613             :     }
     614             :   }
     615             : 
     616           0 :   nsCOMPtr<nsIUploadChannel2> uploadChan = do_QueryInterface(httpChan);
     617           0 :   if (!uploadChan) {
     618           0 :     return;
     619             :   }
     620             : 
     621           0 :   NS_NAMED_LITERAL_CSTRING(uploadData, "PING");
     622             : 
     623           0 :   nsCOMPtr<nsIInputStream> uploadStream;
     624           0 :   NS_NewPostDataStream(getter_AddRefs(uploadStream), false, uploadData);
     625           0 :   if (!uploadStream) {
     626           0 :     return;
     627             :   }
     628             : 
     629           0 :   uploadChan->ExplicitSetUploadStream(uploadStream,
     630           0 :                                       NS_LITERAL_CSTRING("text/ping"),
     631           0 :                                       uploadData.Length(),
     632           0 :                                       NS_LITERAL_CSTRING("POST"), false);
     633             : 
     634             :   // The channel needs to have a loadgroup associated with it, so that we can
     635             :   // cancel the channel and any redirected channels it may create.
     636           0 :   nsCOMPtr<nsILoadGroup> loadGroup = do_CreateInstance(NS_LOADGROUP_CONTRACTID);
     637           0 :   if (!loadGroup) {
     638           0 :     return;
     639             :   }
     640           0 :   nsCOMPtr<nsIInterfaceRequestor> callbacks = do_QueryInterface(info->docShell);
     641           0 :   loadGroup->SetNotificationCallbacks(callbacks);
     642           0 :   chan->SetLoadGroup(loadGroup);
     643             : 
     644           0 :   RefPtr<nsPingListener> pingListener = new nsPingListener();
     645           0 :   chan->AsyncOpen2(pingListener);
     646             : 
     647             :   // Even if AsyncOpen failed, we still count this as a successful ping.  It's
     648             :   // possible that AsyncOpen may have failed after triggering some background
     649             :   // process that may have written something to the network.
     650           0 :   info->numPings++;
     651             : 
     652             :   // Prevent ping requests from stalling and never being garbage collected...
     653           0 :   if (NS_FAILED(pingListener->StartTimeout(doc->GetDocGroup()))) {
     654             :     // If we failed to setup the timer, then we should just cancel the channel
     655             :     // because we won't be able to ensure that it goes away in a timely manner.
     656           0 :     chan->Cancel(NS_ERROR_ABORT);
     657           0 :     return;
     658             :   }
     659             :   // if the channel openend successfully, then make the pingListener hold
     660             :   // a strong reference to the loadgroup which is released in ::OnStopRequest
     661           0 :   pingListener->SetLoadGroup(loadGroup);
     662             : }
     663             : 
     664             : // Spec: http://whatwg.org/specs/web-apps/current-work/#ping
     665             : static void
     666           0 : DispatchPings(nsIDocShell* aDocShell,
     667             :               nsIContent* aContent,
     668             :               nsIURI* aTarget,
     669             :               nsIURI* aReferrer,
     670             :               uint32_t aReferrerPolicy)
     671             : {
     672             :   SendPingInfo info;
     673             : 
     674           0 :   if (!PingsEnabled(&info.maxPings, &info.requireSameHost)) {
     675           0 :     return;
     676             :   }
     677           0 :   if (info.maxPings == 0) {
     678           0 :     return;
     679             :   }
     680             : 
     681           0 :   info.numPings = 0;
     682           0 :   info.target = aTarget;
     683           0 :   info.referrer = aReferrer;
     684           0 :   info.referrerPolicy = aReferrerPolicy;
     685           0 :   info.docShell = aDocShell;
     686             : 
     687           0 :   ForEachPing(aContent, SendPing, &info);
     688             : }
     689             : 
     690             : static nsDOMNavigationTiming::Type
     691           6 : ConvertLoadTypeToNavigationType(uint32_t aLoadType)
     692             : {
     693             :   // Not initialized, assume it's normal load.
     694           6 :   if (aLoadType == 0) {
     695           0 :     aLoadType = LOAD_NORMAL;
     696             :   }
     697             : 
     698           6 :   auto result = nsDOMNavigationTiming::TYPE_RESERVED;
     699           6 :   switch (aLoadType) {
     700             :     case LOAD_NORMAL:
     701             :     case LOAD_NORMAL_EXTERNAL:
     702             :     case LOAD_NORMAL_BYPASS_CACHE:
     703             :     case LOAD_NORMAL_BYPASS_PROXY:
     704             :     case LOAD_NORMAL_BYPASS_PROXY_AND_CACHE:
     705             :     case LOAD_NORMAL_REPLACE:
     706             :     case LOAD_NORMAL_ALLOW_MIXED_CONTENT:
     707             :     case LOAD_LINK:
     708             :     case LOAD_STOP_CONTENT:
     709             :     case LOAD_REPLACE_BYPASS_CACHE:
     710           6 :       result = nsDOMNavigationTiming::TYPE_NAVIGATE;
     711           6 :       break;
     712             :     case LOAD_HISTORY:
     713           0 :       result = nsDOMNavigationTiming::TYPE_BACK_FORWARD;
     714           0 :       break;
     715             :     case LOAD_RELOAD_NORMAL:
     716             :     case LOAD_RELOAD_CHARSET_CHANGE:
     717             :     case LOAD_RELOAD_BYPASS_CACHE:
     718             :     case LOAD_RELOAD_BYPASS_PROXY:
     719             :     case LOAD_RELOAD_BYPASS_PROXY_AND_CACHE:
     720             :     case LOAD_RELOAD_ALLOW_MIXED_CONTENT:
     721           0 :       result = nsDOMNavigationTiming::TYPE_RELOAD;
     722           0 :       break;
     723             :     case LOAD_STOP_CONTENT_AND_REPLACE:
     724             :     case LOAD_REFRESH:
     725             :     case LOAD_BYPASS_HISTORY:
     726             :     case LOAD_ERROR_PAGE:
     727             :     case LOAD_PUSHSTATE:
     728           0 :       result = nsDOMNavigationTiming::TYPE_RESERVED;
     729           0 :       break;
     730             :     default:
     731             :       // NS_NOTREACHED("Unexpected load type value");
     732           0 :       result = nsDOMNavigationTiming::TYPE_RESERVED;
     733           0 :       break;
     734             :   }
     735             : 
     736           6 :   return result;
     737             : }
     738             : 
     739             : static nsISHEntry* GetRootSHEntry(nsISHEntry* aEntry);
     740             : 
     741             : static void
     742           0 : IncreasePrivateDocShellCount()
     743             : {
     744           0 :   gNumberOfPrivateDocShells++;
     745           0 :   if (gNumberOfPrivateDocShells > 1 ||
     746           0 :       !XRE_IsContentProcess()) {
     747           0 :     return;
     748             :   }
     749             : 
     750           0 :   mozilla::dom::ContentChild* cc = mozilla::dom::ContentChild::GetSingleton();
     751           0 :   cc->SendPrivateDocShellsExist(true);
     752             : }
     753             : 
     754             : static void
     755           0 : DecreasePrivateDocShellCount()
     756             : {
     757           0 :   MOZ_ASSERT(gNumberOfPrivateDocShells > 0);
     758           0 :   gNumberOfPrivateDocShells--;
     759           0 :   if (!gNumberOfPrivateDocShells) {
     760           0 :     if (XRE_IsContentProcess()) {
     761           0 :       dom::ContentChild* cc = dom::ContentChild::GetSingleton();
     762           0 :       cc->SendPrivateDocShellsExist(false);
     763           0 :       return;
     764             :     }
     765             : 
     766           0 :     nsCOMPtr<nsIObserverService> obsvc = services::GetObserverService();
     767           0 :     if (obsvc) {
     768           0 :       obsvc->NotifyObservers(nullptr, "last-pb-context-exited", nullptr);
     769             :     }
     770             :   }
     771             : }
     772             : 
     773           5 : nsDocShell::nsDocShell()
     774             :   : nsDocLoader()
     775             :   , mDefaultScrollbarPref(Scrollbar_Auto, Scrollbar_Auto)
     776             :   , mReferrerPolicy(0)
     777             :   , mFailedLoadType(0)
     778             :   , mTreeOwner(nullptr)
     779             :   , mChromeEventHandler(nullptr)
     780             :   , mCharsetReloadState(eCharsetReloadInit)
     781             :   , mChildOffset(0)
     782             :   , mBusyFlags(BUSY_FLAGS_NONE)
     783             :   , mAppType(nsIDocShell::APP_TYPE_UNKNOWN)
     784             :   , mLoadType(0)
     785             :   , mMarginWidth(-1)
     786             :   , mMarginHeight(-1)
     787             :   , mItemType(typeContent)
     788             :   , mPreviousTransIndex(-1)
     789             :   , mLoadedTransIndex(-1)
     790             :   , mSandboxFlags(0)
     791             :   , mOrientationLock(eScreenOrientation_None)
     792             :   , mFullscreenAllowed(CHECK_ATTRIBUTES)
     793             :   , mCreated(false)
     794             :   , mAllowSubframes(true)
     795             :   , mAllowPlugins(true)
     796             :   , mAllowJavascript(true)
     797             :   , mAllowMetaRedirects(true)
     798             :   , mAllowImages(true)
     799             :   , mAllowMedia(true)
     800             :   , mAllowDNSPrefetch(true)
     801             :   , mAllowWindowControl(true)
     802             :   , mAllowContentRetargeting(true)
     803             :   , mAllowContentRetargetingOnChildren(true)
     804             :   , mUseErrorPages(false)
     805             :   , mObserveErrorPages(true)
     806             :   , mAllowAuth(true)
     807             :   , mAllowKeywordFixup(false)
     808             :   , mIsOffScreenBrowser(false)
     809             :   , mIsActive(true)
     810             :   , mDisableMetaRefreshWhenInactive(false)
     811             :   , mIsPrerendered(false)
     812             :   , mIsAppTab(false)
     813             :   , mUseGlobalHistory(false)
     814             :   , mUseRemoteTabs(false)
     815             :   , mUseTrackingProtection(false)
     816             :   , mDeviceSizeIsPageSize(false)
     817             :   , mWindowDraggingAllowed(false)
     818             :   , mInFrameSwap(false)
     819             :   , mInheritPrivateBrowsingId(true)
     820             :   , mCanExecuteScripts(false)
     821             :   , mFiredUnloadEvent(false)
     822             :   , mEODForCurrentDocument(false)
     823             :   , mURIResultedInDocument(false)
     824             :   , mIsBeingDestroyed(false)
     825             :   , mIsExecutingOnLoadHandler(false)
     826             :   , mIsPrintingOrPP(false)
     827             :   , mSavingOldViewer(false)
     828             :   , mDynamicallyCreated(false)
     829             :   , mAffectPrivateSessionLifetime(true)
     830             :   , mInvisible(false)
     831             :   , mHasLoadedNonBlankURI(false)
     832             :   , mBlankTiming(false)
     833             :   , mCreatingDocument(false)
     834             : #ifdef DEBUG
     835             :   , mInEnsureScriptEnv(false)
     836             : #endif
     837             :   , mDefaultLoadFlags(nsIRequest::LOAD_NORMAL)
     838             :   , mFrameType(FRAME_TYPE_REGULAR)
     839             :   , mPrivateBrowsingId(0)
     840             :   , mForcedCharset(nullptr)
     841             :   , mParentCharset(nullptr)
     842             :   , mParentCharsetSource(0)
     843             :   , mJSRunToCompletionDepth(0)
     844           5 :   , mTouchEventsOverride(nsIDocShell::TOUCHEVENTS_OVERRIDE_NONE)
     845             : {
     846           5 :   AssertOriginAttributesMatchPrivateBrowsing();
     847             : 
     848           5 :   nsContentUtils::GenerateUUIDInPlace(mHistoryID);
     849             : 
     850           5 :   if (gDocShellCount++ == 0) {
     851           2 :     NS_ASSERTION(sURIFixup == nullptr,
     852             :                  "Huh, sURIFixup not null in first nsDocShell ctor!");
     853             : 
     854           2 :     CallGetService(NS_URIFIXUP_CONTRACTID, &sURIFixup);
     855             :   }
     856             : 
     857           5 :   MOZ_LOG(gDocShellLeakLog, LogLevel::Debug, ("DOCSHELL %p created\n", this));
     858             : 
     859             : #ifdef DEBUG
     860             :   // We're counting the number of |nsDocShells| to help find leaks
     861           5 :   ++gNumberOfDocShells;
     862           5 :   if (!PR_GetEnv("MOZ_QUIET")) {
     863           5 :     printf_stderr("++DOCSHELL %p == %ld [pid = %d] [id = %s]\n",
     864             :                   (void*)this,
     865             :                   gNumberOfDocShells,
     866             :                   getpid(),
     867          10 :                   nsIDToCString(mHistoryID).get());
     868             :   }
     869             : #endif
     870           5 : }
     871             : 
     872           0 : nsDocShell::~nsDocShell()
     873             : {
     874           0 :   MOZ_ASSERT(!mObserved);
     875             : 
     876           0 :   Destroy();
     877             : 
     878           0 :   nsCOMPtr<nsISHistoryInternal> shPrivate(do_QueryInterface(mSessionHistory));
     879           0 :   if (shPrivate) {
     880           0 :     shPrivate->SetRootDocShell(nullptr);
     881             :   }
     882             : 
     883           0 :   if (--gDocShellCount == 0) {
     884           0 :     NS_IF_RELEASE(sURIFixup);
     885             :   }
     886             : 
     887           0 :   MOZ_LOG(gDocShellLeakLog, LogLevel::Debug, ("DOCSHELL %p destroyed\n", this));
     888             : 
     889             : #ifdef DEBUG
     890             :   // We're counting the number of |nsDocShells| to help find leaks
     891           0 :   --gNumberOfDocShells;
     892           0 :   if (!PR_GetEnv("MOZ_QUIET")) {
     893           0 :     printf_stderr("--DOCSHELL %p == %ld [pid = %d] [id = %s]\n",
     894             :                   (void*)this,
     895             :                   gNumberOfDocShells,
     896             :                   getpid(),
     897           0 :                   nsIDToCString(mHistoryID).get());
     898             :   }
     899             : #endif
     900           0 : }
     901             : 
     902             : nsresult
     903           5 : nsDocShell::Init()
     904             : {
     905           5 :   nsresult rv = nsDocLoader::Init();
     906           5 :   NS_ENSURE_SUCCESS(rv, rv);
     907             : 
     908           5 :   NS_ASSERTION(mLoadGroup, "Something went wrong!");
     909             : 
     910           5 :   mContentListener = new nsDSURIContentListener(this);
     911           5 :   rv = mContentListener->Init();
     912           5 :   NS_ENSURE_SUCCESS(rv, rv);
     913             : 
     914             :   // We want to hold a strong ref to the loadgroup, so it better hold a weak
     915             :   // ref to us...  use an InterfaceRequestorProxy to do this.
     916             :   nsCOMPtr<nsIInterfaceRequestor> proxy =
     917          10 :     new InterfaceRequestorProxy(static_cast<nsIInterfaceRequestor*>(this));
     918           5 :   mLoadGroup->SetNotificationCallbacks(proxy);
     919             : 
     920           5 :   rv = nsDocLoader::AddDocLoaderAsChildOfRoot(this);
     921           5 :   NS_ENSURE_SUCCESS(rv, rv);
     922             : 
     923             :   // Add as |this| a progress listener to itself.  A little weird, but
     924             :   // simpler than reproducing all the listener-notification logic in
     925             :   // overrides of the various methods via which nsDocLoader can be
     926             :   // notified.   Note that this holds an nsWeakPtr to ourselves, so it's ok.
     927          10 :   return AddProgressListener(this, nsIWebProgress::NOTIFY_STATE_DOCUMENT |
     928          10 :                                      nsIWebProgress::NOTIFY_STATE_NETWORK);
     929             : }
     930             : 
     931             : void
     932           9 : nsDocShell::DestroyChildren()
     933             : {
     934          18 :   nsCOMPtr<nsIDocShellTreeItem> shell;
     935          18 :   nsTObserverArray<nsDocLoader*>::ForwardIterator iter(mChildList);
     936           9 :   while (iter.HasMore()) {
     937           0 :     shell = do_QueryObject(iter.GetNext());
     938           0 :     NS_ASSERTION(shell, "docshell has null child");
     939             : 
     940           0 :     if (shell) {
     941           0 :       shell->SetTreeOwner(nullptr);
     942             :     }
     943             :   }
     944             : 
     945           9 :   nsDocLoader::DestroyChildren();
     946           9 : }
     947             : 
     948        6958 : NS_IMPL_ADDREF_INHERITED(nsDocShell, nsDocLoader)
     949        6885 : NS_IMPL_RELEASE_INHERITED(nsDocShell, nsDocLoader)
     950             : 
     951        6011 : NS_INTERFACE_MAP_BEGIN(nsDocShell)
     952        6011 :   NS_INTERFACE_MAP_ENTRY(nsIDocShell)
     953        5171 :   NS_INTERFACE_MAP_ENTRY(nsIDocShellTreeItem)
     954        4584 :   NS_INTERFACE_MAP_ENTRY(nsIWebNavigation)
     955        4110 :   NS_INTERFACE_MAP_ENTRY(nsIBaseWindow)
     956        4037 :   NS_INTERFACE_MAP_ENTRY(nsIScrollable)
     957        3985 :   NS_INTERFACE_MAP_ENTRY(nsITextScroll)
     958        3984 :   NS_INTERFACE_MAP_ENTRY(nsIDocCharset)
     959        3984 :   NS_INTERFACE_MAP_ENTRY(nsIRefreshURI)
     960        3984 :   NS_INTERFACE_MAP_ENTRY(nsIWebProgressListener)
     961        3902 :   NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
     962        3882 :   NS_INTERFACE_MAP_ENTRY(nsIContentViewerContainer)
     963        3882 :   NS_INTERFACE_MAP_ENTRY(nsIWebPageDescriptor)
     964        3882 :   NS_INTERFACE_MAP_ENTRY(nsIAuthPromptProvider)
     965        3882 :   NS_INTERFACE_MAP_ENTRY(nsILoadContext)
     966        2565 :   NS_INTERFACE_MAP_ENTRY(nsIWebShellServices)
     967        2565 :   NS_INTERFACE_MAP_ENTRY(nsILinkHandler)
     968        2551 :   NS_INTERFACE_MAP_ENTRY(nsIClipboardCommands)
     969        2551 :   NS_INTERFACE_MAP_ENTRY(nsIDOMStorageManager)
     970        2549 :   NS_INTERFACE_MAP_ENTRY(nsINetworkInterceptController)
     971        2541 :   NS_INTERFACE_MAP_ENTRY(nsIDeprecationWarner)
     972        2541 : NS_INTERFACE_MAP_END_INHERITING(nsDocLoader)
     973             : 
     974             : NS_IMETHODIMP
     975         971 : nsDocShell::GetInterface(const nsIID& aIID, void** aSink)
     976             : {
     977         971 :   NS_PRECONDITION(aSink, "null out param");
     978             : 
     979         971 :   *aSink = nullptr;
     980             : 
     981         971 :   if (aIID.Equals(NS_GET_IID(nsICommandManager))) {
     982           0 :     NS_ENSURE_SUCCESS(EnsureCommandHandler(), NS_ERROR_FAILURE);
     983           0 :     *aSink = mCommandManager;
     984         971 :   } else if (aIID.Equals(NS_GET_IID(nsIURIContentListener))) {
     985          18 :     *aSink = mContentListener;
     986        2859 :   } else if ((aIID.Equals(NS_GET_IID(nsIScriptGlobalObject)) ||
     987        1906 :               aIID.Equals(NS_GET_IID(nsIGlobalObject)) ||
     988        1815 :               aIID.Equals(NS_GET_IID(nsPIDOMWindowOuter)) ||
     989        1628 :               aIID.Equals(NS_GET_IID(mozIDOMWindowProxy)) ||
     990        1530 :               aIID.Equals(NS_GET_IID(nsIDOMWindow)) ||
     991        1906 :               aIID.Equals(NS_GET_IID(nsIDOMWindowInternal))) &&
     992         189 :              NS_SUCCEEDED(EnsureScriptEnvironment())) {
     993         189 :     return mScriptGlobal->QueryInterface(aIID, aSink);
     994         770 :   } else if (aIID.Equals(NS_GET_IID(nsIDOMDocument)) &&
     995           6 :              NS_SUCCEEDED(EnsureContentViewer())) {
     996           6 :     mContentViewer->GetDOMDocument((nsIDOMDocument**)aSink);
     997           6 :     return *aSink ? NS_OK : NS_NOINTERFACE;
     998         758 :   } else if (aIID.Equals(NS_GET_IID(nsIDocument)) &&
     999           0 :              NS_SUCCEEDED(EnsureContentViewer())) {
    1000           0 :     nsCOMPtr<nsIDocument> doc = mContentViewer->GetDocument();
    1001           0 :     doc.forget(aSink);
    1002           0 :     return *aSink ? NS_OK : NS_NOINTERFACE;
    1003         758 :   } else if (aIID.Equals(NS_GET_IID(nsIApplicationCacheContainer))) {
    1004           3 :     *aSink = nullptr;
    1005             : 
    1006             :     // Return application cache associated with this docshell, if any
    1007             : 
    1008           6 :     nsCOMPtr<nsIContentViewer> contentViewer;
    1009           3 :     GetContentViewer(getter_AddRefs(contentViewer));
    1010           3 :     if (!contentViewer) {
    1011           0 :       return NS_ERROR_NO_INTERFACE;
    1012             :     }
    1013             : 
    1014           6 :     nsCOMPtr<nsIDOMDocument> domDoc;
    1015           3 :     contentViewer->GetDOMDocument(getter_AddRefs(domDoc));
    1016           3 :     NS_ASSERTION(domDoc, "Should have a document.");
    1017           3 :     if (!domDoc) {
    1018           0 :       return NS_ERROR_NO_INTERFACE;
    1019             :     }
    1020             : 
    1021             : #if defined(DEBUG)
    1022           3 :     MOZ_LOG(gDocShellLog, LogLevel::Debug,
    1023             :            ("nsDocShell[%p]: returning app cache container %p",
    1024             :             this, domDoc.get()));
    1025             : #endif
    1026           3 :     return domDoc->QueryInterface(aIID, aSink);
    1027         755 :   } else if (aIID.Equals(NS_GET_IID(nsIPrompt)) &&
    1028           0 :              NS_SUCCEEDED(EnsureScriptEnvironment())) {
    1029             :     nsresult rv;
    1030             :     nsCOMPtr<nsIWindowWatcher> wwatch =
    1031           0 :       do_GetService(NS_WINDOWWATCHER_CONTRACTID, &rv);
    1032           0 :     NS_ENSURE_SUCCESS(rv, rv);
    1033             : 
    1034             :     // Get the an auth prompter for our window so that the parenting
    1035             :     // of the dialogs works as it should when using tabs.
    1036             :     nsIPrompt* prompt;
    1037           0 :     rv = wwatch->GetNewPrompter(mScriptGlobal->AsOuter(), &prompt);
    1038           0 :     NS_ENSURE_SUCCESS(rv, rv);
    1039             : 
    1040           0 :     *aSink = prompt;
    1041           0 :     return NS_OK;
    1042        1510 :   } else if (aIID.Equals(NS_GET_IID(nsIAuthPrompt)) ||
    1043         755 :              aIID.Equals(NS_GET_IID(nsIAuthPrompt2))) {
    1044           0 :     return NS_SUCCEEDED(GetAuthPrompt(PROMPT_NORMAL, aIID, aSink)) ?
    1045           0 :       NS_OK : NS_NOINTERFACE;
    1046         755 :   } else if (aIID.Equals(NS_GET_IID(nsISHistory))) {
    1047           0 :     nsCOMPtr<nsISHistory> shistory;
    1048           0 :     nsresult rv = GetSessionHistory(getter_AddRefs(shistory));
    1049           0 :     if (NS_SUCCEEDED(rv) && shistory) {
    1050           0 :       shistory.forget(aSink);
    1051           0 :       return NS_OK;
    1052             :     }
    1053           0 :     return NS_NOINTERFACE;
    1054         755 :   } else if (aIID.Equals(NS_GET_IID(nsIWebBrowserFind))) {
    1055           0 :     nsresult rv = EnsureFind();
    1056           0 :     if (NS_FAILED(rv)) {
    1057           0 :       return rv;
    1058             :     }
    1059             : 
    1060           0 :     *aSink = mFind;
    1061           0 :     NS_ADDREF((nsISupports*)*aSink);
    1062           0 :     return NS_OK;
    1063         755 :   } else if (aIID.Equals(NS_GET_IID(nsIEditingSession))) {
    1064           0 :     nsCOMPtr<nsIEditingSession> es;
    1065           0 :     GetEditingSession(getter_AddRefs(es));
    1066           0 :     es.forget(aSink);
    1067           0 :     return *aSink ? NS_OK : NS_NOINTERFACE;
    1068         755 :   } else if (aIID.Equals(NS_GET_IID(nsIClipboardDragDropHookList)) &&
    1069           0 :              NS_SUCCEEDED(EnsureTransferableHookData())) {
    1070           0 :     *aSink = mTransferableHookData;
    1071           0 :     NS_ADDREF((nsISupports*)*aSink);
    1072           0 :     return NS_OK;
    1073         755 :   } else if (aIID.Equals(NS_GET_IID(nsISelectionDisplay))) {
    1074           0 :     nsIPresShell* shell = GetPresShell();
    1075           0 :     if (shell) {
    1076           0 :       return shell->QueryInterface(aIID, aSink);
    1077             :     }
    1078         755 :   } else if (aIID.Equals(NS_GET_IID(nsIDocShellTreeOwner))) {
    1079           1 :     nsCOMPtr<nsIDocShellTreeOwner> treeOwner;
    1080           1 :     nsresult rv = GetTreeOwner(getter_AddRefs(treeOwner));
    1081           1 :     if (NS_SUCCEEDED(rv) && treeOwner) {
    1082           1 :       return treeOwner->QueryInterface(aIID, aSink);
    1083             :     }
    1084         754 :   } else if (aIID.Equals(NS_GET_IID(nsITabChild))) {
    1085           7 :     *aSink = GetTabChild().take();
    1086           7 :     return *aSink ? NS_OK : NS_ERROR_FAILURE;
    1087         747 :   } else if (aIID.Equals(NS_GET_IID(nsIContentFrameMessageManager))) {
    1088             :     nsCOMPtr<nsITabChild> tabChild =
    1089           6 :       do_GetInterface(static_cast<nsIDocShell*>(this));
    1090           6 :     nsCOMPtr<nsIContentFrameMessageManager> mm;
    1091           3 :     if (tabChild) {
    1092           3 :       tabChild->GetMessageManager(getter_AddRefs(mm));
    1093             :     } else {
    1094           0 :       if (nsPIDOMWindowOuter* win = GetWindow()) {
    1095           0 :         mm = do_QueryInterface(win->GetParentTarget());
    1096             :       }
    1097             :     }
    1098           3 :     *aSink = mm.get();
    1099             :   } else {
    1100         744 :     return nsDocLoader::GetInterface(aIID, aSink);
    1101             :   }
    1102             : 
    1103          21 :   NS_IF_ADDREF(((nsISupports*)*aSink));
    1104          21 :   return *aSink ? NS_OK : NS_NOINTERFACE;
    1105             : }
    1106             : 
    1107             : uint32_t
    1108           6 : nsDocShell::ConvertDocShellLoadInfoToLoadType(
    1109             :     nsDocShellInfoLoadType aDocShellLoadType)
    1110             : {
    1111           6 :   uint32_t loadType = LOAD_NORMAL;
    1112             : 
    1113           6 :   switch (aDocShellLoadType) {
    1114             :     case nsIDocShellLoadInfo::loadNormal:
    1115           6 :       loadType = LOAD_NORMAL;
    1116           6 :       break;
    1117             :     case nsIDocShellLoadInfo::loadNormalReplace:
    1118           0 :       loadType = LOAD_NORMAL_REPLACE;
    1119           0 :       break;
    1120             :     case nsIDocShellLoadInfo::loadNormalExternal:
    1121           0 :       loadType = LOAD_NORMAL_EXTERNAL;
    1122           0 :       break;
    1123             :     case nsIDocShellLoadInfo::loadHistory:
    1124           0 :       loadType = LOAD_HISTORY;
    1125           0 :       break;
    1126             :     case nsIDocShellLoadInfo::loadNormalBypassCache:
    1127           0 :       loadType = LOAD_NORMAL_BYPASS_CACHE;
    1128           0 :       break;
    1129             :     case nsIDocShellLoadInfo::loadNormalBypassProxy:
    1130           0 :       loadType = LOAD_NORMAL_BYPASS_PROXY;
    1131           0 :       break;
    1132             :     case nsIDocShellLoadInfo::loadNormalBypassProxyAndCache:
    1133           0 :       loadType = LOAD_NORMAL_BYPASS_PROXY_AND_CACHE;
    1134           0 :       break;
    1135             :     case nsIDocShellLoadInfo::loadNormalAllowMixedContent:
    1136           0 :       loadType = LOAD_NORMAL_ALLOW_MIXED_CONTENT;
    1137           0 :       break;
    1138             :     case nsIDocShellLoadInfo::loadReloadNormal:
    1139           0 :       loadType = LOAD_RELOAD_NORMAL;
    1140           0 :       break;
    1141             :     case nsIDocShellLoadInfo::loadReloadCharsetChange:
    1142           0 :       loadType = LOAD_RELOAD_CHARSET_CHANGE;
    1143           0 :       break;
    1144             :     case nsIDocShellLoadInfo::loadReloadBypassCache:
    1145           0 :       loadType = LOAD_RELOAD_BYPASS_CACHE;
    1146           0 :       break;
    1147             :     case nsIDocShellLoadInfo::loadReloadBypassProxy:
    1148           0 :       loadType = LOAD_RELOAD_BYPASS_PROXY;
    1149           0 :       break;
    1150             :     case nsIDocShellLoadInfo::loadReloadBypassProxyAndCache:
    1151           0 :       loadType = LOAD_RELOAD_BYPASS_PROXY_AND_CACHE;
    1152           0 :       break;
    1153             :     case nsIDocShellLoadInfo::loadLink:
    1154           0 :       loadType = LOAD_LINK;
    1155           0 :       break;
    1156             :     case nsIDocShellLoadInfo::loadRefresh:
    1157           0 :       loadType = LOAD_REFRESH;
    1158           0 :       break;
    1159             :     case nsIDocShellLoadInfo::loadBypassHistory:
    1160           0 :       loadType = LOAD_BYPASS_HISTORY;
    1161           0 :       break;
    1162             :     case nsIDocShellLoadInfo::loadStopContent:
    1163           0 :       loadType = LOAD_STOP_CONTENT;
    1164           0 :       break;
    1165             :     case nsIDocShellLoadInfo::loadStopContentAndReplace:
    1166           0 :       loadType = LOAD_STOP_CONTENT_AND_REPLACE;
    1167           0 :       break;
    1168             :     case nsIDocShellLoadInfo::loadPushState:
    1169           0 :       loadType = LOAD_PUSHSTATE;
    1170           0 :       break;
    1171             :     case nsIDocShellLoadInfo::loadReplaceBypassCache:
    1172           0 :       loadType = LOAD_REPLACE_BYPASS_CACHE;
    1173           0 :       break;
    1174             :     case nsIDocShellLoadInfo::loadReloadMixedContent:
    1175           0 :       loadType = LOAD_RELOAD_ALLOW_MIXED_CONTENT;
    1176           0 :       break;
    1177             :     default:
    1178           0 :       NS_NOTREACHED("Unexpected nsDocShellInfoLoadType value");
    1179             :   }
    1180             : 
    1181           6 :   return loadType;
    1182             : }
    1183             : 
    1184             : nsDocShellInfoLoadType
    1185           3 : nsDocShell::ConvertLoadTypeToDocShellLoadInfo(uint32_t aLoadType)
    1186             : {
    1187           3 :   nsDocShellInfoLoadType docShellLoadType = nsIDocShellLoadInfo::loadNormal;
    1188           3 :   switch (aLoadType) {
    1189             :     case LOAD_NORMAL:
    1190           3 :       docShellLoadType = nsIDocShellLoadInfo::loadNormal;
    1191           3 :       break;
    1192             :     case LOAD_NORMAL_REPLACE:
    1193           0 :       docShellLoadType = nsIDocShellLoadInfo::loadNormalReplace;
    1194           0 :       break;
    1195             :     case LOAD_NORMAL_EXTERNAL:
    1196           0 :       docShellLoadType = nsIDocShellLoadInfo::loadNormalExternal;
    1197           0 :       break;
    1198             :     case LOAD_NORMAL_BYPASS_CACHE:
    1199           0 :       docShellLoadType = nsIDocShellLoadInfo::loadNormalBypassCache;
    1200           0 :       break;
    1201             :     case LOAD_NORMAL_BYPASS_PROXY:
    1202           0 :       docShellLoadType = nsIDocShellLoadInfo::loadNormalBypassProxy;
    1203           0 :       break;
    1204             :     case LOAD_NORMAL_BYPASS_PROXY_AND_CACHE:
    1205           0 :       docShellLoadType = nsIDocShellLoadInfo::loadNormalBypassProxyAndCache;
    1206           0 :       break;
    1207             :     case LOAD_NORMAL_ALLOW_MIXED_CONTENT:
    1208           0 :       docShellLoadType = nsIDocShellLoadInfo::loadNormalAllowMixedContent;
    1209           0 :       break;
    1210             :     case LOAD_HISTORY:
    1211           0 :       docShellLoadType = nsIDocShellLoadInfo::loadHistory;
    1212           0 :       break;
    1213             :     case LOAD_RELOAD_NORMAL:
    1214           0 :       docShellLoadType = nsIDocShellLoadInfo::loadReloadNormal;
    1215           0 :       break;
    1216             :     case LOAD_RELOAD_CHARSET_CHANGE:
    1217           0 :       docShellLoadType = nsIDocShellLoadInfo::loadReloadCharsetChange;
    1218           0 :       break;
    1219             :     case LOAD_RELOAD_BYPASS_CACHE:
    1220           0 :       docShellLoadType = nsIDocShellLoadInfo::loadReloadBypassCache;
    1221           0 :       break;
    1222             :     case LOAD_RELOAD_BYPASS_PROXY:
    1223           0 :       docShellLoadType = nsIDocShellLoadInfo::loadReloadBypassProxy;
    1224           0 :       break;
    1225             :     case LOAD_RELOAD_BYPASS_PROXY_AND_CACHE:
    1226           0 :       docShellLoadType = nsIDocShellLoadInfo::loadReloadBypassProxyAndCache;
    1227           0 :       break;
    1228             :     case LOAD_LINK:
    1229           0 :       docShellLoadType = nsIDocShellLoadInfo::loadLink;
    1230           0 :       break;
    1231             :     case LOAD_REFRESH:
    1232           0 :       docShellLoadType = nsIDocShellLoadInfo::loadRefresh;
    1233           0 :       break;
    1234             :     case LOAD_BYPASS_HISTORY:
    1235             :     case LOAD_ERROR_PAGE:
    1236           0 :       docShellLoadType = nsIDocShellLoadInfo::loadBypassHistory;
    1237           0 :       break;
    1238             :     case LOAD_STOP_CONTENT:
    1239           0 :       docShellLoadType = nsIDocShellLoadInfo::loadStopContent;
    1240           0 :       break;
    1241             :     case LOAD_STOP_CONTENT_AND_REPLACE:
    1242           0 :       docShellLoadType = nsIDocShellLoadInfo::loadStopContentAndReplace;
    1243           0 :       break;
    1244             :     case LOAD_PUSHSTATE:
    1245           0 :       docShellLoadType = nsIDocShellLoadInfo::loadPushState;
    1246           0 :       break;
    1247             :     case LOAD_REPLACE_BYPASS_CACHE:
    1248           0 :       docShellLoadType = nsIDocShellLoadInfo::loadReplaceBypassCache;
    1249           0 :       break;
    1250             :     case LOAD_RELOAD_ALLOW_MIXED_CONTENT:
    1251           0 :       docShellLoadType = nsIDocShellLoadInfo::loadReloadMixedContent;
    1252           0 :       break;
    1253             :     default:
    1254           0 :       NS_NOTREACHED("Unexpected load type value");
    1255             :   }
    1256             : 
    1257           3 :   return docShellLoadType;
    1258             : }
    1259             : 
    1260             : NS_IMETHODIMP
    1261           6 : nsDocShell::LoadURI(nsIURI* aURI,
    1262             :                     nsIDocShellLoadInfo* aLoadInfo,
    1263             :                     uint32_t aLoadFlags,
    1264             :                     bool aFirstParty)
    1265             : {
    1266           6 :   NS_PRECONDITION(aLoadInfo || (aLoadFlags & EXTRA_LOAD_FLAGS) == 0,
    1267             :                   "Unexpected flags");
    1268           6 :   NS_PRECONDITION((aLoadFlags & 0xf) == 0, "Should not have these flags set");
    1269             : 
    1270             :   // Note: we allow loads to get through here even if mFiredUnloadEvent is
    1271             :   // true; that case will get handled in LoadInternal or LoadHistoryEntry,
    1272             :   // so we pass false as the second parameter to IsNavigationAllowed.
    1273             :   // However, we don't allow the page to change location *in the middle of*
    1274             :   // firing beforeunload, so we do need to check if *beforeunload* is currently
    1275             :   // firing, so we call IsNavigationAllowed rather than just IsPrintingOrPP.
    1276           6 :   if (!IsNavigationAllowed(true, false)) {
    1277           0 :     return NS_OK; // JS may not handle returning of an error code
    1278             :   }
    1279             : 
    1280          12 :   nsCOMPtr<nsIURI> referrer;
    1281          12 :   nsCOMPtr<nsIURI> originalURI;
    1282          12 :   Maybe<nsCOMPtr<nsIURI>> resultPrincipalURI;
    1283           6 :   bool loadReplace = false;
    1284          12 :   nsCOMPtr<nsIInputStream> postStream;
    1285          12 :   nsCOMPtr<nsIInputStream> headersStream;
    1286          12 :   nsCOMPtr<nsIPrincipal> triggeringPrincipal;
    1287           6 :   bool inheritPrincipal = false;
    1288           6 :   bool principalIsExplicit = false;
    1289           6 :   bool sendReferrer = true;
    1290           6 :   uint32_t referrerPolicy = mozilla::net::RP_Unset;
    1291           6 :   bool isSrcdoc = false;
    1292          12 :   nsCOMPtr<nsISHEntry> shEntry;
    1293          12 :   nsXPIDLString target;
    1294          12 :   nsAutoString srcdoc;
    1295          12 :   nsCOMPtr<nsIDocShell> sourceDocShell;
    1296          12 :   nsCOMPtr<nsIURI> baseURI;
    1297             : 
    1298           6 :   uint32_t loadType = MAKE_LOAD_TYPE(LOAD_NORMAL, aLoadFlags);
    1299             : 
    1300           6 :   NS_ENSURE_ARG(aURI);
    1301             : 
    1302          18 :   if (!StartupTimeline::HasRecord(StartupTimeline::FIRST_LOAD_URI) &&
    1303           9 :       mItemType == typeContent && !NS_IsAboutBlank(aURI)) {
    1304           1 :     StartupTimeline::RecordOnce(StartupTimeline::FIRST_LOAD_URI);
    1305             :   }
    1306             : 
    1307             :   // Extract the info from the DocShellLoadInfo struct...
    1308           6 :   if (aLoadInfo) {
    1309           6 :     aLoadInfo->GetReferrer(getter_AddRefs(referrer));
    1310           6 :     aLoadInfo->GetOriginalURI(getter_AddRefs(originalURI));
    1311           6 :     GetMaybeResultPrincipalURI(aLoadInfo, resultPrincipalURI);
    1312           6 :     aLoadInfo->GetLoadReplace(&loadReplace);
    1313           6 :     nsDocShellInfoLoadType lt = nsIDocShellLoadInfo::loadNormal;
    1314           6 :     aLoadInfo->GetLoadType(&lt);
    1315             :     // Get the appropriate loadType from nsIDocShellLoadInfo type
    1316           6 :     loadType = ConvertDocShellLoadInfoToLoadType(lt);
    1317             : 
    1318           6 :     aLoadInfo->GetTriggeringPrincipal(getter_AddRefs(triggeringPrincipal));
    1319           6 :     aLoadInfo->GetInheritPrincipal(&inheritPrincipal);
    1320           6 :     aLoadInfo->GetPrincipalIsExplicit(&principalIsExplicit);
    1321           6 :     aLoadInfo->GetSHEntry(getter_AddRefs(shEntry));
    1322           6 :     aLoadInfo->GetTarget(getter_Copies(target));
    1323           6 :     aLoadInfo->GetPostDataStream(getter_AddRefs(postStream));
    1324           6 :     aLoadInfo->GetHeadersStream(getter_AddRefs(headersStream));
    1325           6 :     aLoadInfo->GetSendReferrer(&sendReferrer);
    1326           6 :     aLoadInfo->GetReferrerPolicy(&referrerPolicy);
    1327           6 :     aLoadInfo->GetIsSrcdocLoad(&isSrcdoc);
    1328           6 :     aLoadInfo->GetSrcdocData(srcdoc);
    1329           6 :     aLoadInfo->GetSourceDocShell(getter_AddRefs(sourceDocShell));
    1330           6 :     aLoadInfo->GetBaseURI(getter_AddRefs(baseURI));
    1331             :   }
    1332             : 
    1333           6 :   MOZ_LOG(gDocShellLeakLog, LogLevel::Debug,
    1334             :           ("nsDocShell[%p]: loading %s with flags 0x%08x",
    1335             :            this, aURI->GetSpecOrDefault().get(), aLoadFlags));
    1336             : 
    1337          12 :   if (!shEntry &&
    1338           6 :       !LOAD_TYPE_HAS_FLAGS(loadType, LOAD_FLAGS_REPLACE_HISTORY)) {
    1339             :     // First verify if this is a subframe.
    1340          12 :     nsCOMPtr<nsIDocShellTreeItem> parentAsItem;
    1341           6 :     GetSameTypeParent(getter_AddRefs(parentAsItem));
    1342          12 :     nsCOMPtr<nsIDocShell> parentDS(do_QueryInterface(parentAsItem));
    1343             :     uint32_t parentLoadType;
    1344             : 
    1345           6 :     if (parentDS && parentDS != static_cast<nsIDocShell*>(this)) {
    1346             :       /* OK. It is a subframe. Checkout the
    1347             :        * parent's loadtype. If the parent was loaded thro' a history
    1348             :        * mechanism, then get the SH entry for the child from the parent.
    1349             :        * This is done to restore frameset navigation while going back/forward.
    1350             :        * If the parent was loaded through any other loadType, set the
    1351             :        * child's loadType too accordingly, so that session history does not
    1352             :        * get confused.
    1353             :        */
    1354             : 
    1355             :       // Get the parent's load type
    1356           1 :       parentDS->GetLoadType(&parentLoadType);
    1357             : 
    1358             :       // Get the ShEntry for the child from the parent
    1359           2 :       nsCOMPtr<nsISHEntry> currentSH;
    1360           1 :       bool oshe = false;
    1361           1 :       parentDS->GetCurrentSHEntry(getter_AddRefs(currentSH), &oshe);
    1362           1 :       bool dynamicallyAddedChild = mDynamicallyCreated;
    1363           1 :       if (!dynamicallyAddedChild && !oshe && currentSH) {
    1364           0 :         currentSH->HasDynamicallyAddedChild(&dynamicallyAddedChild);
    1365             :       }
    1366           1 :       if (!dynamicallyAddedChild) {
    1367             :         // Only use the old SHEntry, if we're sure enough that
    1368             :         // it wasn't originally for some other frame.
    1369           0 :         parentDS->GetChildSHEntry(mChildOffset, getter_AddRefs(shEntry));
    1370             :       }
    1371             : 
    1372             :       // Make some decisions on the child frame's loadType based on the
    1373             :       // parent's loadType.
    1374           1 :       if (!mCurrentURI) {
    1375             :         // This is a newly created frame. Check for exception cases first.
    1376             :         // By default the subframe will inherit the parent's loadType.
    1377           1 :         if (shEntry && (parentLoadType == LOAD_NORMAL ||
    1378           0 :                         parentLoadType == LOAD_LINK   ||
    1379           1 :                         parentLoadType == LOAD_NORMAL_EXTERNAL)) {
    1380             :           // The parent was loaded normally. In this case, this *brand new*
    1381             :           // child really shouldn't have a SHEntry. If it does, it could be
    1382             :           // because the parent is replacing an existing frame with a new frame,
    1383             :           // in the onLoadHandler. We don't want this url to get into session
    1384             :           // history. Clear off shEntry, and set load type to
    1385             :           // LOAD_BYPASS_HISTORY.
    1386           0 :           bool inOnLoadHandler = false;
    1387           0 :           parentDS->GetIsExecutingOnLoadHandler(&inOnLoadHandler);
    1388           0 :           if (inOnLoadHandler) {
    1389           0 :             loadType = LOAD_NORMAL_REPLACE;
    1390           0 :             shEntry = nullptr;
    1391             :           }
    1392           1 :         } else if (parentLoadType == LOAD_REFRESH) {
    1393             :           // Clear shEntry. For refresh loads, we have to load
    1394             :           // what comes thro' the pipe, not what's in history.
    1395           0 :           shEntry = nullptr;
    1396           2 :         } else if ((parentLoadType == LOAD_BYPASS_HISTORY) ||
    1397           0 :                    (shEntry &&
    1398           0 :                     ((parentLoadType & LOAD_CMD_HISTORY) ||
    1399           0 :                      (parentLoadType == LOAD_RELOAD_NORMAL) ||
    1400           1 :                      (parentLoadType == LOAD_RELOAD_CHARSET_CHANGE)))) {
    1401             :           // If the parent url, bypassed history or was loaded from
    1402             :           // history, pass on the parent's loadType to the new child
    1403             :           // frame too, so that the child frame will also
    1404             :           // avoid getting into history.
    1405           0 :           loadType = parentLoadType;
    1406           1 :         } else if (parentLoadType == LOAD_ERROR_PAGE) {
    1407             :           // If the parent document is an error page, we don't
    1408             :           // want to update global/session history. However,
    1409             :           // this child frame is not an error page.
    1410           0 :           loadType = LOAD_BYPASS_HISTORY;
    1411           2 :         } else if ((parentLoadType == LOAD_RELOAD_BYPASS_CACHE) ||
    1412           2 :                    (parentLoadType == LOAD_RELOAD_BYPASS_PROXY) ||
    1413           1 :                    (parentLoadType == LOAD_RELOAD_BYPASS_PROXY_AND_CACHE)) {
    1414             :           // the new frame should inherit the parent's load type so that it also
    1415             :           // bypasses the cache and/or proxy
    1416           0 :           loadType = parentLoadType;
    1417             :         }
    1418             :       } else {
    1419             :         // This is a pre-existing subframe. If the load was not originally
    1420             :         // initiated by session history, (if (!shEntry) condition succeeded) and
    1421             :         // mCurrentURI is not null, it is possible that a parent's onLoadHandler
    1422             :         // or even self's onLoadHandler is loading a new page in this child.
    1423             :         // Check parent's and self's busy flag  and if it is set, we don't want
    1424             :         // this onLoadHandler load to get in to session history.
    1425           0 :         uint32_t parentBusy = BUSY_FLAGS_NONE;
    1426           0 :         uint32_t selfBusy = BUSY_FLAGS_NONE;
    1427           0 :         parentDS->GetBusyFlags(&parentBusy);
    1428           0 :         GetBusyFlags(&selfBusy);
    1429           0 :         if (parentBusy & BUSY_FLAGS_BUSY ||
    1430           0 :             selfBusy & BUSY_FLAGS_BUSY) {
    1431           0 :           loadType = LOAD_NORMAL_REPLACE;
    1432           0 :           shEntry = nullptr;
    1433             :         }
    1434             :       }
    1435             :     } // parentDS
    1436             :     else {
    1437             :       // This is the root docshell. If we got here while
    1438             :       // executing an onLoad Handler,this load will not go
    1439             :       // into session history.
    1440           5 :       bool inOnLoadHandler = false;
    1441           5 :       GetIsExecutingOnLoadHandler(&inOnLoadHandler);
    1442           5 :       if (inOnLoadHandler) {
    1443           0 :         loadType = LOAD_NORMAL_REPLACE;
    1444             :       }
    1445             :     }
    1446             :   } // !shEntry
    1447             : 
    1448           6 :   if (shEntry) {
    1449             : #ifdef DEBUG
    1450           0 :     MOZ_LOG(gDocShellLog, LogLevel::Debug,
    1451             :            ("nsDocShell[%p]: loading from session history", this));
    1452             : #endif
    1453             : 
    1454           0 :     return LoadHistoryEntry(shEntry, loadType);
    1455             :   }
    1456             : 
    1457             :   // On history navigation via Back/Forward buttons, don't execute
    1458             :   // automatic JavaScript redirection such as |location.href = ...| or
    1459             :   // |window.open()|
    1460             :   //
    1461             :   // LOAD_NORMAL:        window.open(...) etc.
    1462             :   // LOAD_STOP_CONTENT:  location.href = ..., location.assign(...)
    1463          12 :   if ((loadType == LOAD_NORMAL || loadType == LOAD_STOP_CONTENT) &&
    1464           6 :       ShouldBlockLoadingForBackButton()) {
    1465           0 :     return NS_OK;
    1466             :   }
    1467             : 
    1468             :   // Perform the load...
    1469             : 
    1470             :   // We need a principalToInherit.
    1471             :   //
    1472             :   // If principalIsExplicit is not set there are 4 possibilities:
    1473             :   // (1) If the system principal or an expanded principal was passed
    1474             :   //     in and we're a typeContent docshell, inherit the principal
    1475             :   //     from the current document instead.
    1476             :   // (2) In all other cases when the principal passed in is not null,
    1477             :   //     use that principal.
    1478             :   // (3) If the caller has allowed inheriting from the current document,
    1479             :   //     or if we're being called from system code (eg chrome JS or pure
    1480             :   //     C++) then inheritPrincipal should be true and InternalLoad will get
    1481             :   //     a principal from the current document. If none of these things are
    1482             :   //     true, then
    1483             :   // (4) we don't pass a principal into the channel, and a principal will be
    1484             :   //     created later from the channel's internal data.
    1485             :   //
    1486             :   // If principalIsExplicit *is* set, there are 4 possibilities
    1487             :   // (1) If the system principal or an expanded principal was passed in
    1488             :   //     and we're a typeContent docshell, return an error.
    1489             :   // (2) In all other cases when the principal passed in is not null,
    1490             :   //     use that principal.
    1491             :   // (3) If the caller has allowed inheriting from the current document,
    1492             :   //     then inheritPrincipal should be true and InternalLoad will get
    1493             :   //     a principal from the current document. If none of these things are
    1494             :   //     true, then
    1495             :   // (4) we dont' pass a principal into the channel, and a principal will be
    1496             :   //     created later from the channel's internal data.
    1497          12 :   nsCOMPtr<nsIPrincipal> principalToInherit = triggeringPrincipal;
    1498           6 :   if (principalToInherit && mItemType != typeChrome) {
    1499           3 :     if (nsContentUtils::IsSystemPrincipal(principalToInherit)) {
    1500           3 :       if (principalIsExplicit) {
    1501           0 :         return NS_ERROR_DOM_SECURITY_ERR;
    1502             :       }
    1503           3 :       principalToInherit = nullptr;
    1504           3 :       inheritPrincipal = true;
    1505           0 :     } else if (nsContentUtils::IsExpandedPrincipal(principalToInherit)) {
    1506           0 :       if (principalIsExplicit) {
    1507           0 :         return NS_ERROR_DOM_SECURITY_ERR;
    1508             :       }
    1509             :       // Don't inherit from the current page.  Just do the safe thing
    1510             :       // and pretend that we were loaded by a nullprincipal.
    1511             :       //
    1512             :       // We didn't inherit OriginAttributes here as ExpandedPrincipal doesn't
    1513             :       // have origin attributes.
    1514           0 :       principalToInherit = NullPrincipal::CreateWithInheritedAttributes(this);
    1515           0 :       inheritPrincipal = false;
    1516             :     }
    1517             :   }
    1518           6 :   if (!principalToInherit && !inheritPrincipal && !principalIsExplicit) {
    1519             :     // See if there's system or chrome JS code running
    1520           0 :     inheritPrincipal = nsContentUtils::LegacyIsCallerChromeOrNativeCode();
    1521             :   }
    1522             : 
    1523           6 :   if (aLoadFlags & LOAD_FLAGS_DISALLOW_INHERIT_PRINCIPAL) {
    1524           1 :     inheritPrincipal = false;
    1525             :     // If aFirstParty is true and the pref 'privacy.firstparty.isolate' is
    1526             :     // enabled, we will set firstPartyDomain on the origin attributes.
    1527           1 :     principalToInherit = NullPrincipal::CreateWithInheritedAttributes(this, aFirstParty);
    1528             :   }
    1529             : 
    1530             :   // If the triggeringPrincipal is not passed explicitly, we first try to create
    1531             :   // a principal from the referrer, since the referrer URI reflects the web origin
    1532             :   // that triggered the load. If there is no referrer URI, we fall back to using
    1533             :   // the SystemPrincipal. It's safe to assume that no provided triggeringPrincipal
    1534             :   // and no referrer simulate a load that was triggered by the system.
    1535             :   // It's important to note that this block of code needs to appear *after* the block
    1536             :   // where we munge the principalToInherit, because otherwise we would never enter
    1537             :   // code blocks checking if the principalToInherit is null and we will end up with
    1538             :   // a wrong inheritPrincipal flag.
    1539           6 :   if (!triggeringPrincipal) {
    1540           0 :     if (referrer) {
    1541           0 :       nsresult rv = CreatePrincipalFromReferrer(referrer,
    1542           0 :                                                 getter_AddRefs(triggeringPrincipal));
    1543           0 :       NS_ENSURE_SUCCESS(rv, rv);
    1544             :     }
    1545             :     else {
    1546           0 :       triggeringPrincipal = nsContentUtils::GetSystemPrincipal();
    1547             :     }
    1548             :   }
    1549             : 
    1550           6 :   uint32_t flags = 0;
    1551             : 
    1552           6 :   if (inheritPrincipal) {
    1553           2 :     flags |= INTERNAL_LOAD_FLAGS_INHERIT_PRINCIPAL;
    1554             :   }
    1555             : 
    1556           6 :   if (!sendReferrer) {
    1557           0 :     flags |= INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER;
    1558             :   }
    1559             : 
    1560           6 :   if (aLoadFlags & LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP) {
    1561           0 :     flags |= INTERNAL_LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP;
    1562             :   }
    1563             : 
    1564           6 :   if (aLoadFlags & LOAD_FLAGS_FIRST_LOAD) {
    1565           1 :     flags |= INTERNAL_LOAD_FLAGS_FIRST_LOAD;
    1566             :   }
    1567             : 
    1568           6 :   if (aLoadFlags & LOAD_FLAGS_BYPASS_CLASSIFIER) {
    1569           0 :     flags |= INTERNAL_LOAD_FLAGS_BYPASS_CLASSIFIER;
    1570             :   }
    1571             : 
    1572           6 :   if (aLoadFlags & LOAD_FLAGS_FORCE_ALLOW_COOKIES) {
    1573           0 :     flags |= INTERNAL_LOAD_FLAGS_FORCE_ALLOW_COOKIES;
    1574             :   }
    1575             : 
    1576           6 :   if (isSrcdoc) {
    1577           0 :     flags |= INTERNAL_LOAD_FLAGS_IS_SRCDOC;
    1578             :   }
    1579             : 
    1580          12 :   return InternalLoad(aURI,
    1581             :                       originalURI,
    1582             :                       resultPrincipalURI,
    1583             :                       loadReplace,
    1584             :                       referrer,
    1585             :                       referrerPolicy,
    1586             :                       triggeringPrincipal,
    1587             :                       principalToInherit,
    1588             :                       flags,
    1589             :                       target,
    1590             :                       nullptr,      // No type hint
    1591           6 :                       NullString(), // No forced download
    1592             :                       postStream,
    1593             :                       headersStream,
    1594             :                       loadType,
    1595             :                       nullptr, // No SHEntry
    1596             :                       aFirstParty,
    1597             :                       srcdoc,
    1598             :                       sourceDocShell,
    1599             :                       baseURI,
    1600             :                       false,
    1601             :                       nullptr,  // No nsIDocShell
    1602           6 :                       nullptr); // No nsIRequest
    1603             : }
    1604             : 
    1605             : NS_IMETHODIMP
    1606           0 : nsDocShell::LoadStream(nsIInputStream* aStream, nsIURI* aURI,
    1607             :                        const nsACString& aContentType,
    1608             :                        const nsACString& aContentCharset,
    1609             :                        nsIDocShellLoadInfo* aLoadInfo)
    1610             : {
    1611           0 :   NS_ENSURE_ARG(aStream);
    1612             : 
    1613           0 :   mAllowKeywordFixup = false;
    1614             : 
    1615             :   // if the caller doesn't pass in a URI we need to create a dummy URI. necko
    1616             :   // currently requires a URI in various places during the load. Some consumers
    1617             :   // do as well.
    1618           0 :   nsCOMPtr<nsIURI> uri = aURI;
    1619           0 :   if (!uri) {
    1620             :     // HACK ALERT
    1621           0 :     nsresult rv = NS_OK;
    1622           0 :     uri = do_CreateInstance(NS_SIMPLEURI_CONTRACTID, &rv);
    1623           0 :     if (NS_FAILED(rv)) {
    1624           0 :       return rv;
    1625             :     }
    1626             :     // Make sure that the URI spec "looks" like a protocol and path...
    1627             :     // For now, just use a bogus protocol called "internal"
    1628           0 :     rv = uri->SetSpec(NS_LITERAL_CSTRING("internal:load-stream"));
    1629           0 :     if (NS_FAILED(rv)) {
    1630           0 :       return rv;
    1631             :     }
    1632             :   }
    1633             : 
    1634           0 :   uint32_t loadType = LOAD_NORMAL;
    1635           0 :   nsCOMPtr<nsIPrincipal> triggeringPrincipal;
    1636           0 :   if (aLoadInfo) {
    1637           0 :     nsDocShellInfoLoadType lt = nsIDocShellLoadInfo::loadNormal;
    1638           0 :     (void)aLoadInfo->GetLoadType(&lt);
    1639             :     // Get the appropriate LoadType from nsIDocShellLoadInfo type
    1640           0 :     loadType = ConvertDocShellLoadInfoToLoadType(lt);
    1641           0 :     aLoadInfo->GetTriggeringPrincipal(getter_AddRefs(triggeringPrincipal));
    1642             :   }
    1643             : 
    1644           0 :   NS_ENSURE_SUCCESS(Stop(nsIWebNavigation::STOP_NETWORK), NS_ERROR_FAILURE);
    1645             : 
    1646           0 :   mLoadType = loadType;
    1647             : 
    1648           0 :   if (!triggeringPrincipal) {
    1649           0 :     triggeringPrincipal = nsContentUtils::GetSystemPrincipal();
    1650             :   }
    1651             : 
    1652             :   // build up a channel for this stream.
    1653           0 :   nsCOMPtr<nsIChannel> channel;
    1654           0 :   nsresult rv = NS_NewInputStreamChannel(getter_AddRefs(channel),
    1655             :                                          uri,
    1656             :                                          aStream,
    1657             :                                          triggeringPrincipal,
    1658             :                                          nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
    1659             :                                          nsIContentPolicy::TYPE_OTHER,
    1660             :                                          aContentType,
    1661           0 :                                          aContentCharset);
    1662           0 :   NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
    1663             : 
    1664           0 :   nsCOMPtr<nsIURILoader> uriLoader(do_GetService(NS_URI_LOADER_CONTRACTID));
    1665           0 :   NS_ENSURE_TRUE(uriLoader, NS_ERROR_FAILURE);
    1666             : 
    1667           0 :   NS_ENSURE_SUCCESS(DoChannelLoad(channel, uriLoader, false),
    1668             :                     NS_ERROR_FAILURE);
    1669           0 :   return NS_OK;
    1670             : }
    1671             : 
    1672             : NS_IMETHODIMP
    1673           6 : nsDocShell::CreateLoadInfo(nsIDocShellLoadInfo** aLoadInfo)
    1674             : {
    1675           6 :   nsDocShellLoadInfo* loadInfo = new nsDocShellLoadInfo();
    1676          12 :   nsCOMPtr<nsIDocShellLoadInfo> localRef(loadInfo);
    1677             : 
    1678           6 :   localRef.forget(aLoadInfo);
    1679          12 :   return NS_OK;
    1680             : }
    1681             : 
    1682             : /*
    1683             :  * Reset state to a new content model within the current document and the
    1684             :  * document viewer. Called by the document before initiating an out of band
    1685             :  * document.write().
    1686             :  */
    1687             : NS_IMETHODIMP
    1688           0 : nsDocShell::PrepareForNewContentModel()
    1689             : {
    1690           0 :   mEODForCurrentDocument = false;
    1691           0 :   return NS_OK;
    1692             : }
    1693             : 
    1694             : NS_IMETHODIMP
    1695           5 : nsDocShell::FirePageHideNotification(bool aIsUnload)
    1696             : {
    1697           5 :   FirePageHideNotificationInternal(aIsUnload, false);
    1698           5 :   return NS_OK;
    1699             : }
    1700             : 
    1701             : void
    1702           5 : nsDocShell::FirePageHideNotificationInternal(bool aIsUnload,
    1703             :                                              bool aSkipCheckingDynEntries)
    1704             : {
    1705           5 :   if (mContentViewer && !mFiredUnloadEvent) {
    1706             :     // Keep an explicit reference since calling PageHide could release
    1707             :     // mContentViewer
    1708           8 :     nsCOMPtr<nsIContentViewer> contentViewer(mContentViewer);
    1709           4 :     mFiredUnloadEvent = true;
    1710             : 
    1711           4 :     if (mTiming) {
    1712           4 :       mTiming->NotifyUnloadEventStart();
    1713             :     }
    1714             : 
    1715           4 :     contentViewer->PageHide(aIsUnload);
    1716             : 
    1717           4 :     if (mTiming) {
    1718           4 :       mTiming->NotifyUnloadEventEnd();
    1719             :     }
    1720             : 
    1721           8 :     AutoTArray<nsCOMPtr<nsIDocShell>, 8> kids;
    1722           4 :     uint32_t n = mChildList.Length();
    1723           4 :     kids.SetCapacity(n);
    1724           4 :     for (uint32_t i = 0; i < n; i++) {
    1725           0 :       kids.AppendElement(do_QueryInterface(ChildAt(i)));
    1726             :     }
    1727             : 
    1728           4 :     n = kids.Length();
    1729           4 :     for (uint32_t i = 0; i < n; ++i) {
    1730           0 :       RefPtr<nsDocShell> child = static_cast<nsDocShell*>(kids[i].get());
    1731           0 :       if (child) {
    1732             :         // Skip checking dynamic subframe entries in our children.
    1733           0 :         child->FirePageHideNotificationInternal(aIsUnload, true);
    1734             :       }
    1735             :     }
    1736             : 
    1737             :     // If the document is unloading, remove all dynamic subframe entries.
    1738           4 :     if (aIsUnload && !aSkipCheckingDynEntries) {
    1739           8 :       nsCOMPtr<nsISHistory> rootSH;
    1740           4 :       GetRootSessionHistory(getter_AddRefs(rootSH));
    1741           8 :       nsCOMPtr<nsISHistoryInternal> shPrivate = do_QueryInterface(rootSH);
    1742           8 :       nsCOMPtr<nsISHContainer> container(do_QueryInterface(mOSHE));
    1743           4 :       if (shPrivate && container) {
    1744           0 :         int32_t index = -1;
    1745           0 :         rootSH->GetIndex(&index);
    1746           0 :         shPrivate->RemoveDynEntries(index, container);
    1747             :       }
    1748             :     }
    1749             : 
    1750             :     // Now make sure our editor, if any, is detached before we go
    1751             :     // any farther.
    1752           4 :     DetachEditorFromWindow();
    1753             :   }
    1754           5 : }
    1755             : 
    1756             : nsresult
    1757           0 : nsDocShell::DispatchToTabGroup(const char* aName,
    1758             :                                TaskCategory aCategory,
    1759             :                                already_AddRefed<nsIRunnable>&& aRunnable)
    1760             : {
    1761             :   // Hold the ref so we won't forget to release it.
    1762           0 :   nsCOMPtr<nsIRunnable> runnable(aRunnable);
    1763           0 :   nsCOMPtr<nsPIDOMWindowOuter> win = GetWindow();
    1764           0 :   if (!win) {
    1765             :     // Window should only be unavailable after destroyed.
    1766           0 :     MOZ_ASSERT(mIsBeingDestroyed);
    1767           0 :     return NS_ERROR_FAILURE;
    1768             :   }
    1769             : 
    1770           0 :   RefPtr<mozilla::dom::TabGroup> tabGroup = win->TabGroup();
    1771           0 :   return tabGroup->Dispatch(aName, aCategory, runnable.forget());
    1772             : }
    1773             : 
    1774             : NS_IMETHODIMP
    1775           0 : nsDocShell::DispatchLocationChangeEvent()
    1776             : {
    1777           0 :   return DispatchToTabGroup(
    1778             :     "nsDocShell::FireDummyOnLocationChange",
    1779             :     TaskCategory::Other,
    1780           0 :     NewRunnableMethod("nsDocShell::FireDummyOnLocationChange",
    1781             :                       this,
    1782           0 :                       &nsDocShell::FireDummyOnLocationChange));
    1783             : }
    1784             : 
    1785             : bool
    1786          16 : nsDocShell::MaybeInitTiming()
    1787             : {
    1788          16 :   if (mTiming && !mBlankTiming) {
    1789           6 :     return false;
    1790             :   }
    1791             : 
    1792          10 :   bool canBeReset = false;
    1793             : 
    1794          10 :   if (mScriptGlobal && mBlankTiming) {
    1795             :     nsPIDOMWindowInner* innerWin =
    1796           4 :       mScriptGlobal->AsOuter()->GetCurrentInnerWindow();
    1797           4 :     if (innerWin && innerWin->GetPerformance()) {
    1798           4 :       mTiming = innerWin->GetPerformance()->GetDOMTiming();
    1799           4 :       mBlankTiming = false;
    1800             :     }
    1801             :   }
    1802             : 
    1803          10 :   if (!mTiming) {
    1804           6 :     mTiming = new nsDOMNavigationTiming(this);
    1805           6 :     canBeReset = true;
    1806             :   }
    1807             : 
    1808          10 :   mTiming->NotifyNavigationStart(
    1809          10 :     mIsActive ? nsDOMNavigationTiming::DocShellState::eActive
    1810          10 :               : nsDOMNavigationTiming::DocShellState::eInactive);
    1811             : 
    1812          10 :   return canBeReset;
    1813             : }
    1814             : 
    1815             : void
    1816           0 : nsDocShell::MaybeResetInitTiming(bool aReset)
    1817             : {
    1818           0 :   if (aReset) {
    1819           0 :     mTiming = nullptr;
    1820             :   }
    1821           0 : }
    1822             : 
    1823             : //
    1824             : // Bug 13871: Prevent frameset spoofing
    1825             : //
    1826             : // This routine answers: 'Is origin's document from same domain as
    1827             : // target's document?'
    1828             : //
    1829             : // file: uris are considered the same domain for the purpose of
    1830             : // frame navigation regardless of script accessibility (bug 420425)
    1831             : //
    1832             : /* static */ bool
    1833           0 : nsDocShell::ValidateOrigin(nsIDocShellTreeItem* aOriginTreeItem,
    1834             :                            nsIDocShellTreeItem* aTargetTreeItem)
    1835             : {
    1836             :   // We want to bypass this check for chrome callers, but only if there's
    1837             :   // JS on the stack. System callers still need to do it.
    1838           0 :   if (nsContentUtils::GetCurrentJSContext() &&
    1839           0 :       nsContentUtils::IsCallerChrome()) {
    1840           0 :     return true;
    1841             :   }
    1842             : 
    1843           0 :   MOZ_ASSERT(aOriginTreeItem && aTargetTreeItem, "need two docshells");
    1844             : 
    1845             :   // Get origin document principal
    1846           0 :   nsCOMPtr<nsIDocument> originDocument = aOriginTreeItem->GetDocument();
    1847           0 :   NS_ENSURE_TRUE(originDocument, false);
    1848             : 
    1849             :   // Get target principal
    1850           0 :   nsCOMPtr<nsIDocument> targetDocument = aTargetTreeItem->GetDocument();
    1851           0 :   NS_ENSURE_TRUE(targetDocument, false);
    1852             : 
    1853             :   bool equal;
    1854           0 :   nsresult rv = originDocument->NodePrincipal()->Equals(
    1855           0 :     targetDocument->NodePrincipal(), &equal);
    1856           0 :   if (NS_SUCCEEDED(rv) && equal) {
    1857           0 :     return true;
    1858             :   }
    1859             : 
    1860             :   // Not strictly equal, special case if both are file: uris
    1861           0 :   bool originIsFile = false;
    1862           0 :   bool targetIsFile = false;
    1863           0 :   nsCOMPtr<nsIURI> originURI;
    1864           0 :   nsCOMPtr<nsIURI> targetURI;
    1865           0 :   nsCOMPtr<nsIURI> innerOriginURI;
    1866           0 :   nsCOMPtr<nsIURI> innerTargetURI;
    1867             : 
    1868           0 :   rv = originDocument->NodePrincipal()->GetURI(getter_AddRefs(originURI));
    1869           0 :   if (NS_SUCCEEDED(rv) && originURI) {
    1870           0 :     innerOriginURI = NS_GetInnermostURI(originURI);
    1871             :   }
    1872             : 
    1873           0 :   rv = targetDocument->NodePrincipal()->GetURI(getter_AddRefs(targetURI));
    1874           0 :   if (NS_SUCCEEDED(rv) && targetURI) {
    1875           0 :     innerTargetURI = NS_GetInnermostURI(targetURI);
    1876             :   }
    1877             : 
    1878           0 :   return innerOriginURI && innerTargetURI &&
    1879           0 :          NS_SUCCEEDED(innerOriginURI->SchemeIs("file", &originIsFile)) &&
    1880           0 :          NS_SUCCEEDED(innerTargetURI->SchemeIs("file", &targetIsFile)) &&
    1881           0 :          originIsFile && targetIsFile;
    1882             : }
    1883             : 
    1884             : nsresult
    1885           0 : nsDocShell::GetEldestPresContext(nsPresContext** aPresContext)
    1886             : {
    1887           0 :   NS_ENSURE_ARG_POINTER(aPresContext);
    1888           0 :   *aPresContext = nullptr;
    1889             : 
    1890           0 :   nsCOMPtr<nsIContentViewer> viewer = mContentViewer;
    1891           0 :   while (viewer) {
    1892           0 :     nsCOMPtr<nsIContentViewer> prevViewer;
    1893           0 :     viewer->GetPreviousViewer(getter_AddRefs(prevViewer));
    1894           0 :     if (!prevViewer) {
    1895           0 :       return viewer->GetPresContext(aPresContext);
    1896             :     }
    1897           0 :     viewer = prevViewer;
    1898             :   }
    1899             : 
    1900           0 :   return NS_OK;
    1901             : }
    1902             : 
    1903             : NS_IMETHODIMP
    1904          54 : nsDocShell::GetPresContext(nsPresContext** aPresContext)
    1905             : {
    1906          54 :   NS_ENSURE_ARG_POINTER(aPresContext);
    1907          54 :   *aPresContext = nullptr;
    1908             : 
    1909          54 :   if (!mContentViewer) {
    1910           7 :     return NS_OK;
    1911             :   }
    1912             : 
    1913          47 :   return mContentViewer->GetPresContext(aPresContext);
    1914             : }
    1915             : 
    1916             : NS_IMETHODIMP_(nsIPresShell*)
    1917          34 : nsDocShell::GetPresShell()
    1918             : {
    1919          68 :   RefPtr<nsPresContext> presContext;
    1920          34 :   (void)GetPresContext(getter_AddRefs(presContext));
    1921          68 :   return presContext ? presContext->GetPresShell() : nullptr;
    1922             : }
    1923             : 
    1924             : NS_IMETHODIMP
    1925           0 : nsDocShell::GetEldestPresShell(nsIPresShell** aPresShell)
    1926             : {
    1927           0 :   nsresult rv = NS_OK;
    1928             : 
    1929           0 :   NS_ENSURE_ARG_POINTER(aPresShell);
    1930           0 :   *aPresShell = nullptr;
    1931             : 
    1932           0 :   RefPtr<nsPresContext> presContext;
    1933           0 :   (void)GetEldestPresContext(getter_AddRefs(presContext));
    1934             : 
    1935           0 :   if (presContext) {
    1936           0 :     NS_IF_ADDREF(*aPresShell = presContext->GetPresShell());
    1937             :   }
    1938             : 
    1939           0 :   return rv;
    1940             : }
    1941             : 
    1942             : NS_IMETHODIMP
    1943          58 : nsDocShell::GetContentViewer(nsIContentViewer** aContentViewer)
    1944             : {
    1945          58 :   NS_ENSURE_ARG_POINTER(aContentViewer);
    1946             : 
    1947          58 :   *aContentViewer = mContentViewer;
    1948          58 :   NS_IF_ADDREF(*aContentViewer);
    1949          58 :   return NS_OK;
    1950             : }
    1951             : 
    1952             : NS_IMETHODIMP
    1953           3 : nsDocShell::SetChromeEventHandler(nsIDOMEventTarget* aChromeEventHandler)
    1954             : {
    1955             :   // Weak reference. Don't addref.
    1956           6 :   nsCOMPtr<EventTarget> handler = do_QueryInterface(aChromeEventHandler);
    1957           3 :   mChromeEventHandler = handler.get();
    1958             : 
    1959           3 :   if (mScriptGlobal) {
    1960           1 :     mScriptGlobal->SetChromeEventHandler(mChromeEventHandler);
    1961             :   }
    1962             : 
    1963           6 :   return NS_OK;
    1964             : }
    1965             : 
    1966             : NS_IMETHODIMP
    1967          12 : nsDocShell::GetChromeEventHandler(nsIDOMEventTarget** aChromeEventHandler)
    1968             : {
    1969          12 :   NS_ENSURE_ARG_POINTER(aChromeEventHandler);
    1970          24 :   nsCOMPtr<EventTarget> handler = mChromeEventHandler;
    1971          12 :   handler.forget(aChromeEventHandler);
    1972          12 :   return NS_OK;
    1973             : }
    1974             : 
    1975             : NS_IMETHODIMP
    1976           0 : nsDocShell::SetCurrentURI(nsIURI* aURI)
    1977             : {
    1978             :   // Note that securityUI will set STATE_IS_INSECURE, even if
    1979             :   // the scheme of |aURI| is "https".
    1980           0 :   SetCurrentURI(aURI, nullptr, true, 0);
    1981           0 :   return NS_OK;
    1982             : }
    1983             : 
    1984             : bool
    1985           8 : nsDocShell::SetCurrentURI(nsIURI* aURI, nsIRequest* aRequest,
    1986             :                           bool aFireOnLocationChange, uint32_t aLocationFlags)
    1987             : {
    1988           8 :   MOZ_LOG(gDocShellLeakLog, LogLevel::Debug,
    1989             :           ("DOCSHELL %p SetCurrentURI %s\n",
    1990             :            this, aURI ? aURI->GetSpecOrDefault().get() : ""));
    1991             : 
    1992             :   // We don't want to send a location change when we're displaying an error
    1993             :   // page, and we don't want to change our idea of "current URI" either
    1994           8 :   if (mLoadType == LOAD_ERROR_PAGE) {
    1995           0 :     return false;
    1996             :   }
    1997             : 
    1998           8 :   mCurrentURI = NS_TryToMakeImmutable(aURI);
    1999             : 
    2000           8 :   if (!NS_IsAboutBlank(mCurrentURI)) {
    2001           3 :     mHasLoadedNonBlankURI = true;
    2002             :   }
    2003             : 
    2004           8 :   bool isRoot = false;  // Is this the root docshell
    2005           8 :   bool isSubFrame = false;  // Is this a subframe navigation?
    2006             : 
    2007          16 :   nsCOMPtr<nsIDocShellTreeItem> root;
    2008             : 
    2009           8 :   GetSameTypeRootTreeItem(getter_AddRefs(root));
    2010           8 :   if (root.get() == static_cast<nsIDocShellTreeItem*>(this)) {
    2011             :     // This is the root docshell
    2012           7 :     isRoot = true;
    2013             :   }
    2014           8 :   if (mLSHE) {
    2015           1 :     mLSHE->GetIsSubFrame(&isSubFrame);
    2016             :   }
    2017             : 
    2018           8 :   if (!isSubFrame && !isRoot) {
    2019             :     /*
    2020             :      * We don't want to send OnLocationChange notifications when
    2021             :      * a subframe is being loaded for the first time, while
    2022             :      * visiting a frameset page
    2023             :      */
    2024           1 :     return false;
    2025             :   }
    2026             : 
    2027           7 :   if (aFireOnLocationChange) {
    2028           4 :     FireOnLocationChange(this, aRequest, aURI, aLocationFlags);
    2029             :   }
    2030           7 :   return !aFireOnLocationChange;
    2031             : }
    2032             : 
    2033             : NS_IMETHODIMP
    2034           0 : nsDocShell::GetCharset(nsACString& aCharset)
    2035             : {
    2036           0 :   aCharset.Truncate();
    2037             : 
    2038           0 :   nsIPresShell* presShell = GetPresShell();
    2039           0 :   NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE);
    2040           0 :   nsIDocument* doc = presShell->GetDocument();
    2041           0 :   NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE);
    2042           0 :   doc->GetDocumentCharacterSet()->Name(aCharset);
    2043           0 :   return NS_OK;
    2044             : }
    2045             : 
    2046             : NS_IMETHODIMP
    2047           0 : nsDocShell::GatherCharsetMenuTelemetry()
    2048             : {
    2049           0 :   nsCOMPtr<nsIContentViewer> viewer;
    2050           0 :   GetContentViewer(getter_AddRefs(viewer));
    2051           0 :   if (!viewer) {
    2052           0 :     return NS_OK;
    2053             :   }
    2054             : 
    2055           0 :   nsIDocument* doc = viewer->GetDocument();
    2056           0 :   if (!doc || doc->WillIgnoreCharsetOverride()) {
    2057           0 :     return NS_OK;
    2058             :   }
    2059             : 
    2060           0 :   Telemetry::Accumulate(Telemetry::CHARSET_OVERRIDE_USED, true);
    2061             : 
    2062           0 :   bool isFileURL = false;
    2063           0 :   nsIURI* url = doc->GetOriginalURI();
    2064           0 :   if (url) {
    2065           0 :     url->SchemeIs("file", &isFileURL);
    2066             :   }
    2067             : 
    2068           0 :   int32_t charsetSource = doc->GetDocumentCharacterSetSource();
    2069           0 :   switch (charsetSource) {
    2070             :     case kCharsetFromTopLevelDomain:
    2071             :       // Unlabeled doc on a domain that we map to a fallback encoding
    2072           0 :       Telemetry::Accumulate(Telemetry::CHARSET_OVERRIDE_SITUATION, 7);
    2073           0 :       break;
    2074             :     case kCharsetFromFallback:
    2075             :     case kCharsetFromDocTypeDefault:
    2076             :     case kCharsetFromCache:
    2077             :     case kCharsetFromParentFrame:
    2078             :     case kCharsetFromHintPrevDoc:
    2079             :       // Changing charset on an unlabeled doc.
    2080           0 :       if (isFileURL) {
    2081           0 :         Telemetry::Accumulate(Telemetry::CHARSET_OVERRIDE_SITUATION, 0);
    2082             :       } else {
    2083           0 :         Telemetry::Accumulate(Telemetry::CHARSET_OVERRIDE_SITUATION, 1);
    2084             :       }
    2085           0 :       break;
    2086             :     case kCharsetFromAutoDetection:
    2087             :       // Changing charset on unlabeled doc where chardet fired
    2088           0 :       if (isFileURL) {
    2089           0 :         Telemetry::Accumulate(Telemetry::CHARSET_OVERRIDE_SITUATION, 2);
    2090             :       } else {
    2091           0 :         Telemetry::Accumulate(Telemetry::CHARSET_OVERRIDE_SITUATION, 3);
    2092             :       }
    2093           0 :       break;
    2094             :     case kCharsetFromMetaPrescan:
    2095             :     case kCharsetFromMetaTag:
    2096             :     case kCharsetFromChannel:
    2097             :       // Changing charset on a doc that had a charset label.
    2098           0 :       Telemetry::Accumulate(Telemetry::CHARSET_OVERRIDE_SITUATION, 4);
    2099           0 :       break;
    2100             :     case kCharsetFromParentForced:
    2101             :     case kCharsetFromUserForced:
    2102             :       // Changing charset on a document that already had an override.
    2103           0 :       Telemetry::Accumulate(Telemetry::CHARSET_OVERRIDE_SITUATION, 5);
    2104           0 :       break;
    2105             :     case kCharsetFromIrreversibleAutoDetection:
    2106             :     case kCharsetFromOtherComponent:
    2107             :     case kCharsetFromByteOrderMark:
    2108             :     case kCharsetUninitialized:
    2109             :     default:
    2110             :       // Bug. This isn't supposed to happen.
    2111           0 :       Telemetry::Accumulate(Telemetry::CHARSET_OVERRIDE_SITUATION, 6);
    2112           0 :       break;
    2113             :   }
    2114           0 :   return NS_OK;
    2115             : }
    2116             : 
    2117             : NS_IMETHODIMP
    2118           0 : nsDocShell::SetCharset(const nsACString& aCharset)
    2119             : {
    2120             :   // set the charset override
    2121           0 :   return SetForcedCharset(aCharset);
    2122             : }
    2123             : 
    2124             : NS_IMETHODIMP
    2125           0 : nsDocShell::SetForcedCharset(const nsACString& aCharset)
    2126             : {
    2127           0 :   if (aCharset.IsEmpty()) {
    2128           0 :     mForcedCharset = nullptr;
    2129           0 :     return NS_OK;
    2130             :   }
    2131           0 :   const Encoding* encoding = Encoding::ForLabel(aCharset);
    2132           0 :   if (!encoding) {
    2133             :     // Reject unknown labels
    2134           0 :     return NS_ERROR_INVALID_ARG;
    2135             :   }
    2136           0 :   if (!encoding->IsAsciiCompatible() && encoding != ISO_2022_JP_ENCODING) {
    2137             :     // Reject XSS hazards
    2138           0 :     return NS_ERROR_INVALID_ARG;
    2139             :   }
    2140           0 :   mForcedCharset = encoding;
    2141           0 :   return NS_OK;
    2142             : }
    2143             : 
    2144             : NS_IMETHODIMP
    2145           0 : nsDocShell::GetForcedCharset(nsACString& aResult)
    2146             : {
    2147           0 :   mForcedCharset->Name(aResult);
    2148           0 :   return NS_OK;
    2149             : }
    2150             : 
    2151             : void
    2152           0 : nsDocShell::SetParentCharset(const Encoding*& aCharset,
    2153             :                              int32_t aCharsetSource,
    2154             :                              nsIPrincipal* aPrincipal)
    2155             : {
    2156           0 :   mParentCharset = aCharset;
    2157           0 :   mParentCharsetSource = aCharsetSource;
    2158           0 :   mParentCharsetPrincipal = aPrincipal;
    2159           0 : }
    2160             : 
    2161             : void
    2162           3 : nsDocShell::GetParentCharset(const Encoding*& aCharset,
    2163             :                              int32_t* aCharsetSource,
    2164             :                              nsIPrincipal** aPrincipal)
    2165             : {
    2166           3 :   aCharset = mParentCharset;
    2167           3 :   *aCharsetSource = mParentCharsetSource;
    2168           3 :   NS_IF_ADDREF(*aPrincipal = mParentCharsetPrincipal);
    2169           3 : }
    2170             : 
    2171             : NS_IMETHODIMP
    2172           8 : nsDocShell::GetChannelIsUnsafe(bool* aUnsafe)
    2173             : {
    2174           8 :   *aUnsafe = false;
    2175             : 
    2176           8 :   nsIChannel* channel = GetCurrentDocChannel();
    2177           8 :   if (!channel) {
    2178           3 :     return NS_OK;
    2179             :   }
    2180             : 
    2181          10 :   nsCOMPtr<nsIJARChannel> jarChannel = do_QueryInterface(channel);
    2182           5 :   if (!jarChannel) {
    2183           5 :     return NS_OK;
    2184             :   }
    2185             : 
    2186           0 :   return jarChannel->GetIsUnsafe(aUnsafe);
    2187             : }
    2188             : 
    2189             : NS_IMETHODIMP
    2190           4 : nsDocShell::GetHasMixedActiveContentLoaded(bool* aHasMixedActiveContentLoaded)
    2191             : {
    2192           8 :   nsCOMPtr<nsIDocument> doc(GetDocument());
    2193           4 :   *aHasMixedActiveContentLoaded = doc && doc->GetHasMixedActiveContentLoaded();
    2194           8 :   return NS_OK;
    2195             : }
    2196             : 
    2197             : NS_IMETHODIMP
    2198           2 : nsDocShell::GetHasMixedActiveContentBlocked(bool* aHasMixedActiveContentBlocked)
    2199             : {
    2200           4 :   nsCOMPtr<nsIDocument> doc(GetDocument());
    2201           2 :   *aHasMixedActiveContentBlocked =
    2202           2 :     doc && doc->GetHasMixedActiveContentBlocked();
    2203           4 :   return NS_OK;
    2204             : }
    2205             : 
    2206             : NS_IMETHODIMP
    2207           2 : nsDocShell::GetHasMixedDisplayContentLoaded(bool* aHasMixedDisplayContentLoaded)
    2208             : {
    2209           4 :   nsCOMPtr<nsIDocument> doc(GetDocument());
    2210           2 :   *aHasMixedDisplayContentLoaded =
    2211           2 :     doc && doc->GetHasMixedDisplayContentLoaded();
    2212           4 :   return NS_OK;
    2213             : }
    2214             : 
    2215             : NS_IMETHODIMP
    2216           2 : nsDocShell::GetHasMixedDisplayContentBlocked(
    2217             :   bool* aHasMixedDisplayContentBlocked)
    2218             : {
    2219           4 :   nsCOMPtr<nsIDocument> doc(GetDocument());
    2220           2 :   *aHasMixedDisplayContentBlocked =
    2221           2 :     doc && doc->GetHasMixedDisplayContentBlocked();
    2222           4 :   return NS_OK;
    2223             : }
    2224             : 
    2225             : NS_IMETHODIMP
    2226           2 : nsDocShell::GetHasTrackingContentBlocked(bool* aHasTrackingContentBlocked)
    2227             : {
    2228           4 :   nsCOMPtr<nsIDocument> doc(GetDocument());
    2229           2 :   *aHasTrackingContentBlocked = doc && doc->GetHasTrackingContentBlocked();
    2230           4 :   return NS_OK;
    2231             : }
    2232             : 
    2233             : NS_IMETHODIMP
    2234           2 : nsDocShell::GetHasTrackingContentLoaded(bool* aHasTrackingContentLoaded)
    2235             : {
    2236           4 :   nsCOMPtr<nsIDocument> doc(GetDocument());
    2237           2 :   *aHasTrackingContentLoaded = doc && doc->GetHasTrackingContentLoaded();
    2238           4 :   return NS_OK;
    2239             : }
    2240             : 
    2241             : NS_IMETHODIMP
    2242           2 : nsDocShell::GetAllowPlugins(bool* aAllowPlugins)
    2243             : {
    2244           2 :   NS_ENSURE_ARG_POINTER(aAllowPlugins);
    2245             : 
    2246           2 :   *aAllowPlugins = mAllowPlugins;
    2247           2 :   if (!mAllowPlugins) {
    2248           0 :     return NS_OK;
    2249             :   }
    2250             : 
    2251             :   bool unsafe;
    2252           2 :   *aAllowPlugins = NS_SUCCEEDED(GetChannelIsUnsafe(&unsafe)) && !unsafe;
    2253           2 :   return NS_OK;
    2254             : }
    2255             : 
    2256             : NS_IMETHODIMP
    2257           2 : nsDocShell::SetAllowPlugins(bool aAllowPlugins)
    2258             : {
    2259           2 :   mAllowPlugins = aAllowPlugins;
    2260             :   // XXX should enable or disable a plugin host
    2261           2 :   return NS_OK;
    2262             : }
    2263             : 
    2264             : NS_IMETHODIMP
    2265          10 : nsDocShell::GetAllowJavascript(bool* aAllowJavascript)
    2266             : {
    2267          10 :   NS_ENSURE_ARG_POINTER(aAllowJavascript);
    2268             : 
    2269          10 :   *aAllowJavascript = mAllowJavascript;
    2270          10 :   return NS_OK;
    2271             : }
    2272             : 
    2273             : NS_IMETHODIMP
    2274           2 : nsDocShell::SetAllowJavascript(bool aAllowJavascript)
    2275             : {
    2276           2 :   mAllowJavascript = aAllowJavascript;
    2277           2 :   RecomputeCanExecuteScripts();
    2278           2 :   return NS_OK;
    2279             : }
    2280             : 
    2281             : NS_IMETHODIMP
    2282        2259 : nsDocShell::GetUsePrivateBrowsing(bool* aUsePrivateBrowsing)
    2283             : {
    2284        2259 :   NS_ENSURE_ARG_POINTER(aUsePrivateBrowsing);
    2285        2259 :   AssertOriginAttributesMatchPrivateBrowsing();
    2286        2259 :   *aUsePrivateBrowsing = mPrivateBrowsingId > 0;
    2287        2259 :   return NS_OK;
    2288             : }
    2289             : 
    2290             : NS_IMETHODIMP
    2291           0 : nsDocShell::SetUsePrivateBrowsing(bool aUsePrivateBrowsing)
    2292             : {
    2293           0 :   nsContentUtils::ReportToConsoleNonLocalized(
    2294           0 :     NS_LITERAL_STRING("Only internal code is allowed to set the usePrivateBrowsing attribute"),
    2295             :     nsIScriptError::warningFlag,
    2296           0 :     NS_LITERAL_CSTRING("Internal API Used"),
    2297           0 :     mContentViewer ? mContentViewer->GetDocument() : nullptr);
    2298             : 
    2299           0 :   if (!CanSetOriginAttributes()) {
    2300           0 :     bool changed = aUsePrivateBrowsing != (mPrivateBrowsingId > 0);
    2301             : 
    2302           0 :     return changed ? NS_ERROR_FAILURE : NS_OK;
    2303             :   }
    2304             : 
    2305           0 :   return SetPrivateBrowsing(aUsePrivateBrowsing);
    2306             : }
    2307             : 
    2308             : NS_IMETHODIMP
    2309           9 : nsDocShell::SetPrivateBrowsing(bool aUsePrivateBrowsing)
    2310             : {
    2311           9 :   bool changed = aUsePrivateBrowsing != (mPrivateBrowsingId > 0);
    2312           9 :   if (changed) {
    2313           0 :     mPrivateBrowsingId = aUsePrivateBrowsing ? 1 : 0;
    2314             : 
    2315           0 :     if (mItemType != typeChrome) {
    2316           0 :       mOriginAttributes.SyncAttributesWithPrivateBrowsing(aUsePrivateBrowsing);
    2317             :     }
    2318             : 
    2319           0 :     if (mAffectPrivateSessionLifetime) {
    2320           0 :       if (aUsePrivateBrowsing) {
    2321           0 :         IncreasePrivateDocShellCount();
    2322             :       } else {
    2323           0 :         DecreasePrivateDocShellCount();
    2324             :       }
    2325             :     }
    2326             :   }
    2327             : 
    2328          18 :   nsTObserverArray<nsDocLoader*>::ForwardIterator iter(mChildList);
    2329           9 :   while (iter.HasMore()) {
    2330           0 :     nsCOMPtr<nsILoadContext> shell = do_QueryObject(iter.GetNext());
    2331           0 :     if (shell) {
    2332           0 :       shell->SetPrivateBrowsing(aUsePrivateBrowsing);
    2333             :     }
    2334             :   }
    2335             : 
    2336           9 :   if (changed) {
    2337           0 :     nsTObserverArray<nsWeakPtr>::ForwardIterator iter(mPrivacyObservers);
    2338           0 :     while (iter.HasMore()) {
    2339           0 :       nsWeakPtr ref = iter.GetNext();
    2340           0 :       nsCOMPtr<nsIPrivacyTransitionObserver> obs = do_QueryReferent(ref);
    2341           0 :       if (!obs) {
    2342           0 :         mPrivacyObservers.RemoveElement(ref);
    2343             :       } else {
    2344           0 :         obs->PrivateModeChanged(aUsePrivateBrowsing);
    2345             :       }
    2346             :     }
    2347             :   }
    2348             : 
    2349           9 :   AssertOriginAttributesMatchPrivateBrowsing();
    2350          18 :   return NS_OK;
    2351             : }
    2352             : 
    2353             : NS_IMETHODIMP
    2354           4 : nsDocShell::GetHasLoadedNonBlankURI(bool* aResult)
    2355             : {
    2356           4 :   NS_ENSURE_ARG_POINTER(aResult);
    2357             : 
    2358           4 :   *aResult = mHasLoadedNonBlankURI;
    2359           4 :   return NS_OK;
    2360             : }
    2361             : 
    2362             : NS_IMETHODIMP
    2363           5 : nsDocShell::GetUseRemoteTabs(bool* aUseRemoteTabs)
    2364             : {
    2365           5 :   NS_ENSURE_ARG_POINTER(aUseRemoteTabs);
    2366             : 
    2367           5 :   *aUseRemoteTabs = mUseRemoteTabs;
    2368           5 :   return NS_OK;
    2369             : }
    2370             : 
    2371             : NS_IMETHODIMP
    2372           4 : nsDocShell::SetRemoteTabs(bool aUseRemoteTabs)
    2373             : {
    2374             : #ifdef MOZ_CRASHREPORTER
    2375           4 :   if (aUseRemoteTabs) {
    2376          12 :     CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("DOMIPCEnabled"),
    2377          16 :                                        NS_LITERAL_CSTRING("1"));
    2378             :   }
    2379             : #endif
    2380             : 
    2381           4 :   mUseRemoteTabs = aUseRemoteTabs;
    2382           4 :   return NS_OK;
    2383             : }
    2384             : 
    2385             : NS_IMETHODIMP
    2386           3 : nsDocShell::SetAffectPrivateSessionLifetime(bool aAffectLifetime)
    2387             : {
    2388           3 :   bool change = aAffectLifetime != mAffectPrivateSessionLifetime;
    2389           3 :   if (change && UsePrivateBrowsing()) {
    2390           0 :     AssertOriginAttributesMatchPrivateBrowsing();
    2391           0 :     if (aAffectLifetime) {
    2392           0 :       IncreasePrivateDocShellCount();
    2393             :     } else {
    2394           0 :       DecreasePrivateDocShellCount();
    2395             :     }
    2396             :   }
    2397           3 :   mAffectPrivateSessionLifetime = aAffectLifetime;
    2398             : 
    2399           6 :   nsTObserverArray<nsDocLoader*>::ForwardIterator iter(mChildList);
    2400           3 :   while (iter.HasMore()) {
    2401           0 :     nsCOMPtr<nsIDocShell> shell = do_QueryObject(iter.GetNext());
    2402           0 :     if (shell) {
    2403           0 :       shell->SetAffectPrivateSessionLifetime(aAffectLifetime);
    2404             :     }
    2405             :   }
    2406           6 :   return NS_OK;
    2407             : }
    2408             : 
    2409             : NS_IMETHODIMP
    2410           3 : nsDocShell::GetAffectPrivateSessionLifetime(bool* aAffectLifetime)
    2411             : {
    2412           3 :   *aAffectLifetime = mAffectPrivateSessionLifetime;
    2413           3 :   return NS_OK;
    2414             : }
    2415             : 
    2416             : NS_IMETHODIMP
    2417           1 : nsDocShell::AddWeakPrivacyTransitionObserver(
    2418             :     nsIPrivacyTransitionObserver* aObserver)
    2419             : {
    2420           2 :   nsWeakPtr weakObs = do_GetWeakReference(aObserver);
    2421           1 :   if (!weakObs) {
    2422           0 :     return NS_ERROR_NOT_AVAILABLE;
    2423             :   }
    2424           1 :   return mPrivacyObservers.AppendElement(weakObs) ? NS_OK : NS_ERROR_FAILURE;
    2425             : }
    2426             : 
    2427             : NS_IMETHODIMP
    2428           0 : nsDocShell::AddWeakReflowObserver(nsIReflowObserver* aObserver)
    2429             : {
    2430           0 :   nsWeakPtr weakObs = do_GetWeakReference(aObserver);
    2431           0 :   if (!weakObs) {
    2432           0 :     return NS_ERROR_FAILURE;
    2433             :   }
    2434           0 :   return mReflowObservers.AppendElement(weakObs) ? NS_OK : NS_ERROR_FAILURE;
    2435             : }
    2436             : 
    2437             : NS_IMETHODIMP
    2438           0 : nsDocShell::RemoveWeakReflowObserver(nsIReflowObserver* aObserver)
    2439             : {
    2440           0 :   nsWeakPtr obs = do_GetWeakReference(aObserver);
    2441           0 :   return mReflowObservers.RemoveElement(obs) ? NS_OK : NS_ERROR_FAILURE;
    2442             : }
    2443             : 
    2444             : NS_IMETHODIMP
    2445          29 : nsDocShell::NotifyReflowObservers(bool aInterruptible,
    2446             :                                   DOMHighResTimeStamp aStart,
    2447             :                                   DOMHighResTimeStamp aEnd)
    2448             : {
    2449          58 :   nsTObserverArray<nsWeakPtr>::ForwardIterator iter(mReflowObservers);
    2450          29 :   while (iter.HasMore()) {
    2451           0 :     nsWeakPtr ref = iter.GetNext();
    2452           0 :     nsCOMPtr<nsIReflowObserver> obs = do_QueryReferent(ref);
    2453           0 :     if (!obs) {
    2454           0 :       mReflowObservers.RemoveElement(ref);
    2455           0 :     } else if (aInterruptible) {
    2456           0 :       obs->ReflowInterruptible(aStart, aEnd);
    2457             :     } else {
    2458           0 :       obs->Reflow(aStart, aEnd);
    2459             :     }
    2460             :   }
    2461          58 :   return NS_OK;
    2462             : }
    2463             : 
    2464             : NS_IMETHODIMP
    2465           2 : nsDocShell::GetAllowMetaRedirects(bool* aReturn)
    2466             : {
    2467           2 :   NS_ENSURE_ARG_POINTER(aReturn);
    2468             : 
    2469           2 :   *aReturn = mAllowMetaRedirects;
    2470           2 :   if (!mAllowMetaRedirects) {
    2471           0 :     return NS_OK;
    2472             :   }
    2473             : 
    2474             :   bool unsafe;
    2475           2 :   *aReturn = NS_SUCCEEDED(GetChannelIsUnsafe(&unsafe)) && !unsafe;
    2476           2 :   return NS_OK;
    2477             : }
    2478             : 
    2479             : NS_IMETHODIMP
    2480           2 : nsDocShell::SetAllowMetaRedirects(bool aValue)
    2481             : {
    2482           2 :   mAllowMetaRedirects = aValue;
    2483           2 :   return NS_OK;
    2484             : }
    2485             : 
    2486             : NS_IMETHODIMP
    2487           9 : nsDocShell::GetAllowSubframes(bool* aAllowSubframes)
    2488             : {
    2489           9 :   NS_ENSURE_ARG_POINTER(aAllowSubframes);
    2490             : 
    2491           9 :   *aAllowSubframes = mAllowSubframes;
    2492           9 :   return NS_OK;
    2493             : }
    2494             : 
    2495             : NS_IMETHODIMP
    2496           2 : nsDocShell::SetAllowSubframes(bool aAllowSubframes)
    2497             : {
    2498           2 :   mAllowSubframes = aAllowSubframes;
    2499           2 :   return NS_OK;
    2500             : }
    2501             : 
    2502             : NS_IMETHODIMP
    2503           3 : nsDocShell::GetAllowImages(bool* aAllowImages)
    2504             : {
    2505           3 :   NS_ENSURE_ARG_POINTER(aAllowImages);
    2506             : 
    2507           3 :   *aAllowImages = mAllowImages;
    2508           3 :   return NS_OK;
    2509             : }
    2510             : 
    2511             : NS_IMETHODIMP
    2512           2 : nsDocShell::SetAllowImages(bool aAllowImages)
    2513             : {
    2514           2 :   mAllowImages = aAllowImages;
    2515           2 :   return NS_OK;
    2516             : }
    2517             : 
    2518             : NS_IMETHODIMP
    2519           2 : nsDocShell::GetAllowMedia(bool* aAllowMedia)
    2520             : {
    2521           2 :   *aAllowMedia = mAllowMedia;
    2522           2 :   return NS_OK;
    2523             : }
    2524             : 
    2525             : NS_IMETHODIMP
    2526           2 : nsDocShell::SetAllowMedia(bool aAllowMedia)
    2527             : {
    2528           2 :   mAllowMedia = aAllowMedia;
    2529             : 
    2530             :   // Mute or unmute audio contexts attached to the inner window.
    2531           2 :   if (mScriptGlobal) {
    2532           0 :     if (nsPIDOMWindowInner* innerWin =
    2533           0 :         mScriptGlobal->AsOuter()->GetCurrentInnerWindow()) {
    2534           0 :       if (aAllowMedia) {
    2535           0 :         innerWin->UnmuteAudioContexts();
    2536             :       } else {
    2537           0 :         innerWin->MuteAudioContexts();
    2538             :       }
    2539             :     }
    2540             :   }
    2541             : 
    2542           2 :   return NS_OK;
    2543             : }
    2544             : 
    2545             : NS_IMETHODIMP
    2546           6 : nsDocShell::GetAllowDNSPrefetch(bool* aAllowDNSPrefetch)
    2547             : {
    2548           6 :   *aAllowDNSPrefetch = mAllowDNSPrefetch;
    2549           6 :   return NS_OK;
    2550             : }
    2551             : 
    2552             : NS_IMETHODIMP
    2553           4 : nsDocShell::SetAllowDNSPrefetch(bool aAllowDNSPrefetch)
    2554             : {
    2555           4 :   mAllowDNSPrefetch = aAllowDNSPrefetch;
    2556           4 :   return NS_OK;
    2557             : }
    2558             : 
    2559             : NS_IMETHODIMP
    2560           2 : nsDocShell::GetAllowWindowControl(bool* aAllowWindowControl)
    2561             : {
    2562           2 :   *aAllowWindowControl = mAllowWindowControl;
    2563           2 :   return NS_OK;
    2564             : }
    2565             : 
    2566             : NS_IMETHODIMP
    2567           2 : nsDocShell::SetAllowWindowControl(bool aAllowWindowControl)
    2568             : {
    2569           2 :   mAllowWindowControl = aAllowWindowControl;
    2570           2 :   return NS_OK;
    2571             : }
    2572             : 
    2573             : NS_IMETHODIMP
    2574           0 : nsDocShell::GetAllowContentRetargeting(bool* aAllowContentRetargeting)
    2575             : {
    2576           0 :   *aAllowContentRetargeting = mAllowContentRetargeting;
    2577           0 :   return NS_OK;
    2578             : }
    2579             : 
    2580             : NS_IMETHODIMP
    2581           2 : nsDocShell::SetAllowContentRetargeting(bool aAllowContentRetargeting)
    2582             : {
    2583           2 :   mAllowContentRetargetingOnChildren = aAllowContentRetargeting;
    2584           2 :   mAllowContentRetargeting = aAllowContentRetargeting;
    2585           2 :   return NS_OK;
    2586             : }
    2587             : 
    2588             : NS_IMETHODIMP
    2589           2 : nsDocShell::GetAllowContentRetargetingOnChildren(
    2590             :     bool* aAllowContentRetargetingOnChildren)
    2591             : {
    2592           2 :   *aAllowContentRetargetingOnChildren = mAllowContentRetargetingOnChildren;
    2593           2 :   return NS_OK;
    2594             : }
    2595             : 
    2596             : NS_IMETHODIMP
    2597           0 : nsDocShell::SetAllowContentRetargetingOnChildren(
    2598             :     bool aAllowContentRetargetingOnChildren)
    2599             : {
    2600           0 :   mAllowContentRetargetingOnChildren = aAllowContentRetargetingOnChildren;
    2601           0 :   return NS_OK;
    2602             : }
    2603             : 
    2604             : NS_IMETHODIMP
    2605           0 : nsDocShell::GetInheritPrivateBrowsingId(bool* aInheritPrivateBrowsingId)
    2606             : {
    2607           0 :   *aInheritPrivateBrowsingId = mInheritPrivateBrowsingId;
    2608           0 :   return NS_OK;
    2609             : }
    2610             : 
    2611             : NS_IMETHODIMP
    2612           0 : nsDocShell::SetInheritPrivateBrowsingId(bool aInheritPrivateBrowsingId)
    2613             : {
    2614           0 :   mInheritPrivateBrowsingId = aInheritPrivateBrowsingId;
    2615           0 :   return NS_OK;
    2616             : }
    2617             : 
    2618             : NS_IMETHODIMP
    2619           0 : nsDocShell::GetFullscreenAllowed(bool* aFullscreenAllowed)
    2620             : {
    2621           0 :   NS_ENSURE_ARG_POINTER(aFullscreenAllowed);
    2622             : 
    2623             :   // Browsers and apps have their mFullscreenAllowed retrieved from their
    2624             :   // corresponding iframe in their parent upon creation.
    2625           0 :   if (mFullscreenAllowed != CHECK_ATTRIBUTES) {
    2626           0 :     *aFullscreenAllowed = (mFullscreenAllowed == PARENT_ALLOWS);
    2627           0 :     return NS_OK;
    2628             :   }
    2629             : 
    2630             :   // Assume false until we determine otherwise...
    2631           0 :   *aFullscreenAllowed = false;
    2632             : 
    2633           0 :   nsCOMPtr<nsPIDOMWindowOuter> win = GetWindow();
    2634           0 :   if (!win) {
    2635           0 :     return NS_OK;
    2636             :   }
    2637           0 :   if (nsCOMPtr<Element> frameElement = win->GetFrameElementInternal()) {
    2638           0 :     if (frameElement->IsXULElement()) {
    2639           0 :       if (frameElement->HasAttr(kNameSpaceID_None,
    2640             :                                 nsGkAtoms::disablefullscreen)) {
    2641             :         // Document inside this frame is explicitly disabled.
    2642           0 :         return NS_OK;
    2643             :       }
    2644             :     } else {
    2645             :       // We do not allow document inside any containing element other
    2646             :       // than iframe to enter fullscreen.
    2647           0 :       if (frameElement->IsHTMLElement(nsGkAtoms::iframe)) {
    2648             :         // If any ancestor iframe does not have allowfullscreen attribute
    2649             :         // set, then fullscreen is not allowed.
    2650           0 :         if (!frameElement->HasAttr(kNameSpaceID_None,
    2651           0 :                                   nsGkAtoms::allowfullscreen) &&
    2652           0 :             !frameElement->HasAttr(kNameSpaceID_None,
    2653             :                                   nsGkAtoms::mozallowfullscreen)) {
    2654           0 :           return NS_OK;
    2655             :         }
    2656           0 :       } else if (frameElement->IsHTMLElement(nsGkAtoms::embed)) {
    2657             :         // Respect allowfullscreen only if this is a rewritten YouTube embed.
    2658             :         nsCOMPtr<nsIObjectLoadingContent> objectLoadingContent =
    2659           0 :           do_QueryInterface(frameElement);
    2660           0 :         if (!objectLoadingContent) {
    2661           0 :           return NS_OK;
    2662             :         }
    2663             :         nsObjectLoadingContent* olc =
    2664           0 :           static_cast<nsObjectLoadingContent*>(objectLoadingContent.get());
    2665           0 :         if (!olc->IsRewrittenYoutubeEmbed()) {
    2666           0 :           return NS_OK;
    2667             :         }
    2668             :         // We don't have to check prefixed attributes because Flash does not
    2669             :         // support them.
    2670           0 :         if (!frameElement->HasAttr(kNameSpaceID_None,
    2671             :                                   nsGkAtoms::allowfullscreen)) {
    2672           0 :           return NS_OK;
    2673             :         }
    2674             :       } else {
    2675             :         // neither iframe nor embed
    2676           0 :         return NS_OK;
    2677             :       }
    2678             :     }
    2679             :   }
    2680             : 
    2681             :   // If we have no parent then we're the root docshell; no ancestor of the
    2682             :   // original docshell doesn't have a allowfullscreen attribute, so
    2683             :   // report fullscreen as allowed.
    2684           0 :   RefPtr<nsDocShell> parent = GetParentDocshell();
    2685           0 :   if (!parent) {
    2686           0 :     *aFullscreenAllowed = true;
    2687           0 :     return NS_OK;
    2688             :   }
    2689             : 
    2690             :   // Otherwise, we have a parent, continue the checking for
    2691             :   // mozFullscreenAllowed in the parent docshell's ancestors.
    2692           0 :   return parent->GetFullscreenAllowed(aFullscreenAllowed);
    2693             : }
    2694             : 
    2695             : NS_IMETHODIMP
    2696           1 : nsDocShell::SetFullscreenAllowed(bool aFullscreenAllowed)
    2697             : {
    2698           1 :   if (!nsIDocShell::GetIsMozBrowser()) {
    2699             :     // Only allow setting of fullscreenAllowed on content/process boundaries.
    2700             :     // At non-boundaries the fullscreenAllowed attribute is calculated based on
    2701             :     // whether all enclosing frames have the "mozFullscreenAllowed" attribute
    2702             :     // set to "true". fullscreenAllowed is set at the process boundaries to
    2703             :     // propagate the value of the parent's "mozFullscreenAllowed" attribute
    2704             :     // across process boundaries.
    2705           1 :     return NS_ERROR_UNEXPECTED;
    2706             :   }
    2707           0 :   mFullscreenAllowed = (aFullscreenAllowed ? PARENT_ALLOWS : PARENT_PROHIBITS);
    2708           0 :   return NS_OK;
    2709             : }
    2710             : 
    2711             : ScreenOrientationInternal
    2712           6 : nsDocShell::OrientationLock()
    2713             : {
    2714           6 :   return mOrientationLock;
    2715             : }
    2716             : 
    2717             : void
    2718           0 : nsDocShell::SetOrientationLock(ScreenOrientationInternal aOrientationLock)
    2719             : {
    2720           0 :   mOrientationLock = aOrientationLock;
    2721           0 : }
    2722             : 
    2723             : NS_IMETHODIMP
    2724           5 : nsDocShell::GetMayEnableCharacterEncodingMenu(
    2725             :     bool* aMayEnableCharacterEncodingMenu)
    2726             : {
    2727           5 :   *aMayEnableCharacterEncodingMenu = false;
    2728           5 :   if (!mContentViewer) {
    2729           0 :     return NS_OK;
    2730             :   }
    2731           5 :   nsIDocument* doc = mContentViewer->GetDocument();
    2732           5 :   if (!doc) {
    2733           0 :     return NS_OK;
    2734             :   }
    2735           5 :   if (doc->WillIgnoreCharsetOverride()) {
    2736           3 :     return NS_OK;
    2737             :   }
    2738             : 
    2739           2 :   *aMayEnableCharacterEncodingMenu = true;
    2740           2 :   return NS_OK;
    2741             : }
    2742             : 
    2743             : NS_IMETHODIMP
    2744           0 : nsDocShell::GetDocShellEnumerator(int32_t aItemType, int32_t aDirection,
    2745             :                                   nsISimpleEnumerator** aResult)
    2746             : {
    2747           0 :   NS_ENSURE_ARG_POINTER(aResult);
    2748           0 :   *aResult = nullptr;
    2749             : 
    2750           0 :   RefPtr<nsDocShellEnumerator> docShellEnum;
    2751           0 :   if (aDirection == ENUMERATE_FORWARDS) {
    2752           0 :     docShellEnum = new nsDocShellForwardsEnumerator;
    2753             :   } else {
    2754           0 :     docShellEnum = new nsDocShellBackwardsEnumerator;
    2755             :   }
    2756             : 
    2757           0 :   nsresult rv = docShellEnum->SetEnumDocShellType(aItemType);
    2758           0 :   if (NS_FAILED(rv)) {
    2759           0 :     return rv;
    2760             :   }
    2761             : 
    2762           0 :   rv = docShellEnum->SetEnumerationRootItem((nsIDocShellTreeItem*)this);
    2763           0 :   if (NS_FAILED(rv)) {
    2764           0 :     return rv;
    2765             :   }
    2766             : 
    2767           0 :   rv = docShellEnum->First();
    2768           0 :   if (NS_FAILED(rv)) {
    2769           0 :     return rv;
    2770             :   }
    2771             : 
    2772           0 :   rv = docShellEnum->QueryInterface(NS_GET_IID(nsISimpleEnumerator),
    2773           0 :                                     (void**)aResult);
    2774             : 
    2775           0 :   return rv;
    2776             : }
    2777             : 
    2778             : NS_IMETHODIMP
    2779          39 : nsDocShell::GetAppType(uint32_t* aAppType)
    2780             : {
    2781          39 :   *aAppType = mAppType;
    2782          39 :   return NS_OK;
    2783             : }
    2784             : 
    2785             : NS_IMETHODIMP
    2786           0 : nsDocShell::SetAppType(uint32_t aAppType)
    2787             : {
    2788           0 :   mAppType = aAppType;
    2789           0 :   return NS_OK;
    2790             : }
    2791             : 
    2792             : NS_IMETHODIMP
    2793           0 : nsDocShell::GetAllowAuth(bool* aAllowAuth)
    2794             : {
    2795           0 :   *aAllowAuth = mAllowAuth;
    2796           0 :   return NS_OK;
    2797             : }
    2798             : 
    2799             : NS_IMETHODIMP
    2800           0 : nsDocShell::SetAllowAuth(bool aAllowAuth)
    2801             : {
    2802           0 :   mAllowAuth = aAllowAuth;
    2803           0 :   return NS_OK;
    2804             : }
    2805             : 
    2806             : NS_IMETHODIMP
    2807           0 : nsDocShell::GetZoom(float* aZoom)
    2808             : {
    2809           0 :   NS_ENSURE_ARG_POINTER(aZoom);
    2810           0 :   *aZoom = 1.0f;
    2811           0 :   return NS_OK;
    2812             : }
    2813             : 
    2814             : NS_IMETHODIMP
    2815           0 : nsDocShell::SetZoom(float aZoom)
    2816             : {
    2817           0 :   return NS_ERROR_NOT_IMPLEMENTED;
    2818             : }
    2819             : 
    2820             : NS_IMETHODIMP
    2821           3 : nsDocShell::GetMarginWidth(int32_t* aWidth)
    2822             : {
    2823           3 :   NS_ENSURE_ARG_POINTER(aWidth);
    2824             : 
    2825           3 :   *aWidth = mMarginWidth;
    2826           3 :   return NS_OK;
    2827             : }
    2828             : 
    2829             : NS_IMETHODIMP
    2830           1 : nsDocShell::SetMarginWidth(int32_t aWidth)
    2831             : {
    2832           1 :   mMarginWidth = aWidth;
    2833           1 :   return NS_OK;
    2834             : }
    2835             : 
    2836             : NS_IMETHODIMP
    2837           3 : nsDocShell::GetMarginHeight(int32_t* aHeight)
    2838             : {
    2839           3 :   NS_ENSURE_ARG_POINTER(aHeight);
    2840             : 
    2841           3 :   *aHeight = mMarginHeight;
    2842           3 :   return NS_OK;
    2843             : }
    2844             : 
    2845             : NS_IMETHODIMP
    2846           1 : nsDocShell::SetMarginHeight(int32_t aHeight)
    2847             : {
    2848           1 :   mMarginHeight = aHeight;
    2849           1 :   return NS_OK;
    2850             : }
    2851             : 
    2852             : NS_IMETHODIMP
    2853           0 : nsDocShell::GetBusyFlags(uint32_t* aBusyFlags)
    2854             : {
    2855           0 :   NS_ENSURE_ARG_POINTER(aBusyFlags);
    2856             : 
    2857           0 :   *aBusyFlags = mBusyFlags;
    2858           0 :   return NS_OK;
    2859             : }
    2860             : 
    2861             : NS_IMETHODIMP
    2862           0 : nsDocShell::TabToTreeOwner(bool aForward, bool aForDocumentNavigation, bool* aTookFocus)
    2863             : {
    2864           0 :   NS_ENSURE_ARG_POINTER(aTookFocus);
    2865             : 
    2866           0 :   nsCOMPtr<nsIWebBrowserChromeFocus> chromeFocus = do_GetInterface(mTreeOwner);
    2867           0 :   if (chromeFocus) {
    2868           0 :     if (aForward) {
    2869           0 :       *aTookFocus = NS_SUCCEEDED(chromeFocus->FocusNextElement(aForDocumentNavigation));
    2870             :     } else {
    2871           0 :       *aTookFocus = NS_SUCCEEDED(chromeFocus->FocusPrevElement(aForDocumentNavigation));
    2872             :     }
    2873             :   } else {
    2874           0 :     *aTookFocus = false;
    2875             :   }
    2876             : 
    2877           0 :   return NS_OK;
    2878             : }
    2879             : 
    2880             : NS_IMETHODIMP
    2881           3 : nsDocShell::GetSecurityUI(nsISecureBrowserUI** aSecurityUI)
    2882             : {
    2883           3 :   NS_IF_ADDREF(*aSecurityUI = mSecurityUI);
    2884           3 :   return NS_OK;
    2885             : }
    2886             : 
    2887             : NS_IMETHODIMP
    2888           2 : nsDocShell::SetSecurityUI(nsISecureBrowserUI* aSecurityUI)
    2889             : {
    2890           2 :   mSecurityUI = aSecurityUI;
    2891           2 :   mSecurityUI->SetDocShell(this);
    2892           2 :   return NS_OK;
    2893             : }
    2894             : 
    2895             : NS_IMETHODIMP
    2896           0 : nsDocShell::GetUseErrorPages(bool* aUseErrorPages)
    2897             : {
    2898           0 :   *aUseErrorPages = UseErrorPages();
    2899           0 :   return NS_OK;
    2900             : }
    2901             : 
    2902             : NS_IMETHODIMP
    2903           0 : nsDocShell::SetUseErrorPages(bool aUseErrorPages)
    2904             : {
    2905             :   // If mUseErrorPages is set explicitly, stop using sUseErrorPages.
    2906           0 :   if (mObserveErrorPages) {
    2907           0 :     mObserveErrorPages = false;
    2908             :   }
    2909           0 :   mUseErrorPages = aUseErrorPages;
    2910           0 :   return NS_OK;
    2911             : }
    2912             : 
    2913             : NS_IMETHODIMP
    2914           1 : nsDocShell::GetPreviousTransIndex(int32_t* aPreviousTransIndex)
    2915             : {
    2916           1 :   *aPreviousTransIndex = mPreviousTransIndex;
    2917           1 :   return NS_OK;
    2918             : }
    2919             : 
    2920             : NS_IMETHODIMP
    2921           1 : nsDocShell::GetLoadedTransIndex(int32_t* aLoadedTransIndex)
    2922             : {
    2923           1 :   *aLoadedTransIndex = mLoadedTransIndex;
    2924           1 :   return NS_OK;
    2925             : }
    2926             : 
    2927             : NS_IMETHODIMP
    2928           0 : nsDocShell::HistoryPurged(int32_t aNumEntries)
    2929             : {
    2930             :   // These indices are used for fastback cache eviction, to determine
    2931             :   // which session history entries are candidates for content viewer
    2932             :   // eviction.  We need to adjust by the number of entries that we
    2933             :   // just purged from history, so that we look at the right session history
    2934             :   // entries during eviction.
    2935           0 :   mPreviousTransIndex = std::max(-1, mPreviousTransIndex - aNumEntries);
    2936           0 :   mLoadedTransIndex = std::max(0, mLoadedTransIndex - aNumEntries);
    2937             : 
    2938           0 :   nsTObserverArray<nsDocLoader*>::ForwardIterator iter(mChildList);
    2939           0 :   while (iter.HasMore()) {
    2940           0 :     nsCOMPtr<nsIDocShell> shell = do_QueryObject(iter.GetNext());
    2941           0 :     if (shell) {
    2942           0 :       shell->HistoryPurged(aNumEntries);
    2943             :     }
    2944             :   }
    2945             : 
    2946           0 :   return NS_OK;
    2947             : }
    2948             : 
    2949             : nsresult
    2950           0 : nsDocShell::HistoryTransactionRemoved(int32_t aIndex)
    2951             : {
    2952             :   // These indices are used for fastback cache eviction, to determine
    2953             :   // which session history entries are candidates for content viewer
    2954             :   // eviction.  We need to adjust by the number of entries that we
    2955             :   // just purged from history, so that we look at the right session history
    2956             :   // entries during eviction.
    2957           0 :   if (aIndex == mPreviousTransIndex) {
    2958           0 :     mPreviousTransIndex = -1;
    2959           0 :   } else if (aIndex < mPreviousTransIndex) {
    2960           0 :     --mPreviousTransIndex;
    2961             :   }
    2962           0 :   if (mLoadedTransIndex == aIndex) {
    2963           0 :     mLoadedTransIndex = 0;
    2964           0 :   } else if (aIndex < mLoadedTransIndex) {
    2965           0 :     --mLoadedTransIndex;
    2966             :   }
    2967             : 
    2968           0 :   nsTObserverArray<nsDocLoader*>::ForwardIterator iter(mChildList);
    2969           0 :   while (iter.HasMore()) {
    2970           0 :     nsCOMPtr<nsIDocShell> shell = do_QueryObject(iter.GetNext());
    2971           0 :     if (shell) {
    2972           0 :       static_cast<nsDocShell*>(shell.get())->HistoryTransactionRemoved(aIndex);
    2973             :     }
    2974             :   }
    2975             : 
    2976           0 :   return NS_OK;
    2977             : }
    2978             : 
    2979             : NS_IMETHODIMP
    2980           1 : nsDocShell::SetRecordProfileTimelineMarkers(bool aValue)
    2981             : {
    2982           1 :   bool currentValue = nsIDocShell::GetRecordProfileTimelineMarkers();
    2983           1 :   if (currentValue == aValue) {
    2984           1 :     return NS_OK;
    2985             :   }
    2986             : 
    2987           0 :   RefPtr<TimelineConsumers> timelines = TimelineConsumers::Get();
    2988           0 :   if (!timelines) {
    2989           0 :     return NS_OK;
    2990             :   }
    2991             : 
    2992           0 :   if (aValue) {
    2993           0 :     MOZ_ASSERT(!timelines->HasConsumer(this));
    2994           0 :     timelines->AddConsumer(this);
    2995           0 :     MOZ_ASSERT(timelines->HasConsumer(this));
    2996           0 :     UseEntryScriptProfiling();
    2997             :   } else {
    2998           0 :     MOZ_ASSERT(timelines->HasConsumer(this));
    2999           0 :     timelines->RemoveConsumer(this);
    3000           0 :     MOZ_ASSERT(!timelines->HasConsumer(this));
    3001           0 :     UnuseEntryScriptProfiling();
    3002             :   }
    3003             : 
    3004           0 :   return NS_OK;
    3005             : }
    3006             : 
    3007             : NS_IMETHODIMP
    3008         260 : nsDocShell::GetRecordProfileTimelineMarkers(bool* aValue)
    3009             : {
    3010         260 :   *aValue = !!mObserved;
    3011         260 :   return NS_OK;
    3012             : }
    3013             : 
    3014             : nsresult
    3015           0 : nsDocShell::PopProfileTimelineMarkers(
    3016             :     JSContext* aCx,
    3017             :     JS::MutableHandle<JS::Value> aOut)
    3018             : {
    3019           0 :   RefPtr<TimelineConsumers> timelines = TimelineConsumers::Get();
    3020           0 :   if (!timelines) {
    3021           0 :     return NS_OK;
    3022             :   }
    3023             : 
    3024           0 :   nsTArray<dom::ProfileTimelineMarker> store;
    3025           0 :   SequenceRooter<dom::ProfileTimelineMarker> rooter(aCx, &store);
    3026             : 
    3027           0 :   timelines->PopMarkers(this, aCx, store);
    3028             : 
    3029           0 :   if (!ToJSValue(aCx, store, aOut)) {
    3030           0 :     JS_ClearPendingException(aCx);
    3031           0 :     return NS_ERROR_UNEXPECTED;
    3032             :   }
    3033             : 
    3034           0 :   return NS_OK;
    3035             : }
    3036             : 
    3037             : nsresult
    3038           0 : nsDocShell::Now(DOMHighResTimeStamp* aWhen)
    3039             : {
    3040           0 :   *aWhen = (TimeStamp::Now() - TimeStamp::ProcessCreation()).ToMilliseconds();
    3041           0 :   return NS_OK;
    3042             : }
    3043             : 
    3044             : NS_IMETHODIMP
    3045           0 : nsDocShell::SetWindowDraggingAllowed(bool aValue)
    3046             : {
    3047           0 :   RefPtr<nsDocShell> parent = GetParentDocshell();
    3048           0 :   if (!aValue && mItemType == typeChrome && !parent) {
    3049             :     // Window dragging is always allowed for top level
    3050             :     // chrome docshells.
    3051           0 :     return NS_ERROR_FAILURE;
    3052             :   }
    3053           0 :   mWindowDraggingAllowed = aValue;
    3054           0 :   return NS_OK;
    3055             : }
    3056             : 
    3057             : NS_IMETHODIMP
    3058          26 : nsDocShell::GetWindowDraggingAllowed(bool* aValue)
    3059             : {
    3060             :   // window dragging regions in CSS (-moz-window-drag:drag)
    3061             :   // can be slow. Default behavior is to only allow it for
    3062             :   // chrome top level windows.
    3063          52 :   RefPtr<nsDocShell> parent = GetParentDocshell();
    3064          26 :   if (mItemType == typeChrome && !parent) {
    3065             :     // Top level chrome window
    3066          24 :     *aValue = true;
    3067             :   } else {
    3068           2 :     *aValue = mWindowDraggingAllowed;
    3069             :   }
    3070          52 :   return NS_OK;
    3071             : }
    3072             : 
    3073             : nsIDOMStorageManager*
    3074           2 : nsDocShell::TopSessionStorageManager()
    3075             : {
    3076             :   nsresult rv;
    3077             : 
    3078           4 :   nsCOMPtr<nsIDocShellTreeItem> topItem;
    3079           2 :   rv = GetSameTypeRootTreeItem(getter_AddRefs(topItem));
    3080           2 :   if (NS_FAILED(rv)) {
    3081           0 :     return nullptr;
    3082             :   }
    3083             : 
    3084           2 :   if (!topItem) {
    3085           0 :     return nullptr;
    3086             :   }
    3087             : 
    3088           2 :   nsDocShell* topDocShell = static_cast<nsDocShell*>(topItem.get());
    3089           2 :   if (topDocShell != this) {
    3090           0 :     return topDocShell->TopSessionStorageManager();
    3091             :   }
    3092             : 
    3093           2 :   if (!mSessionStorageManager) {
    3094             :     mSessionStorageManager =
    3095           1 :       do_CreateInstance("@mozilla.org/dom/sessionStorage-manager;1");
    3096             :   }
    3097             : 
    3098           2 :   return mSessionStorageManager;
    3099             : }
    3100             : 
    3101             : NS_IMETHODIMP
    3102           0 : nsDocShell::GetCurrentDocumentChannel(nsIChannel** aResult)
    3103             : {
    3104           0 :   NS_IF_ADDREF(*aResult = GetCurrentDocChannel());
    3105           0 :   return NS_OK;
    3106             : }
    3107             : 
    3108             : nsIChannel*
    3109           8 : nsDocShell::GetCurrentDocChannel()
    3110             : {
    3111           8 :   if (mContentViewer) {
    3112           7 :     nsIDocument* doc = mContentViewer->GetDocument();
    3113           7 :     if (doc) {
    3114           7 :       return doc->GetChannel();
    3115             :     }
    3116             :   }
    3117           1 :   return nullptr;
    3118             : }
    3119             : 
    3120             : NS_IMETHODIMP
    3121           0 : nsDocShell::AddWeakScrollObserver(nsIScrollObserver* aObserver)
    3122             : {
    3123           0 :   nsWeakPtr weakObs = do_GetWeakReference(aObserver);
    3124           0 :   if (!weakObs) {
    3125           0 :     return NS_ERROR_FAILURE;
    3126             :   }
    3127           0 :   return mScrollObservers.AppendElement(weakObs) ? NS_OK : NS_ERROR_FAILURE;
    3128             : }
    3129             : 
    3130             : NS_IMETHODIMP
    3131           0 : nsDocShell::RemoveWeakScrollObserver(nsIScrollObserver* aObserver)
    3132             : {
    3133           0 :   nsWeakPtr obs = do_GetWeakReference(aObserver);
    3134           0 :   return mScrollObservers.RemoveElement(obs) ? NS_OK : NS_ERROR_FAILURE;
    3135             : }
    3136             : 
    3137             : void
    3138           0 : nsDocShell::NotifyAsyncPanZoomStarted()
    3139             : {
    3140           0 :   nsTObserverArray<nsWeakPtr>::ForwardIterator iter(mScrollObservers);
    3141           0 :   while (iter.HasMore()) {
    3142           0 :     nsWeakPtr ref = iter.GetNext();
    3143           0 :     nsCOMPtr<nsIScrollObserver> obs = do_QueryReferent(ref);
    3144           0 :     if (obs) {
    3145           0 :       obs->AsyncPanZoomStarted();
    3146             :     } else {
    3147           0 :       mScrollObservers.RemoveElement(ref);
    3148             :     }
    3149             :   }
    3150           0 : }
    3151             : 
    3152             : void
    3153           0 : nsDocShell::NotifyAsyncPanZoomStopped()
    3154             : {
    3155           0 :   nsTObserverArray<nsWeakPtr>::ForwardIterator iter(mScrollObservers);
    3156           0 :   while (iter.HasMore()) {
    3157           0 :     nsWeakPtr ref = iter.GetNext();
    3158           0 :     nsCOMPtr<nsIScrollObserver> obs = do_QueryReferent(ref);
    3159           0 :     if (obs) {
    3160           0 :       obs->AsyncPanZoomStopped();
    3161             :     } else {
    3162           0 :       mScrollObservers.RemoveElement(ref);
    3163             :     }
    3164             :   }
    3165           0 : }
    3166             : 
    3167             : NS_IMETHODIMP
    3168           0 : nsDocShell::NotifyScrollObservers()
    3169             : {
    3170           0 :   nsTObserverArray<nsWeakPtr>::ForwardIterator iter(mScrollObservers);
    3171           0 :   while (iter.HasMore()) {
    3172           0 :     nsWeakPtr ref = iter.GetNext();
    3173           0 :     nsCOMPtr<nsIScrollObserver> obs = do_QueryReferent(ref);
    3174           0 :     if (obs) {
    3175           0 :       obs->ScrollPositionChanged();
    3176             :     } else {
    3177           0 :       mScrollObservers.RemoveElement(ref);
    3178             :     }
    3179             :   }
    3180           0 :   return NS_OK;
    3181             : }
    3182             : 
    3183             : //*****************************************************************************
    3184             : // nsDocShell::nsIDocShellTreeItem
    3185             : //*****************************************************************************
    3186             : 
    3187             : NS_IMETHODIMP
    3188           0 : nsDocShell::GetName(nsAString& aName)
    3189             : {
    3190           0 :   aName = mName;
    3191           0 :   return NS_OK;
    3192             : }
    3193             : 
    3194             : NS_IMETHODIMP
    3195           3 : nsDocShell::SetName(const nsAString& aName)
    3196             : {
    3197           3 :   mName = aName;
    3198           3 :   return NS_OK;
    3199             : }
    3200             : 
    3201             : NS_IMETHODIMP
    3202          80 : nsDocShell::NameEquals(const nsAString& aName, bool* aResult)
    3203             : {
    3204          80 :   NS_ENSURE_ARG_POINTER(aResult);
    3205          80 :   *aResult = mName.Equals(aName);
    3206          80 :   return NS_OK;
    3207             : }
    3208             : 
    3209             : NS_IMETHODIMP
    3210           6 : nsDocShell::GetCustomUserAgent(nsAString& aCustomUserAgent)
    3211             : {
    3212           6 :   aCustomUserAgent = mCustomUserAgent;
    3213           6 :   return NS_OK;
    3214             : }
    3215             : 
    3216             : NS_IMETHODIMP
    3217           0 : nsDocShell::SetCustomUserAgent(const nsAString& aCustomUserAgent)
    3218             : {
    3219           0 :   mCustomUserAgent = aCustomUserAgent;
    3220             :   RefPtr<nsGlobalWindow> win = mScriptGlobal ?
    3221           0 :     mScriptGlobal->GetCurrentInnerWindowInternal() : nullptr;
    3222           0 :   if (win) {
    3223           0 :     Navigator* navigator = win->Navigator();
    3224           0 :     if (navigator) {
    3225           0 :       navigator->ClearUserAgentCache();
    3226             :     }
    3227             :   }
    3228             : 
    3229           0 :   uint32_t childCount = mChildList.Length();
    3230           0 :   for (uint32_t i = 0; i < childCount; ++i) {
    3231           0 :     nsCOMPtr<nsIDocShell> childShell = do_QueryInterface(ChildAt(i));
    3232           0 :     if (childShell) {
    3233           0 :       childShell->SetCustomUserAgent(aCustomUserAgent);
    3234             :     }
    3235             :   }
    3236           0 :   return NS_OK;
    3237             : }
    3238             : 
    3239             : NS_IMETHODIMP
    3240          49 : nsDocShell::GetTouchEventsOverride(uint32_t* aTouchEventsOverride)
    3241             : {
    3242          49 :   NS_ENSURE_ARG_POINTER(aTouchEventsOverride);
    3243             : 
    3244          49 :   *aTouchEventsOverride = mTouchEventsOverride;
    3245          49 :   return NS_OK;
    3246             : }
    3247             : 
    3248             : NS_IMETHODIMP
    3249           2 : nsDocShell::SetTouchEventsOverride(uint32_t aTouchEventsOverride)
    3250             : {
    3251           2 :   if (!(aTouchEventsOverride == nsIDocShell::TOUCHEVENTS_OVERRIDE_NONE ||
    3252             :         aTouchEventsOverride == nsIDocShell::TOUCHEVENTS_OVERRIDE_ENABLED ||
    3253             :         aTouchEventsOverride == nsIDocShell::TOUCHEVENTS_OVERRIDE_DISABLED)) {
    3254           0 :     return NS_ERROR_INVALID_ARG;
    3255             :   }
    3256             : 
    3257           2 :   mTouchEventsOverride = aTouchEventsOverride;
    3258             : 
    3259           2 :   uint32_t childCount = mChildList.Length();
    3260           2 :   for (uint32_t i = 0; i < childCount; ++i) {
    3261           0 :     nsCOMPtr<nsIDocShell> childShell = do_QueryInterface(ChildAt(i));
    3262           0 :     if (childShell) {
    3263           0 :       childShell->SetTouchEventsOverride(aTouchEventsOverride);
    3264             :     }
    3265             :   }
    3266           2 :   return NS_OK;
    3267             : }
    3268             : 
    3269             : /* virtual */ int32_t
    3270         417 : nsDocShell::ItemType()
    3271             : {
    3272         417 :   return mItemType;
    3273             : }
    3274             : 
    3275             : NS_IMETHODIMP
    3276           0 : nsDocShell::GetItemType(int32_t* aItemType)
    3277             : {
    3278           0 :   NS_ENSURE_ARG_POINTER(aItemType);
    3279             : 
    3280           0 :   *aItemType = ItemType();
    3281           0 :   return NS_OK;
    3282             : }
    3283             : 
    3284             : NS_IMETHODIMP
    3285           5 : nsDocShell::SetItemType(int32_t aItemType)
    3286             : {
    3287           5 :   NS_ENSURE_ARG((aItemType == typeChrome) || (typeContent == aItemType));
    3288             : 
    3289             :   // Only allow setting the type on root docshells.  Those would be the ones
    3290             :   // that have the docloader service as mParent or have no mParent at all.
    3291             :   nsCOMPtr<nsIDocumentLoader> docLoaderService =
    3292          10 :     do_GetService(NS_DOCUMENTLOADER_SERVICE_CONTRACTID);
    3293           5 :   NS_ENSURE_TRUE(docLoaderService, NS_ERROR_UNEXPECTED);
    3294             : 
    3295           5 :   NS_ENSURE_STATE(!mParent || mParent == docLoaderService);
    3296             : 
    3297           5 :   mItemType = aItemType;
    3298             : 
    3299             :   // disable auth prompting for anything but content
    3300           5 :   mAllowAuth = mItemType == typeContent;
    3301             : 
    3302          10 :   RefPtr<nsPresContext> presContext = nullptr;
    3303           5 :   GetPresContext(getter_AddRefs(presContext));
    3304           5 :   if (presContext) {
    3305           0 :     presContext->UpdateIsChrome();
    3306             :   }
    3307             : 
    3308           5 :   return NS_OK;
    3309             : }
    3310             : 
    3311             : NS_IMETHODIMP
    3312          10 : nsDocShell::GetParent(nsIDocShellTreeItem** aParent)
    3313             : {
    3314          10 :   if (!mParent) {
    3315           0 :     *aParent = nullptr;
    3316             :   } else {
    3317          10 :     CallQueryInterface(mParent, aParent);
    3318             :   }
    3319             :   // Note that in the case when the parent is not an nsIDocShellTreeItem we
    3320             :   // don't want to throw; we just want to return null.
    3321          10 :   return NS_OK;
    3322             : }
    3323             : 
    3324             : already_AddRefed<nsDocShell>
    3325         126 : nsDocShell::GetParentDocshell()
    3326             : {
    3327         252 :   nsCOMPtr<nsIDocShell> docshell = do_QueryInterface(GetAsSupports(mParent));
    3328         252 :   return docshell.forget().downcast<nsDocShell>();
    3329             : }
    3330             : 
    3331             : void
    3332          23 : nsDocShell::RecomputeCanExecuteScripts()
    3333             : {
    3334          23 :   bool old = mCanExecuteScripts;
    3335          46 :   RefPtr<nsDocShell> parent = GetParentDocshell();
    3336             : 
    3337             :   // If we have no tree owner, that means that we've been detached from the
    3338             :   // docshell tree (this is distinct from having no parent dochshell, which
    3339             :   // is the case for root docshells). It would be nice to simply disallow
    3340             :   // script in detached docshells, but bug 986542 demonstrates that this
    3341             :   // behavior breaks at least one website.
    3342             :   //
    3343             :   // So instead, we use our previous value, unless mAllowJavascript has been
    3344             :   // explicitly set to false.
    3345          23 :   if (!mTreeOwner) {
    3346          17 :     mCanExecuteScripts = mCanExecuteScripts && mAllowJavascript;
    3347             :     // If scripting has been explicitly disabled on our docshell, we're done.
    3348           6 :   } else if (!mAllowJavascript) {
    3349           0 :     mCanExecuteScripts = false;
    3350             :     // If we have a parent, inherit.
    3351           6 :   } else if (parent) {
    3352           2 :     mCanExecuteScripts = parent->mCanExecuteScripts;
    3353             :     // Otherwise, we're the root of the tree, and we haven't explicitly disabled
    3354             :     // script. Allow.
    3355             :   } else {
    3356           4 :     mCanExecuteScripts = true;
    3357             :   }
    3358             : 
    3359             :   // Inform our active DOM window.
    3360             :   //
    3361             :   // This will pass the outer, which will be in the scope of the active inner.
    3362          23 :   if (mScriptGlobal && mScriptGlobal->GetGlobalJSObject()) {
    3363             :     xpc::Scriptability& scriptability =
    3364           4 :       xpc::Scriptability::Get(mScriptGlobal->GetGlobalJSObject());
    3365           4 :     scriptability.SetDocShellAllowsScript(mCanExecuteScripts);
    3366             :   }
    3367             : 
    3368             :   // If our value has changed, our children might be affected. Recompute their
    3369             :   // value as well.
    3370          23 :   if (old != mCanExecuteScripts) {
    3371          10 :     nsTObserverArray<nsDocLoader*>::ForwardIterator iter(mChildList);
    3372           5 :     while (iter.HasMore()) {
    3373           0 :       static_cast<nsDocShell*>(iter.GetNext())->RecomputeCanExecuteScripts();
    3374             :     }
    3375             :   }
    3376          23 : }
    3377             : 
    3378             : nsresult
    3379          12 : nsDocShell::SetDocLoaderParent(nsDocLoader* aParent)
    3380             : {
    3381          12 :   bool wasFrame = IsFrame();
    3382             : #ifdef DEBUG
    3383          12 :   bool wasPrivate = UsePrivateBrowsing();
    3384             : #endif
    3385             : 
    3386          12 :   nsresult rv = nsDocLoader::SetDocLoaderParent(aParent);
    3387          12 :   NS_ENSURE_SUCCESS(rv, rv);
    3388             : 
    3389          24 :   nsCOMPtr<nsISupportsPriority> priorityGroup = do_QueryInterface(mLoadGroup);
    3390          12 :   if (wasFrame != IsFrame() && priorityGroup) {
    3391           1 :     priorityGroup->AdjustPriority(wasFrame ? -1 : 1);
    3392             :   }
    3393             : 
    3394             :   // Curse ambiguous nsISupports inheritance!
    3395          12 :   nsISupports* parent = GetAsSupports(aParent);
    3396             : 
    3397             :   // If parent is another docshell, we inherit all their flags for
    3398             :   // allowing plugins, scripting etc.
    3399             :   bool value;
    3400          24 :   nsString customUserAgent;
    3401          24 :   nsCOMPtr<nsIDocShell> parentAsDocShell(do_QueryInterface(parent));
    3402          12 :   if (parentAsDocShell) {
    3403           2 :     if (mAllowPlugins && NS_SUCCEEDED(parentAsDocShell->GetAllowPlugins(&value))) {
    3404           2 :       SetAllowPlugins(value);
    3405             :     }
    3406           2 :     if (mAllowJavascript && NS_SUCCEEDED(parentAsDocShell->GetAllowJavascript(&value))) {
    3407           2 :       SetAllowJavascript(value);
    3408             :     }
    3409           2 :     if (mAllowMetaRedirects && NS_SUCCEEDED(parentAsDocShell->GetAllowMetaRedirects(&value))) {
    3410           2 :       SetAllowMetaRedirects(value);
    3411             :     }
    3412           2 :     if (mAllowSubframes && NS_SUCCEEDED(parentAsDocShell->GetAllowSubframes(&value))) {
    3413           2 :       SetAllowSubframes(value);
    3414             :     }
    3415           2 :     if (mAllowImages && NS_SUCCEEDED(parentAsDocShell->GetAllowImages(&value))) {
    3416           2 :       SetAllowImages(value);
    3417             :     }
    3418           2 :     SetAllowMedia(parentAsDocShell->GetAllowMedia() && mAllowMedia);
    3419           2 :     if (mAllowWindowControl && NS_SUCCEEDED(parentAsDocShell->GetAllowWindowControl(&value))) {
    3420           2 :       SetAllowWindowControl(value);
    3421             :     }
    3422           4 :     SetAllowContentRetargeting(mAllowContentRetargeting &&
    3423           4 :       parentAsDocShell->GetAllowContentRetargetingOnChildren());
    3424           2 :     if (parentAsDocShell->GetIsPrerendered()) {
    3425           0 :       SetIsPrerendered();
    3426             :     }
    3427           2 :     if (NS_SUCCEEDED(parentAsDocShell->GetIsActive(&value))) {
    3428             :       // a prerendered docshell is not active yet
    3429           2 :       SetIsActive(value && !mIsPrerendered);
    3430             :     }
    3431           4 :     if (NS_SUCCEEDED(parentAsDocShell->GetCustomUserAgent(customUserAgent)) &&
    3432           2 :         !customUserAgent.IsEmpty()) {
    3433           0 :       SetCustomUserAgent(customUserAgent);
    3434             :     }
    3435           2 :     if (NS_FAILED(parentAsDocShell->GetAllowDNSPrefetch(&value))) {
    3436           0 :       value = false;
    3437             :     }
    3438           2 :     SetAllowDNSPrefetch(mAllowDNSPrefetch && value);
    3439           2 :     if (mInheritPrivateBrowsingId) {
    3440           2 :       value = parentAsDocShell->GetAffectPrivateSessionLifetime();
    3441           2 :       SetAffectPrivateSessionLifetime(value);
    3442             :     }
    3443             :     uint32_t flags;
    3444           2 :     if (NS_SUCCEEDED(parentAsDocShell->GetDefaultLoadFlags(&flags))) {
    3445           2 :       SetDefaultLoadFlags(flags);
    3446             :     }
    3447             :     uint32_t touchEventsOverride;
    3448           2 :     if (NS_SUCCEEDED(parentAsDocShell->GetTouchEventsOverride(&touchEventsOverride))) {
    3449           2 :       SetTouchEventsOverride(touchEventsOverride);
    3450             :     }
    3451             :   }
    3452             : 
    3453          24 :   nsCOMPtr<nsILoadContext> parentAsLoadContext(do_QueryInterface(parent));
    3454          14 :   if (parentAsLoadContext && mInheritPrivateBrowsingId &&
    3455           2 :       NS_SUCCEEDED(parentAsLoadContext->GetUsePrivateBrowsing(&value))) {
    3456           2 :     SetPrivateBrowsing(value);
    3457             :   }
    3458             : 
    3459          24 :   nsCOMPtr<nsIURIContentListener> parentURIListener(do_GetInterface(parent));
    3460          12 :   if (parentURIListener) {
    3461           2 :     mContentListener->SetParentContentListener(parentURIListener);
    3462             :   }
    3463             : 
    3464             :   // Our parent has changed. Recompute scriptability.
    3465          12 :   RecomputeCanExecuteScripts();
    3466             : 
    3467          12 :   NS_ASSERTION(mInheritPrivateBrowsingId || wasPrivate == UsePrivateBrowsing(),
    3468             :                "Private browsing state changed while inheritance was disabled");
    3469             : 
    3470          12 :   return NS_OK;
    3471             : }
    3472             : 
    3473             : NS_IMETHODIMP
    3474         162 : nsDocShell::GetSameTypeParent(nsIDocShellTreeItem** aParent)
    3475             : {
    3476         162 :   NS_ENSURE_ARG_POINTER(aParent);
    3477         162 :   *aParent = nullptr;
    3478             : 
    3479         162 :   if (nsIDocShell::GetIsMozBrowser()) {
    3480           0 :     return NS_OK;
    3481             :   }
    3482             : 
    3483             :   nsCOMPtr<nsIDocShellTreeItem> parent =
    3484         324 :     do_QueryInterface(GetAsSupports(mParent));
    3485         162 :   if (!parent) {
    3486         120 :     return NS_OK;
    3487             :   }
    3488             : 
    3489          42 :   if (parent->ItemType() == mItemType) {
    3490          20 :     parent.swap(*aParent);
    3491             :   }
    3492          42 :   return NS_OK;
    3493             : }
    3494             : 
    3495             : NS_IMETHODIMP
    3496         315 : nsDocShell::GetSameTypeParentIgnoreBrowserBoundaries(nsIDocShell** aParent)
    3497             : {
    3498         315 :   NS_ENSURE_ARG_POINTER(aParent);
    3499         315 :   *aParent = nullptr;
    3500             : 
    3501             :   nsCOMPtr<nsIDocShellTreeItem> parent =
    3502         630 :     do_QueryInterface(GetAsSupports(mParent));
    3503         315 :   if (!parent) {
    3504         281 :     return NS_OK;
    3505             :   }
    3506             : 
    3507          34 :   if (parent->ItemType() == mItemType) {
    3508          26 :     nsCOMPtr<nsIDocShell> parentDS = do_QueryInterface(parent);
    3509          13 :     parentDS.forget(aParent);
    3510             :   }
    3511          34 :   return NS_OK;
    3512             : }
    3513             : 
    3514             : NS_IMETHODIMP
    3515          49 : nsDocShell::GetRootTreeItem(nsIDocShellTreeItem** aRootTreeItem)
    3516             : {
    3517          49 :   NS_ENSURE_ARG_POINTER(aRootTreeItem);
    3518             : 
    3519          98 :   RefPtr<nsDocShell> root = this;
    3520          98 :   RefPtr<nsDocShell> parent = root->GetParentDocshell();
    3521          49 :   while (parent) {
    3522           0 :     root = parent;
    3523           0 :     parent = root->GetParentDocshell();
    3524             :   }
    3525             : 
    3526          49 :   root.forget(aRootTreeItem);
    3527          49 :   return NS_OK;
    3528             : }
    3529             : 
    3530             : NS_IMETHODIMP
    3531          54 : nsDocShell::GetSameTypeRootTreeItem(nsIDocShellTreeItem** aRootTreeItem)
    3532             : {
    3533          54 :   NS_ENSURE_ARG_POINTER(aRootTreeItem);
    3534          54 :   *aRootTreeItem = static_cast<nsIDocShellTreeItem*>(this);
    3535             : 
    3536         108 :   nsCOMPtr<nsIDocShellTreeItem> parent;
    3537          54 :   NS_ENSURE_SUCCESS(GetSameTypeParent(getter_AddRefs(parent)),
    3538             :                     NS_ERROR_FAILURE);
    3539          70 :   while (parent) {
    3540           8 :     *aRootTreeItem = parent;
    3541           8 :     NS_ENSURE_SUCCESS(
    3542             :       (*aRootTreeItem)->GetSameTypeParent(getter_AddRefs(parent)),
    3543             :       NS_ERROR_FAILURE);
    3544             :   }
    3545          54 :   NS_ADDREF(*aRootTreeItem);
    3546          54 :   return NS_OK;
    3547             : }
    3548             : 
    3549             : NS_IMETHODIMP
    3550           0 : nsDocShell::GetSameTypeRootTreeItemIgnoreBrowserBoundaries(nsIDocShell** aRootTreeItem)
    3551             : {
    3552           0 :     NS_ENSURE_ARG_POINTER(aRootTreeItem);
    3553           0 :     *aRootTreeItem = static_cast<nsIDocShell *>(this);
    3554             : 
    3555           0 :     nsCOMPtr<nsIDocShell> parent;
    3556           0 :     NS_ENSURE_SUCCESS(GetSameTypeParentIgnoreBrowserBoundaries(getter_AddRefs(parent)),
    3557             :                       NS_ERROR_FAILURE);
    3558           0 :     while (parent) {
    3559           0 :       *aRootTreeItem = parent;
    3560           0 :       NS_ENSURE_SUCCESS((*aRootTreeItem)->
    3561             :         GetSameTypeParentIgnoreBrowserBoundaries(getter_AddRefs(parent)),
    3562             :         NS_ERROR_FAILURE);
    3563             :     }
    3564           0 :     NS_ADDREF(*aRootTreeItem);
    3565           0 :     return NS_OK;
    3566             : }
    3567             : 
    3568             : /* static */
    3569             : bool
    3570           0 : nsDocShell::CanAccessItem(nsIDocShellTreeItem* aTargetItem,
    3571             :                           nsIDocShellTreeItem* aAccessingItem,
    3572             :                           bool aConsiderOpener)
    3573             : {
    3574           0 :   NS_PRECONDITION(aTargetItem, "Must have target item!");
    3575             : 
    3576           0 :   if (!gValidateOrigin || !aAccessingItem) {
    3577             :     // Good to go
    3578           0 :     return true;
    3579             :   }
    3580             : 
    3581             :   // XXXbz should we care if aAccessingItem or the document therein is
    3582             :   // chrome?  Should those get extra privileges?
    3583             : 
    3584             :   // For historical context, see:
    3585             :   //
    3586             :   // Bug 13871:  Prevent frameset spoofing
    3587             :   // Bug 103638: Targets with same name in different windows open in wrong
    3588             :   //             window with javascript
    3589             :   // Bug 408052: Adopt "ancestor" frame navigation policy
    3590             : 
    3591             :   // Now do a security check.
    3592             :   //
    3593             :   // Disallow navigation if the two frames are not part of the same app, or if
    3594             :   // they have different is-in-browser-element states.
    3595             :   //
    3596             :   // Allow navigation if
    3597             :   //  1) aAccessingItem can script aTargetItem or one of its ancestors in
    3598             :   //     the frame hierarchy or
    3599             :   //  2) aTargetItem is a top-level frame and aAccessingItem is its descendant
    3600             :   //  3) aTargetItem is a top-level frame and aAccessingItem can target
    3601             :   //     its opener per rule (1) or (2).
    3602             : 
    3603           0 :   if (aTargetItem == aAccessingItem) {
    3604             :     // A frame is allowed to navigate itself.
    3605           0 :     return true;
    3606             :   }
    3607             : 
    3608           0 :   nsCOMPtr<nsIDocShell> targetDS = do_QueryInterface(aTargetItem);
    3609           0 :   nsCOMPtr<nsIDocShell> accessingDS = do_QueryInterface(aAccessingItem);
    3610           0 :   if (!targetDS || !accessingDS) {
    3611             :     // We must be able to convert both to nsIDocShell.
    3612           0 :     return false;
    3613             :   }
    3614             : 
    3615           0 :   if (targetDS->GetIsInIsolatedMozBrowserElement() !=
    3616           0 :         accessingDS->GetIsInIsolatedMozBrowserElement()) {
    3617           0 :     return false;
    3618             :   }
    3619             : 
    3620           0 :   nsCOMPtr<nsIDocShellTreeItem> accessingRoot;
    3621           0 :   aAccessingItem->GetSameTypeRootTreeItem(getter_AddRefs(accessingRoot));
    3622           0 :   nsCOMPtr<nsIDocShell> accessingRootDS = do_QueryInterface(accessingRoot);
    3623             : 
    3624           0 :   nsCOMPtr<nsIDocShellTreeItem> targetRoot;
    3625           0 :   aTargetItem->GetSameTypeRootTreeItem(getter_AddRefs(targetRoot));
    3626           0 :   nsCOMPtr<nsIDocShell> targetRootDS = do_QueryInterface(targetRoot);
    3627             : 
    3628             :   OriginAttributes targetOA =
    3629           0 :     static_cast<nsDocShell*>(targetDS.get())->GetOriginAttributes();
    3630             :   OriginAttributes accessingOA =
    3631           0 :     static_cast<nsDocShell*>(accessingDS.get())->GetOriginAttributes();
    3632             : 
    3633             :   // When the first party isolation is on, the top-level docShell may not have
    3634             :   // the firstPartyDomain in its originAttributes, but its document will have
    3635             :   // it. So we get the firstPartyDomain from the nodePrincipal of the document
    3636             :   // before we compare the originAttributes.
    3637           0 :   if (OriginAttributes::IsFirstPartyEnabled()) {
    3638           0 :     if (aAccessingItem->ItemType() == nsIDocShellTreeItem::typeContent &&
    3639           0 :         (accessingDS == accessingRootDS || accessingDS->GetIsMozBrowser())) {
    3640             : 
    3641           0 :       nsCOMPtr<nsIDocument> accessingDoc = aAccessingItem->GetDocument();
    3642             : 
    3643           0 :       if (accessingDoc) {
    3644           0 :         nsCOMPtr<nsIPrincipal> accessingPrincipal = accessingDoc->NodePrincipal();
    3645             : 
    3646             :         accessingOA.mFirstPartyDomain =
    3647           0 :           accessingPrincipal->OriginAttributesRef().mFirstPartyDomain;
    3648             :       }
    3649             :     }
    3650             : 
    3651           0 :     if (aTargetItem->ItemType() == nsIDocShellTreeItem::typeContent &&
    3652           0 :         (targetDS == targetRootDS || targetDS->GetIsMozBrowser())) {
    3653             : 
    3654           0 :       nsCOMPtr<nsIDocument> targetDoc = aAccessingItem->GetDocument();
    3655             : 
    3656           0 :       if (targetDoc) {
    3657           0 :         nsCOMPtr<nsIPrincipal> targetPrincipal = targetDoc->NodePrincipal();
    3658             : 
    3659             :         targetOA.mFirstPartyDomain =
    3660           0 :           targetPrincipal->OriginAttributesRef().mFirstPartyDomain;
    3661             :       }
    3662             :     }
    3663             :   }
    3664             : 
    3665           0 :   if (targetOA != accessingOA) {
    3666           0 :     return false;
    3667             :   }
    3668             : 
    3669             :   // A private document can't access a non-private one, and vice versa.
    3670           0 :   if (static_cast<nsDocShell*>(targetDS.get())->UsePrivateBrowsing() !=
    3671           0 :       static_cast<nsDocShell*>(accessingDS.get())->UsePrivateBrowsing()) {
    3672           0 :     return false;
    3673             :   }
    3674             : 
    3675           0 :   if (aTargetItem == accessingRoot) {
    3676             :     // A frame can navigate its root.
    3677           0 :     return true;
    3678             :   }
    3679             : 
    3680             :   // Check if aAccessingItem can navigate one of aTargetItem's ancestors.
    3681           0 :   nsCOMPtr<nsIDocShellTreeItem> target = aTargetItem;
    3682           0 :   do {
    3683           0 :     if (ValidateOrigin(aAccessingItem, target)) {
    3684           0 :       return true;
    3685             :     }
    3686             : 
    3687           0 :     nsCOMPtr<nsIDocShellTreeItem> parent;
    3688           0 :     target->GetSameTypeParent(getter_AddRefs(parent));
    3689           0 :     parent.swap(target);
    3690             :   } while (target);
    3691             : 
    3692           0 :   if (aTargetItem != targetRoot) {
    3693             :     // target is a subframe, not in accessor's frame hierarchy, and all its
    3694             :     // ancestors have origins different from that of the accessor. Don't
    3695             :     // allow access.
    3696           0 :     return false;
    3697             :   }
    3698             : 
    3699           0 :   if (!aConsiderOpener) {
    3700             :     // All done here
    3701           0 :     return false;
    3702             :   }
    3703             : 
    3704           0 :   nsCOMPtr<nsPIDOMWindowOuter> targetWindow = aTargetItem->GetWindow();
    3705           0 :   if (!targetWindow) {
    3706           0 :     NS_ERROR("This should not happen, really");
    3707           0 :     return false;
    3708             :   }
    3709             : 
    3710           0 :   nsCOMPtr<mozIDOMWindowProxy> targetOpener = targetWindow->GetOpener();
    3711           0 :   nsCOMPtr<nsIWebNavigation> openerWebNav(do_GetInterface(targetOpener));
    3712           0 :   nsCOMPtr<nsIDocShellTreeItem> openerItem(do_QueryInterface(openerWebNav));
    3713             : 
    3714           0 :   if (!openerItem) {
    3715           0 :     return false;
    3716             :   }
    3717             : 
    3718           0 :   return CanAccessItem(openerItem, aAccessingItem, false);
    3719             : }
    3720             : 
    3721             : static bool
    3722           0 : ItemIsActive(nsIDocShellTreeItem* aItem)
    3723             : {
    3724           0 :   if (nsCOMPtr<nsPIDOMWindowOuter> window = aItem->GetWindow()) {
    3725           0 :     auto* win = nsGlobalWindow::Cast(window);
    3726           0 :     MOZ_ASSERT(win->IsOuterWindow());
    3727           0 :     if (!win->GetClosedOuter()) {
    3728           0 :       return true;
    3729             :     }
    3730             :   }
    3731             : 
    3732           0 :   return false;
    3733             : }
    3734             : 
    3735             : NS_IMETHODIMP
    3736           0 : nsDocShell::FindItemWithName(const nsAString& aName,
    3737             :                              nsIDocShellTreeItem* aRequestor,
    3738             :                              nsIDocShellTreeItem* aOriginalRequestor,
    3739             :                              bool aSkipTabGroup,
    3740             :                              nsIDocShellTreeItem** aResult)
    3741             : {
    3742           0 :   NS_ENSURE_ARG_POINTER(aResult);
    3743             : 
    3744             :   // If we don't find one, we return NS_OK and a null result
    3745           0 :   *aResult = nullptr;
    3746             : 
    3747           0 :   if (aName.IsEmpty()) {
    3748           0 :     return NS_OK;
    3749             :   }
    3750             : 
    3751           0 :   if (aRequestor) {
    3752             :     // If aRequestor is not null we don't need to check special names, so
    3753             :     // just hand straight off to the search by actual name function.
    3754           0 :     return DoFindItemWithName(aName, aRequestor, aOriginalRequestor,
    3755           0 :                               aSkipTabGroup, aResult);
    3756             :   } else {
    3757             :     // This is the entry point into the target-finding algorithm.  Check
    3758             :     // for special names.  This should only be done once, hence the check
    3759             :     // for a null aRequestor.
    3760             : 
    3761           0 :     nsCOMPtr<nsIDocShellTreeItem> foundItem;
    3762           0 :     if (aName.LowerCaseEqualsLiteral("_self")) {
    3763           0 :       foundItem = this;
    3764           0 :     } else if (aName.LowerCaseEqualsLiteral("_blank")) {
    3765             :       // Just return null.  Caller must handle creating a new window with
    3766             :       // a blank name himself.
    3767           0 :       return NS_OK;
    3768           0 :     } else if (aName.LowerCaseEqualsLiteral("_parent")) {
    3769           0 :       GetSameTypeParent(getter_AddRefs(foundItem));
    3770           0 :       if (!foundItem) {
    3771           0 :         foundItem = this;
    3772             :       }
    3773           0 :     } else if (aName.LowerCaseEqualsLiteral("_top")) {
    3774           0 :       GetSameTypeRootTreeItem(getter_AddRefs(foundItem));
    3775           0 :       NS_ASSERTION(foundItem, "Must have this; worst case it's us!");
    3776             :     } else {
    3777             :       // Do the search for item by an actual name.
    3778           0 :       DoFindItemWithName(aName, aRequestor, aOriginalRequestor,
    3779           0 :                          aSkipTabGroup, getter_AddRefs(foundItem));
    3780             :     }
    3781             : 
    3782           0 :     if (foundItem && !CanAccessItem(foundItem, aOriginalRequestor)) {
    3783           0 :       foundItem = nullptr;
    3784             :     }
    3785             : 
    3786             :     // DoFindItemWithName only returns active items and we don't check if
    3787             :     // the item is active for the special cases.
    3788           0 :     if (foundItem) {
    3789           0 :       foundItem.swap(*aResult);
    3790             :     }
    3791           0 :     return NS_OK;
    3792             :   }
    3793             : }
    3794             : 
    3795             : void
    3796        2283 : nsDocShell::AssertOriginAttributesMatchPrivateBrowsing() {
    3797             :   // Chrome docshells must not have a private browsing OriginAttribute
    3798             :   // Content docshells must maintain the equality:
    3799             :   // mOriginAttributes.mPrivateBrowsingId == mPrivateBrowsingId
    3800        2283 :   if (mItemType == typeChrome) {
    3801        2104 :     MOZ_DIAGNOSTIC_ASSERT(mOriginAttributes.mPrivateBrowsingId == 0);
    3802             :   } else {
    3803         179 :     MOZ_DIAGNOSTIC_ASSERT(mOriginAttributes.mPrivateBrowsingId == mPrivateBrowsingId);
    3804             :   }
    3805        2283 : }
    3806             : 
    3807             : nsresult
    3808           0 : nsDocShell::DoFindItemWithName(const nsAString& aName,
    3809             :                                nsIDocShellTreeItem* aRequestor,
    3810             :                                nsIDocShellTreeItem* aOriginalRequestor,
    3811             :                                bool aSkipTabGroup,
    3812             :                                nsIDocShellTreeItem** aResult)
    3813             : {
    3814             :   // First we check our name.
    3815           0 :   if (mName.Equals(aName) && ItemIsActive(this) &&
    3816           0 :       CanAccessItem(this, aOriginalRequestor)) {
    3817           0 :     NS_ADDREF(*aResult = this);
    3818           0 :     return NS_OK;
    3819             :   }
    3820             : 
    3821             :   // Second we check our children making sure not to ask a child if
    3822             :   // it is the aRequestor.
    3823             : #ifdef DEBUG
    3824             :   nsresult rv =
    3825             : #endif
    3826             :   FindChildWithName(aName, true, true, aRequestor, aOriginalRequestor,
    3827           0 :                     aResult);
    3828           0 :   NS_ASSERTION(NS_SUCCEEDED(rv),
    3829             :                "FindChildWithName should not be failing here.");
    3830           0 :   if (*aResult) {
    3831           0 :     return NS_OK;
    3832             :   }
    3833             : 
    3834             :   // Third if we have a parent and it isn't the requestor then we
    3835             :   // should ask it to do the search.  If it is the requestor we
    3836             :   // should just stop here and let the parent do the rest.  If we
    3837             :   // don't have a parent, then we should ask the
    3838             :   // docShellTreeOwner to do the search.
    3839             :   nsCOMPtr<nsIDocShellTreeItem> parentAsTreeItem =
    3840           0 :     do_QueryInterface(GetAsSupports(mParent));
    3841           0 :   if (parentAsTreeItem) {
    3842           0 :     if (parentAsTreeItem == aRequestor) {
    3843           0 :       return NS_OK;
    3844             :     }
    3845             : 
    3846             :     // If we have a same-type parent, respecting browser and app boundaries.
    3847             :     // NOTE: Could use GetSameTypeParent if the issues described in bug 1310344 are fixed.
    3848           0 :     if (!GetIsMozBrowser() && parentAsTreeItem->ItemType() == mItemType) {
    3849           0 :       return parentAsTreeItem->FindItemWithName(
    3850             :         aName,
    3851             :         static_cast<nsIDocShellTreeItem*>(this),
    3852             :         aOriginalRequestor,
    3853             :         /* aSkipTabGroup = */ false,
    3854           0 :         aResult);
    3855             :     }
    3856             :   }
    3857             : 
    3858             :   // If we have a null parent or the parent is not of the same type, we need to
    3859             :   // give up on finding it in our tree, and start looking in our TabGroup.
    3860           0 :   nsCOMPtr<nsPIDOMWindowOuter> window = GetWindow();
    3861           0 :   if (window && !aSkipTabGroup) {
    3862           0 :     RefPtr<mozilla::dom::TabGroup> tabGroup = window->TabGroup();
    3863           0 :     tabGroup->FindItemWithName(aName, aRequestor, aOriginalRequestor, aResult);
    3864             :   }
    3865             : 
    3866           0 :   return NS_OK;
    3867             : }
    3868             : 
    3869             : bool
    3870           0 : nsDocShell::IsSandboxedFrom(nsIDocShell* aTargetDocShell)
    3871             : {
    3872             :   // If no target then not sandboxed.
    3873           0 :   if (!aTargetDocShell) {
    3874           0 :     return false;
    3875             :   }
    3876             : 
    3877             :   // We cannot be sandboxed from ourselves.
    3878           0 :   if (aTargetDocShell == this) {
    3879           0 :     return false;
    3880             :   }
    3881             : 
    3882             :   // Default the sandbox flags to our flags, so that if we can't retrieve the
    3883             :   // active document, we will still enforce our own.
    3884           0 :   uint32_t sandboxFlags = mSandboxFlags;
    3885           0 :   if (mContentViewer) {
    3886           0 :     nsCOMPtr<nsIDocument> doc = mContentViewer->GetDocument();
    3887           0 :     if (doc) {
    3888           0 :       sandboxFlags = doc->GetSandboxFlags();
    3889             :     }
    3890             :   }
    3891             : 
    3892             :   // If no flags, we are not sandboxed at all.
    3893           0 :   if (!sandboxFlags) {
    3894           0 :     return false;
    3895             :   }
    3896             : 
    3897             :   // If aTargetDocShell has an ancestor, it is not top level.
    3898           0 :   nsCOMPtr<nsIDocShellTreeItem> ancestorOfTarget;
    3899           0 :   aTargetDocShell->GetSameTypeParent(getter_AddRefs(ancestorOfTarget));
    3900           0 :   if (ancestorOfTarget) {
    3901           0 :     do {
    3902             :       // We are not sandboxed if we are an ancestor of target.
    3903           0 :       if (ancestorOfTarget == this) {
    3904           0 :         return false;
    3905             :       }
    3906           0 :       nsCOMPtr<nsIDocShellTreeItem> tempTreeItem;
    3907           0 :       ancestorOfTarget->GetSameTypeParent(getter_AddRefs(tempTreeItem));
    3908           0 :       tempTreeItem.swap(ancestorOfTarget);
    3909             :     } while (ancestorOfTarget);
    3910             : 
    3911             :     // Otherwise, we are sandboxed from aTargetDocShell.
    3912           0 :     return true;
    3913             :   }
    3914             : 
    3915             :   // aTargetDocShell is top level, are we the "one permitted sandboxed
    3916             :   // navigator", i.e. did we open aTargetDocShell?
    3917           0 :   nsCOMPtr<nsIDocShell> permittedNavigator;
    3918           0 :   aTargetDocShell->GetOnePermittedSandboxedNavigator(
    3919           0 :     getter_AddRefs(permittedNavigator));
    3920           0 :   if (permittedNavigator == this) {
    3921           0 :     return false;
    3922             :   }
    3923             : 
    3924             :   // If SANDBOXED_TOPLEVEL_NAVIGATION flag is not on, we are not sandboxed
    3925             :   // from our top.
    3926           0 :   if (!(sandboxFlags & SANDBOXED_TOPLEVEL_NAVIGATION)) {
    3927           0 :     nsCOMPtr<nsIDocShellTreeItem> rootTreeItem;
    3928           0 :     GetSameTypeRootTreeItem(getter_AddRefs(rootTreeItem));
    3929           0 :     if (SameCOMIdentity(aTargetDocShell, rootTreeItem)) {
    3930           0 :       return false;
    3931             :     }
    3932             :   }
    3933             : 
    3934             :   // Otherwise, we are sandboxed from aTargetDocShell.
    3935           0 :   return true;
    3936             : }
    3937             : 
    3938             : NS_IMETHODIMP
    3939          80 : nsDocShell::GetTreeOwner(nsIDocShellTreeOwner** aTreeOwner)
    3940             : {
    3941          80 :   NS_ENSURE_ARG_POINTER(aTreeOwner);
    3942             : 
    3943          80 :   *aTreeOwner = mTreeOwner;
    3944          80 :   NS_IF_ADDREF(*aTreeOwner);
    3945          80 :   return NS_OK;
    3946             : }
    3947             : 
    3948             : #ifdef DEBUG_DOCSHELL_FOCUS
    3949             : static void
    3950             : PrintDocTree(nsIDocShellTreeItem* aParentNode, int aLevel)
    3951             : {
    3952             :   for (int32_t i = 0; i < aLevel; i++) {
    3953             :     printf("  ");
    3954             :   }
    3955             : 
    3956             :   int32_t childWebshellCount;
    3957             :   aParentNode->GetChildCount(&childWebshellCount);
    3958             :   nsCOMPtr<nsIDocShell> parentAsDocShell(do_QueryInterface(aParentNode));
    3959             :   int32_t type = aParentNode->ItemType();
    3960             :   nsCOMPtr<nsIPresShell> presShell = parentAsDocShell->GetPresShell();
    3961             :   RefPtr<nsPresContext> presContext;
    3962             :   parentAsDocShell->GetPresContext(getter_AddRefs(presContext));
    3963             :   nsIDocument* doc = presShell->GetDocument();
    3964             : 
    3965             :   nsCOMPtr<nsPIDOMWindowOuter> domwin(doc->GetWindow());
    3966             : 
    3967             :   nsCOMPtr<nsIWidget> widget;
    3968             :   nsViewManager* vm = presShell->GetViewManager();
    3969             :   if (vm) {
    3970             :     vm->GetWidget(getter_AddRefs(widget));
    3971             :   }
    3972             :   dom::Element* rootElement = doc->GetRootElement();
    3973             : 
    3974             :   printf("DS %p  Ty %s  Doc %p DW %p EM %p CN %p\n",
    3975             :          (void*)parentAsDocShell.get(),
    3976             :          type == nsIDocShellTreeItem::typeChrome ? "Chr" : "Con",
    3977             :          (void*)doc, (void*)domwin.get(),
    3978             :          (void*)presContext->EventStateManager(), (void*)rootElement);
    3979             : 
    3980             :   if (childWebshellCount > 0) {
    3981             :     for (int32_t i = 0; i < childWebshellCount; i++) {
    3982             :       nsCOMPtr<nsIDocShellTreeItem> child;
    3983             :       aParentNode->GetChildAt(i, getter_AddRefs(child));
    3984             :       PrintDocTree(child, aLevel + 1);
    3985             :     }
    3986             :   }
    3987             : }
    3988             : 
    3989             : static void
    3990             : PrintDocTree(nsIDocShellTreeItem* aParentNode)
    3991             : {
    3992             :   NS_ASSERTION(aParentNode, "Pointer is null!");
    3993             : 
    3994             :   nsCOMPtr<nsIDocShellTreeItem> parentItem;
    3995             :   aParentNode->GetParent(getter_AddRefs(parentItem));
    3996             :   while (parentItem) {
    3997             :     nsCOMPtr<nsIDocShellTreeItem> tmp;
    3998             :     parentItem->GetParent(getter_AddRefs(tmp));
    3999             :     if (!tmp) {
    4000             :       break;
    4001             :     }
    4002             :     parentItem = tmp;
    4003             :   }
    4004             : 
    4005             :   if (!parentItem) {
    4006             :     parentItem = aParentNode;
    4007             :   }
    4008             : 
    4009             :   PrintDocTree(parentItem, 0);
    4010             : }
    4011             : #endif
    4012             : 
    4013             : NS_IMETHODIMP
    4014           9 : nsDocShell::SetTreeOwner(nsIDocShellTreeOwner* aTreeOwner)
    4015             : {
    4016             : #ifdef DEBUG_DOCSHELL_FOCUS
    4017             :   nsCOMPtr<nsIDocShellTreeItem> item(do_QueryInterface(aTreeOwner));
    4018             :   if (item) {
    4019             :     PrintDocTree(item);
    4020             :   }
    4021             : #endif
    4022             : 
    4023             :   // Don't automatically set the progress based on the tree owner for frames
    4024           9 :   if (!IsFrame()) {
    4025             :     nsCOMPtr<nsIWebProgress> webProgress =
    4026          16 :       do_QueryInterface(GetAsSupports(this));
    4027             : 
    4028           8 :     if (webProgress) {
    4029             :       nsCOMPtr<nsIWebProgressListener> oldListener =
    4030          16 :         do_QueryInterface(mTreeOwner);
    4031             :       nsCOMPtr<nsIWebProgressListener> newListener =
    4032          16 :         do_QueryInterface(aTreeOwner);
    4033             : 
    4034           8 :       if (oldListener) {
    4035           0 :         webProgress->RemoveProgressListener(oldListener);
    4036             :       }
    4037             : 
    4038           8 :       if (newListener) {
    4039           6 :         webProgress->AddProgressListener(newListener,
    4040           6 :                                          nsIWebProgress::NOTIFY_ALL);
    4041             :       }
    4042             :     }
    4043             :   }
    4044             : 
    4045           9 :   mTreeOwner = aTreeOwner;  // Weak reference per API
    4046             : 
    4047          18 :   nsTObserverArray<nsDocLoader*>::ForwardIterator iter(mChildList);
    4048           9 :   while (iter.HasMore()) {
    4049           0 :     nsCOMPtr<nsIDocShellTreeItem> child = do_QueryObject(iter.GetNext());
    4050           0 :     NS_ENSURE_TRUE(child, NS_ERROR_FAILURE);
    4051             : 
    4052           0 :     if (child->ItemType() == mItemType) {
    4053           0 :       child->SetTreeOwner(aTreeOwner);
    4054             :     }
    4055             :   }
    4056             : 
    4057             :   // Our tree owner has changed. Recompute scriptability.
    4058             :   //
    4059             :   // Note that this is near-redundant with the recomputation in
    4060             :   // SetDocLoaderParent(), but not so for the root DocShell, where the call to
    4061             :   // SetTreeOwner() happens after the initial AddDocLoaderAsChildOfRoot(),
    4062             :   // and we never set another parent. Given that this is neither expensive nor
    4063             :   // performance-critical, let's be safe and unconditionally recompute this
    4064             :   // state whenever dependent state changes.
    4065           9 :   RecomputeCanExecuteScripts();
    4066             : 
    4067           9 :   return NS_OK;
    4068             : }
    4069             : 
    4070             : NS_IMETHODIMP
    4071           2 : nsDocShell::SetChildOffset(uint32_t aChildOffset)
    4072             : {
    4073           2 :   mChildOffset = aChildOffset;
    4074           2 :   return NS_OK;
    4075             : }
    4076             : 
    4077             : NS_IMETHODIMP
    4078           0 : nsDocShell::GetHistoryID(nsID** aID)
    4079             : {
    4080           0 :   *aID = static_cast<nsID*>(nsMemory::Clone(&mHistoryID, sizeof(nsID)));
    4081           0 :   return NS_OK;
    4082             : }
    4083             : 
    4084             : const nsID
    4085           1 : nsDocShell::HistoryID()
    4086             : {
    4087           1 :   return mHistoryID;
    4088             : }
    4089             : 
    4090             : NS_IMETHODIMP
    4091           9 : nsDocShell::GetIsInUnload(bool* aIsInUnload)
    4092             : {
    4093           9 :   *aIsInUnload = mFiredUnloadEvent;
    4094           9 :   return NS_OK;
    4095             : }
    4096             : 
    4097             : NS_IMETHODIMP
    4098         425 : nsDocShell::GetChildCount(int32_t* aChildCount)
    4099             : {
    4100         425 :   NS_ENSURE_ARG_POINTER(aChildCount);
    4101         425 :   *aChildCount = mChildList.Length();
    4102         425 :   return NS_OK;
    4103             : }
    4104             : 
    4105             : NS_IMETHODIMP
    4106           2 : nsDocShell::AddChild(nsIDocShellTreeItem* aChild)
    4107             : {
    4108           2 :   NS_ENSURE_ARG_POINTER(aChild);
    4109             : 
    4110           4 :   RefPtr<nsDocLoader> childAsDocLoader = GetAsDocLoader(aChild);
    4111           2 :   NS_ENSURE_TRUE(childAsDocLoader, NS_ERROR_UNEXPECTED);
    4112             : 
    4113             :   // Make sure we're not creating a loop in the docshell tree
    4114           2 :   nsDocLoader* ancestor = this;
    4115           2 :   do {
    4116           4 :     if (childAsDocLoader == ancestor) {
    4117           0 :       return NS_ERROR_ILLEGAL_VALUE;
    4118             :     }
    4119           4 :     ancestor = ancestor->GetParent();
    4120           4 :   } while (ancestor);
    4121             : 
    4122             :   // Make sure to remove the child from its current parent.
    4123           2 :   nsDocLoader* childsParent = childAsDocLoader->GetParent();
    4124           2 :   if (childsParent) {
    4125           2 :     nsresult rv = childsParent->RemoveChildLoader(childAsDocLoader);
    4126           2 :     NS_ENSURE_SUCCESS(rv, rv);
    4127             :   }
    4128             : 
    4129             :   // Make sure to clear the treeowner in case this child is a different type
    4130             :   // from us.
    4131           2 :   aChild->SetTreeOwner(nullptr);
    4132             : 
    4133           2 :   nsresult res = AddChildLoader(childAsDocLoader);
    4134           2 :   NS_ENSURE_SUCCESS(res, res);
    4135           2 :   NS_ASSERTION(!mChildList.IsEmpty(),
    4136             :                "child list must not be empty after a successful add");
    4137             : 
    4138           4 :   nsCOMPtr<nsIDocShell> childDocShell = do_QueryInterface(aChild);
    4139           2 :   bool dynamic = false;
    4140           2 :   childDocShell->GetCreatedDynamically(&dynamic);
    4141           2 :   if (!dynamic) {
    4142           0 :     nsCOMPtr<nsISHEntry> currentSH;
    4143           0 :     bool oshe = false;
    4144           0 :     GetCurrentSHEntry(getter_AddRefs(currentSH), &oshe);
    4145           0 :     if (currentSH) {
    4146           0 :       currentSH->HasDynamicallyAddedChild(&dynamic);
    4147             :     }
    4148             :   }
    4149           2 :   childDocShell->SetChildOffset(dynamic ? -1 : mChildList.Length() - 1);
    4150             : 
    4151             :   /* Set the child's global history if the parent has one */
    4152           2 :   if (mUseGlobalHistory) {
    4153           0 :     childDocShell->SetUseGlobalHistory(true);
    4154             :   }
    4155             : 
    4156           2 :   if (aChild->ItemType() != mItemType) {
    4157           1 :     return NS_OK;
    4158             :   }
    4159             : 
    4160           1 :   aChild->SetTreeOwner(mTreeOwner);
    4161             : 
    4162           2 :   nsCOMPtr<nsIDocShell> childAsDocShell(do_QueryInterface(aChild));
    4163           1 :   if (!childAsDocShell) {
    4164           0 :     return NS_OK;
    4165             :   }
    4166             : 
    4167             :   // charset, style-disabling, and zoom will be inherited in SetupNewViewer()
    4168             : 
    4169             :   // Now take this document's charset and set the child's parentCharset field
    4170             :   // to it. We'll later use that field, in the loading process, for the
    4171             :   // charset choosing algorithm.
    4172             :   // If we fail, at any point, we just return NS_OK.
    4173             :   // This code has some performance impact. But this will be reduced when
    4174             :   // the current charset will finally be stored as an Atom, avoiding the
    4175             :   // alias resolution extra look-up.
    4176             : 
    4177             :   // we are NOT going to propagate the charset is this Chrome's docshell
    4178           1 :   if (mItemType == nsIDocShellTreeItem::typeChrome) {
    4179           1 :     return NS_OK;
    4180             :   }
    4181             : 
    4182             :   // get the parent's current charset
    4183           0 :   if (!mContentViewer) {
    4184           0 :     return NS_OK;
    4185             :   }
    4186           0 :   nsIDocument* doc = mContentViewer->GetDocument();
    4187           0 :   if (!doc) {
    4188           0 :     return NS_OK;
    4189             :   }
    4190             : 
    4191           0 :   bool isWyciwyg = false;
    4192             : 
    4193           0 :   if (mCurrentURI) {
    4194             :     // Check if the url is wyciwyg
    4195           0 :     mCurrentURI->SchemeIs("wyciwyg", &isWyciwyg);
    4196             :   }
    4197             : 
    4198           0 :   if (!isWyciwyg) {
    4199             :     // If this docshell is loaded from a wyciwyg: URI, don't
    4200             :     // advertise our charset since it does not in any way reflect
    4201             :     // the actual source charset, which is what we're trying to
    4202             :     // expose here.
    4203             : 
    4204           0 :     const Encoding* parentCS = doc->GetDocumentCharacterSet();
    4205           0 :     int32_t charsetSource = doc->GetDocumentCharacterSetSource();
    4206             :     // set the child's parentCharset
    4207           0 :     childAsDocShell->SetParentCharset(parentCS,
    4208             :                                       charsetSource,
    4209           0 :                                       doc->NodePrincipal());
    4210             :   }
    4211             : 
    4212             :   // printf("### 1 >>> Adding child. Parent CS = %s. ItemType = %d.\n",
    4213             :   //        NS_LossyConvertUTF16toASCII(parentCS).get(), mItemType);
    4214             : 
    4215           0 :   return NS_OK;
    4216             : }
    4217             : 
    4218             : NS_IMETHODIMP
    4219           1 : nsDocShell::RemoveChild(nsIDocShellTreeItem* aChild)
    4220             : {
    4221           1 :   NS_ENSURE_ARG_POINTER(aChild);
    4222             : 
    4223           2 :   RefPtr<nsDocLoader> childAsDocLoader = GetAsDocLoader(aChild);
    4224           1 :   NS_ENSURE_TRUE(childAsDocLoader, NS_ERROR_UNEXPECTED);
    4225             : 
    4226           1 :   nsresult rv = RemoveChildLoader(childAsDocLoader);
    4227           1 :   NS_ENSURE_SUCCESS(rv, rv);
    4228             : 
    4229           1 :   aChild->SetTreeOwner(nullptr);
    4230             : 
    4231           1 :   return nsDocLoader::AddDocLoaderAsChildOfRoot(childAsDocLoader);
    4232             : }
    4233             : 
    4234             : NS_IMETHODIMP
    4235           0 : nsDocShell::GetChildAt(int32_t aIndex, nsIDocShellTreeItem** aChild)
    4236             : {
    4237           0 :   NS_ENSURE_ARG_POINTER(aChild);
    4238             : 
    4239             : #ifdef DEBUG
    4240           0 :   if (aIndex < 0) {
    4241           0 :     NS_WARNING("Negative index passed to GetChildAt");
    4242           0 :   } else if (static_cast<uint32_t>(aIndex) >= mChildList.Length()) {
    4243           0 :     NS_WARNING("Too large an index passed to GetChildAt");
    4244             :   }
    4245             : #endif
    4246             : 
    4247           0 :   nsIDocumentLoader* child = ChildAt(aIndex);
    4248           0 :   NS_ENSURE_TRUE(child, NS_ERROR_UNEXPECTED);
    4249             : 
    4250           0 :   return CallQueryInterface(child, aChild);
    4251             : }
    4252             : 
    4253             : NS_IMETHODIMP
    4254          80 : nsDocShell::FindChildWithName(const nsAString& aName,
    4255             :                               bool aRecurse, bool aSameType,
    4256             :                               nsIDocShellTreeItem* aRequestor,
    4257             :                               nsIDocShellTreeItem* aOriginalRequestor,
    4258             :                               nsIDocShellTreeItem** aResult)
    4259             : {
    4260          80 :   NS_ENSURE_ARG_POINTER(aResult);
    4261             : 
    4262             :   // if we don't find one, we return NS_OK and a null result
    4263          80 :   *aResult = nullptr;
    4264             : 
    4265          80 :   if (aName.IsEmpty()) {
    4266           0 :     return NS_OK;
    4267             :   }
    4268             : 
    4269         160 :   nsXPIDLString childName;
    4270         160 :   nsTObserverArray<nsDocLoader*>::ForwardIterator iter(mChildList);
    4271         242 :   while (iter.HasMore()) {
    4272         161 :     nsCOMPtr<nsIDocShellTreeItem> child = do_QueryObject(iter.GetNext());
    4273          81 :     NS_ENSURE_TRUE(child, NS_ERROR_FAILURE);
    4274          81 :     int32_t childType = child->ItemType();
    4275             : 
    4276          81 :     if (aSameType && (childType != mItemType)) {
    4277           1 :       continue;
    4278             :     }
    4279             : 
    4280          80 :     bool childNameEquals = false;
    4281          80 :     child->NameEquals(aName, &childNameEquals);
    4282          80 :     if (childNameEquals && ItemIsActive(child) &&
    4283           0 :         CanAccessItem(child, aOriginalRequestor)) {
    4284           0 :       child.swap(*aResult);
    4285           0 :       break;
    4286             :     }
    4287             : 
    4288             :     // Only ask it to check children if it is same type
    4289          80 :     if (childType != mItemType) {
    4290           0 :       continue;
    4291             :     }
    4292             : 
    4293             :     // Only ask the child if it isn't the requestor
    4294          80 :     if (aRecurse && (aRequestor != child)) {
    4295             :       // See if child contains the shell with the given name
    4296             : #ifdef DEBUG
    4297             :       nsresult rv =
    4298             : #endif
    4299           0 :       child->FindChildWithName(aName, true, aSameType,
    4300             :                                static_cast<nsIDocShellTreeItem*>(this),
    4301           0 :                                aOriginalRequestor, aResult);
    4302           0 :       NS_ASSERTION(NS_SUCCEEDED(rv), "FindChildWithName should not fail here");
    4303           0 :       if (*aResult) {
    4304             :         // found it
    4305           0 :         return NS_OK;
    4306             :       }
    4307             :     }
    4308             :   }
    4309          80 :   return NS_OK;
    4310             : }
    4311             : 
    4312             : NS_IMETHODIMP
    4313           0 : nsDocShell::GetChildSHEntry(int32_t aChildOffset, nsISHEntry** aResult)
    4314             : {
    4315           0 :   nsresult rv = NS_OK;
    4316             : 
    4317           0 :   NS_ENSURE_ARG_POINTER(aResult);
    4318           0 :   *aResult = nullptr;
    4319             : 
    4320             :   // A nsISHEntry for a child is *only* available when the parent is in
    4321             :   // the progress of loading a document too...
    4322             : 
    4323           0 :   if (mLSHE) {
    4324             :     /* Before looking for the subframe's url, check
    4325             :      * the expiration status of the parent. If the parent
    4326             :      * has expired from cache, then subframes will not be
    4327             :      * loaded from history in certain situations.
    4328             :      */
    4329           0 :     bool parentExpired = false;
    4330           0 :     mLSHE->GetExpirationStatus(&parentExpired);
    4331             : 
    4332             :     /* Get the parent's Load Type so that it can be set on the child too.
    4333             :      * By default give a loadHistory value
    4334             :      */
    4335           0 :     uint32_t loadType = nsIDocShellLoadInfo::loadHistory;
    4336           0 :     mLSHE->GetLoadType(&loadType);
    4337             :     // If the user did a shift-reload on this frameset page,
    4338             :     // we don't want to load the subframes from history.
    4339           0 :     if (loadType == nsIDocShellLoadInfo::loadReloadBypassCache ||
    4340           0 :         loadType == nsIDocShellLoadInfo::loadReloadBypassProxy ||
    4341           0 :         loadType == nsIDocShellLoadInfo::loadReloadBypassProxyAndCache ||
    4342           0 :         loadType == nsIDocShellLoadInfo::loadRefresh) {
    4343           0 :       return rv;
    4344             :     }
    4345             : 
    4346             :     /* If the user pressed reload and the parent frame has expired
    4347             :      *  from cache, we do not want to load the child frame from history.
    4348             :      */
    4349           0 :     if (parentExpired && (loadType == nsIDocShellLoadInfo::loadReloadNormal)) {
    4350             :       // The parent has expired. Return null.
    4351           0 :       *aResult = nullptr;
    4352           0 :       return rv;
    4353             :     }
    4354             : 
    4355           0 :     nsCOMPtr<nsISHContainer> container(do_QueryInterface(mLSHE));
    4356           0 :     if (container) {
    4357             :       // Get the child subframe from session history.
    4358           0 :       rv = container->GetChildAt(aChildOffset, aResult);
    4359           0 :       if (*aResult) {
    4360           0 :         (*aResult)->SetLoadType(loadType);
    4361             :       }
    4362             :     }
    4363             :   }
    4364           0 :   return rv;
    4365             : }
    4366             : 
    4367             : NS_IMETHODIMP
    4368           0 : nsDocShell::AddChildSHEntry(nsISHEntry* aCloneRef, nsISHEntry* aNewEntry,
    4369             :                             int32_t aChildOffset, uint32_t aLoadType,
    4370             :                             bool aCloneChildren)
    4371             : {
    4372           0 :   nsresult rv = NS_OK;
    4373             : 
    4374           0 :   if (mLSHE && aLoadType != LOAD_PUSHSTATE) {
    4375             :     /* You get here if you are currently building a
    4376             :      * hierarchy ie.,you just visited a frameset page
    4377             :      */
    4378           0 :     nsCOMPtr<nsISHContainer> container(do_QueryInterface(mLSHE, &rv));
    4379           0 :     if (container) {
    4380           0 :       if (NS_FAILED(container->ReplaceChild(aNewEntry))) {
    4381           0 :         rv = container->AddChild(aNewEntry, aChildOffset);
    4382             :       }
    4383             :     }
    4384           0 :   } else if (!aCloneRef) {
    4385             :     /* This is an initial load in some subframe.  Just append it if we can */
    4386           0 :     nsCOMPtr<nsISHContainer> container(do_QueryInterface(mOSHE, &rv));
    4387           0 :     if (container) {
    4388           0 :       rv = container->AddChild(aNewEntry, aChildOffset);
    4389             :     }
    4390             :   } else {
    4391           0 :     rv = AddChildSHEntryInternal(aCloneRef, aNewEntry, aChildOffset,
    4392             :                                  aLoadType, aCloneChildren);
    4393             :   }
    4394           0 :   return rv;
    4395             : }
    4396             : 
    4397             : nsresult
    4398           0 : nsDocShell::AddChildSHEntryInternal(nsISHEntry* aCloneRef,
    4399             :                                     nsISHEntry* aNewEntry,
    4400             :                                     int32_t aChildOffset,
    4401             :                                     uint32_t aLoadType,
    4402             :                                     bool aCloneChildren)
    4403             : {
    4404           0 :   nsresult rv = NS_OK;
    4405           0 :   if (mSessionHistory) {
    4406             :     /* You are currently in the rootDocShell.
    4407             :      * You will get here when a subframe has a new url
    4408             :      * to load and you have walked up the tree all the
    4409             :      * way to the top to clone the current SHEntry hierarchy
    4410             :      * and replace the subframe where a new url was loaded with
    4411             :      * a new entry.
    4412             :      */
    4413           0 :     int32_t index = -1;
    4414           0 :     nsCOMPtr<nsISHEntry> currentHE;
    4415           0 :     mSessionHistory->GetIndex(&index);
    4416           0 :     if (index < 0) {
    4417           0 :       return NS_ERROR_FAILURE;
    4418             :     }
    4419             : 
    4420           0 :     rv = mSessionHistory->GetEntryAtIndex(index, false,
    4421           0 :                                           getter_AddRefs(currentHE));
    4422           0 :     NS_ENSURE_TRUE(currentHE, NS_ERROR_FAILURE);
    4423             : 
    4424           0 :     nsCOMPtr<nsISHEntry> currentEntry(do_QueryInterface(currentHE));
    4425           0 :     if (currentEntry) {
    4426           0 :       uint32_t cloneID = 0;
    4427           0 :       nsCOMPtr<nsISHEntry> nextEntry;
    4428           0 :       aCloneRef->GetID(&cloneID);
    4429           0 :       rv = CloneAndReplace(currentEntry, this, cloneID, aNewEntry,
    4430           0 :                            aCloneChildren, getter_AddRefs(nextEntry));
    4431             : 
    4432           0 :       if (NS_SUCCEEDED(rv)) {
    4433             :         nsCOMPtr<nsISHistoryInternal> shPrivate =
    4434           0 :           do_QueryInterface(mSessionHistory);
    4435           0 :         NS_ENSURE_TRUE(shPrivate, NS_ERROR_FAILURE);
    4436           0 :         rv = shPrivate->AddEntry(nextEntry, true);
    4437             :       }
    4438             :     }
    4439             :   } else {
    4440             :     /* Just pass this along */
    4441             :     nsCOMPtr<nsIDocShell> parent =
    4442           0 :       do_QueryInterface(GetAsSupports(mParent), &rv);
    4443           0 :     if (parent) {
    4444           0 :       rv = static_cast<nsDocShell*>(parent.get())->AddChildSHEntryInternal(
    4445             :         aCloneRef, aNewEntry, aChildOffset, aLoadType, aCloneChildren);
    4446             :     }
    4447             :   }
    4448           0 :   return rv;
    4449             : }
    4450             : 
    4451             : nsresult
    4452           0 : nsDocShell::AddChildSHEntryToParent(nsISHEntry* aNewEntry, int32_t aChildOffset,
    4453             :                                     bool aCloneChildren)
    4454             : {
    4455             :   /* You will get here when you are in a subframe and
    4456             :    * a new url has been loaded on you.
    4457             :    * The mOSHE in this subframe will be the previous url's
    4458             :    * mOSHE. This mOSHE will be used as the identification
    4459             :    * for this subframe in the  CloneAndReplace function.
    4460             :    */
    4461             : 
    4462             :   // In this case, we will end up calling AddEntry, which increases the
    4463             :   // current index by 1
    4464           0 :   nsCOMPtr<nsISHistory> rootSH;
    4465           0 :   GetRootSessionHistory(getter_AddRefs(rootSH));
    4466           0 :   if (rootSH) {
    4467           0 :     rootSH->GetIndex(&mPreviousTransIndex);
    4468             :   }
    4469             : 
    4470             :   nsresult rv;
    4471           0 :   nsCOMPtr<nsIDocShell> parent = do_QueryInterface(GetAsSupports(mParent), &rv);
    4472           0 :   if (parent) {
    4473           0 :     rv = parent->AddChildSHEntry(mOSHE, aNewEntry, aChildOffset, mLoadType,
    4474           0 :                                  aCloneChildren);
    4475             :   }
    4476             : 
    4477           0 :   if (rootSH) {
    4478           0 :     rootSH->GetIndex(&mLoadedTransIndex);
    4479             : #ifdef DEBUG_PAGE_CACHE
    4480             :     printf("Previous index: %d, Loaded index: %d\n\n", mPreviousTransIndex,
    4481             :            mLoadedTransIndex);
    4482             : #endif
    4483             :   }
    4484             : 
    4485           0 :   return rv;
    4486             : }
    4487             : 
    4488             : NS_IMETHODIMP
    4489           2 : nsDocShell::SetUseGlobalHistory(bool aUseGlobalHistory)
    4490             : {
    4491             :   nsresult rv;
    4492             : 
    4493           2 :   mUseGlobalHistory = aUseGlobalHistory;
    4494             : 
    4495           2 :   if (!aUseGlobalHistory) {
    4496           0 :     mGlobalHistory = nullptr;
    4497           0 :     return NS_OK;
    4498             :   }
    4499             : 
    4500             :   // No need to initialize mGlobalHistory if IHistory is available.
    4501           4 :   nsCOMPtr<IHistory> history = services::GetHistoryService();
    4502           2 :   if (history) {
    4503           2 :     return NS_OK;
    4504             :   }
    4505             : 
    4506           0 :   if (mGlobalHistory) {
    4507           0 :     return NS_OK;
    4508             :   }
    4509             : 
    4510           0 :   mGlobalHistory = do_GetService(NS_GLOBALHISTORY2_CONTRACTID, &rv);
    4511           0 :   return rv;
    4512             : }
    4513             : 
    4514             : NS_IMETHODIMP
    4515           0 : nsDocShell::GetUseGlobalHistory(bool* aUseGlobalHistory)
    4516             : {
    4517           0 :   *aUseGlobalHistory = mUseGlobalHistory;
    4518           0 :   return NS_OK;
    4519             : }
    4520             : 
    4521             : NS_IMETHODIMP
    4522           0 : nsDocShell::RemoveFromSessionHistory()
    4523             : {
    4524           0 :   nsCOMPtr<nsISHistoryInternal> internalHistory;
    4525           0 :   nsCOMPtr<nsISHistory> sessionHistory;
    4526           0 :   nsCOMPtr<nsIDocShellTreeItem> root;
    4527           0 :   GetSameTypeRootTreeItem(getter_AddRefs(root));
    4528           0 :   if (root) {
    4529           0 :     nsCOMPtr<nsIWebNavigation> rootAsWebnav = do_QueryInterface(root);
    4530           0 :     if (rootAsWebnav) {
    4531           0 :       rootAsWebnav->GetSessionHistory(getter_AddRefs(sessionHistory));
    4532           0 :       internalHistory = do_QueryInterface(sessionHistory);
    4533             :     }
    4534             :   }
    4535           0 :   if (!internalHistory) {
    4536           0 :     return NS_OK;
    4537             :   }
    4538             : 
    4539           0 :   int32_t index = 0;
    4540           0 :   sessionHistory->GetIndex(&index);
    4541           0 :   AutoTArray<nsID, 16> ids({mHistoryID});
    4542           0 :   internalHistory->RemoveEntries(ids, index);
    4543           0 :   return NS_OK;
    4544             : }
    4545             : 
    4546             : NS_IMETHODIMP
    4547           2 : nsDocShell::SetCreatedDynamically(bool aDynamic)
    4548             : {
    4549           2 :   mDynamicallyCreated = aDynamic;
    4550           2 :   return NS_OK;
    4551             : }
    4552             : 
    4553             : NS_IMETHODIMP
    4554           2 : nsDocShell::GetCreatedDynamically(bool* aDynamic)
    4555             : {
    4556           2 :   *aDynamic = mDynamicallyCreated;
    4557           2 :   return NS_OK;
    4558             : }
    4559             : 
    4560             : NS_IMETHODIMP
    4561           1 : nsDocShell::GetCurrentSHEntry(nsISHEntry** aEntry, bool* aOSHE)
    4562             : {
    4563           1 :   *aOSHE = false;
    4564           1 :   *aEntry = nullptr;
    4565           1 :   if (mLSHE) {
    4566           0 :     NS_ADDREF(*aEntry = mLSHE);
    4567           1 :   } else if (mOSHE) {
    4568           0 :     NS_ADDREF(*aEntry = mOSHE);
    4569           0 :     *aOSHE = true;
    4570             :   }
    4571           1 :   return NS_OK;
    4572             : }
    4573             : 
    4574             : nsIScriptGlobalObject*
    4575           0 : nsDocShell::GetScriptGlobalObject()
    4576             : {
    4577           0 :   NS_ENSURE_SUCCESS(EnsureScriptEnvironment(), nullptr);
    4578           0 :   return mScriptGlobal;
    4579             : }
    4580             : 
    4581             : nsIDocument*
    4582         195 : nsDocShell::GetDocument()
    4583             : {
    4584         195 :   NS_ENSURE_SUCCESS(EnsureContentViewer(), nullptr);
    4585         195 :   return mContentViewer->GetDocument();
    4586             : }
    4587             : 
    4588             : nsPIDOMWindowOuter*
    4589         130 : nsDocShell::GetWindow()
    4590             : {
    4591         130 :   if (NS_FAILED(EnsureScriptEnvironment())) {
    4592           1 :     return nullptr;
    4593             :   }
    4594         129 :   return mScriptGlobal->AsOuter();
    4595             : }
    4596             : 
    4597             : NS_IMETHODIMP
    4598           0 : nsDocShell::SetDeviceSizeIsPageSize(bool aValue)
    4599             : {
    4600           0 :   if (mDeviceSizeIsPageSize != aValue) {
    4601           0 :     mDeviceSizeIsPageSize = aValue;
    4602           0 :     RefPtr<nsPresContext> presContext;
    4603           0 :     GetPresContext(getter_AddRefs(presContext));
    4604           0 :     if (presContext) {
    4605           0 :       presContext->MediaFeatureValuesChanged(nsRestyleHint(0));
    4606             :     }
    4607             :   }
    4608           0 :   return NS_OK;
    4609             : }
    4610             : 
    4611             : NS_IMETHODIMP
    4612           6 : nsDocShell::GetDeviceSizeIsPageSize(bool* aValue)
    4613             : {
    4614           6 :   *aValue = mDeviceSizeIsPageSize;
    4615           6 :   return NS_OK;
    4616             : }
    4617             : 
    4618             : void
    4619           0 : nsDocShell::ClearFrameHistory(nsISHEntry* aEntry)
    4620             : {
    4621           0 :   nsCOMPtr<nsISHContainer> shcontainer = do_QueryInterface(aEntry);
    4622           0 :   nsCOMPtr<nsISHistory> rootSH;
    4623           0 :   GetRootSessionHistory(getter_AddRefs(rootSH));
    4624           0 :   nsCOMPtr<nsISHistoryInternal> history = do_QueryInterface(rootSH);
    4625           0 :   if (!history || !shcontainer) {
    4626           0 :     return;
    4627             :   }
    4628             : 
    4629           0 :   int32_t count = 0;
    4630           0 :   shcontainer->GetChildCount(&count);
    4631           0 :   AutoTArray<nsID, 16> ids;
    4632           0 :   for (int32_t i = 0; i < count; ++i) {
    4633           0 :     nsCOMPtr<nsISHEntry> child;
    4634           0 :     shcontainer->GetChildAt(i, getter_AddRefs(child));
    4635           0 :     if (child) {
    4636           0 :       ids.AppendElement(child->DocshellID());
    4637             :     }
    4638             :   }
    4639           0 :   int32_t index = 0;
    4640           0 :   rootSH->GetIndex(&index);
    4641           0 :   history->RemoveEntries(ids, index);
    4642             : }
    4643             : 
    4644             : //-------------------------------------
    4645             : //-- Helper Method for Print discovery
    4646             : //-------------------------------------
    4647             : bool
    4648          11 : nsDocShell::IsPrintingOrPP(bool aDisplayErrorDialog)
    4649             : {
    4650          11 :   if (mIsPrintingOrPP && aDisplayErrorDialog) {
    4651           0 :     DisplayLoadError(NS_ERROR_DOCUMENT_IS_PRINTMODE, nullptr, nullptr, nullptr);
    4652             :   }
    4653             : 
    4654          11 :   return mIsPrintingOrPP;
    4655             : }
    4656             : 
    4657             : bool
    4658          11 : nsDocShell::IsNavigationAllowed(bool aDisplayPrintErrorDialog,
    4659             :                                 bool aCheckIfUnloadFired)
    4660             : {
    4661          33 :   bool isAllowed = !IsPrintingOrPP(aDisplayPrintErrorDialog) &&
    4662          27 :                    (!aCheckIfUnloadFired || !mFiredUnloadEvent);
    4663          11 :   if (!isAllowed) {
    4664           0 :     return false;
    4665             :   }
    4666          11 :   if (!mContentViewer) {
    4667           1 :     return true;
    4668             :   }
    4669             :   bool firingBeforeUnload;
    4670          10 :   mContentViewer->GetBeforeUnloadFiring(&firingBeforeUnload);
    4671          10 :   return !firingBeforeUnload;
    4672             : }
    4673             : 
    4674             : //*****************************************************************************
    4675             : // nsDocShell::nsIWebNavigation
    4676             : //*****************************************************************************
    4677             : 
    4678             : NS_IMETHODIMP
    4679           1 : nsDocShell::GetCanGoBack(bool* aCanGoBack)
    4680             : {
    4681           1 :   if (!IsNavigationAllowed(false)) {
    4682           0 :     *aCanGoBack = false;
    4683           0 :     return NS_OK; // JS may not handle returning of an error code
    4684             :   }
    4685             :   nsresult rv;
    4686           2 :   nsCOMPtr<nsISHistory> rootSH;
    4687           1 :   rv = GetRootSessionHistory(getter_AddRefs(rootSH));
    4688           2 :   nsCOMPtr<nsIWebNavigation> webnav(do_QueryInterface(rootSH));
    4689           1 :   NS_ENSURE_TRUE(webnav, NS_ERROR_FAILURE);
    4690           1 :   rv = webnav->GetCanGoBack(aCanGoBack);
    4691           1 :   return rv;
    4692             : }
    4693             : 
    4694             : NS_IMETHODIMP
    4695           1 : nsDocShell::GetCanGoForward(bool* aCanGoForward)
    4696             : {
    4697           1 :   if (!IsNavigationAllowed(false)) {
    4698           0 :     *aCanGoForward = false;
    4699           0 :     return NS_OK; // JS may not handle returning of an error code
    4700             :   }
    4701             :   nsresult rv;
    4702           2 :   nsCOMPtr<nsISHistory> rootSH;
    4703           1 :   rv = GetRootSessionHistory(getter_AddRefs(rootSH));
    4704           2 :   nsCOMPtr<nsIWebNavigation> webnav(do_QueryInterface(rootSH));
    4705           1 :   NS_ENSURE_TRUE(webnav, NS_ERROR_FAILURE);
    4706           1 :   rv = webnav->GetCanGoForward(aCanGoForward);
    4707           1 :   return rv;
    4708             : }
    4709             : 
    4710             : NS_IMETHODIMP
    4711           0 : nsDocShell::GoBack()
    4712             : {
    4713           0 :   if (!IsNavigationAllowed()) {
    4714           0 :     return NS_OK; // JS may not handle returning of an error code
    4715             :   }
    4716             :   nsresult rv;
    4717           0 :   nsCOMPtr<nsISHistory> rootSH;
    4718           0 :   rv = GetRootSessionHistory(getter_AddRefs(rootSH));
    4719           0 :   nsCOMPtr<nsIWebNavigation> webnav(do_QueryInterface(rootSH));
    4720           0 :   NS_ENSURE_TRUE(webnav, NS_ERROR_FAILURE);
    4721           0 :   rv = webnav->GoBack();
    4722           0 :   return rv;
    4723             : }
    4724             : 
    4725             : NS_IMETHODIMP
    4726           0 : nsDocShell::GoForward()
    4727             : {
    4728           0 :   if (!IsNavigationAllowed()) {
    4729           0 :     return NS_OK; // JS may not handle returning of an error code
    4730             :   }
    4731             :   nsresult rv;
    4732           0 :   nsCOMPtr<nsISHistory> rootSH;
    4733           0 :   rv = GetRootSessionHistory(getter_AddRefs(rootSH));
    4734           0 :   nsCOMPtr<nsIWebNavigation> webnav(do_QueryInterface(rootSH));
    4735           0 :   NS_ENSURE_TRUE(webnav, NS_ERROR_FAILURE);
    4736           0 :   rv = webnav->GoForward();
    4737           0 :   return rv;
    4738             : }
    4739             : 
    4740             : NS_IMETHODIMP
    4741           0 : nsDocShell::GotoIndex(int32_t aIndex)
    4742             : {
    4743           0 :   if (!IsNavigationAllowed()) {
    4744           0 :     return NS_OK; // JS may not handle returning of an error code
    4745             :   }
    4746             :   nsresult rv;
    4747           0 :   nsCOMPtr<nsISHistory> rootSH;
    4748           0 :   rv = GetRootSessionHistory(getter_AddRefs(rootSH));
    4749           0 :   nsCOMPtr<nsIWebNavigation> webnav(do_QueryInterface(rootSH));
    4750           0 :   NS_ENSURE_TRUE(webnav, NS_ERROR_FAILURE);
    4751           0 :   rv = webnav->GotoIndex(aIndex);
    4752           0 :   return rv;
    4753             : }
    4754             : 
    4755             : NS_IMETHODIMP
    4756           2 : nsDocShell::LoadURI(const char16_t* aURI,
    4757             :                     uint32_t aLoadFlags,
    4758             :                     nsIURI* aReferringURI,
    4759             :                     nsIInputStream* aPostStream,
    4760             :                     nsIInputStream* aHeaderStream,
    4761             :                     nsIPrincipal* aTriggeringPrincipal)
    4762             : {
    4763             :   return LoadURIWithOptions(aURI, aLoadFlags, aReferringURI,
    4764             :                             mozilla::net::RP_Unset, aPostStream,
    4765           2 :                             aHeaderStream, nullptr, aTriggeringPrincipal);
    4766             : }
    4767             : 
    4768             : NS_IMETHODIMP
    4769           3 : nsDocShell::LoadURIWithOptions(const char16_t* aURI,
    4770             :                                uint32_t aLoadFlags,
    4771             :                                nsIURI* aReferringURI,
    4772             :                                uint32_t aReferrerPolicy,
    4773             :                                nsIInputStream* aPostStream,
    4774             :                                nsIInputStream* aHeaderStream,
    4775             :                                nsIURI* aBaseURI,
    4776             :                                nsIPrincipal* aTriggeringPrincipal)
    4777             : {
    4778           3 :   NS_ASSERTION((aLoadFlags & 0xf) == 0, "Unexpected flags");
    4779             : 
    4780           3 :   if (!IsNavigationAllowed()) {
    4781           0 :     return NS_OK; // JS may not handle returning of an error code
    4782             :   }
    4783           6 :   nsCOMPtr<nsIURI> uri;
    4784           6 :   nsCOMPtr<nsIInputStream> postStream(aPostStream);
    4785           3 :   nsresult rv = NS_OK;
    4786             : 
    4787             :   // Create a URI from our string; if that succeeds, we want to
    4788             :   // change aLoadFlags to not include the ALLOW_THIRD_PARTY_FIXUP
    4789             :   // flag.
    4790             : 
    4791           6 :   NS_ConvertUTF16toUTF8 uriString(aURI);
    4792             :   // Cleanup the empty spaces that might be on each end.
    4793           3 :   uriString.Trim(" ");
    4794             :   // Eliminate embedded newlines, which single-line text fields now allow:
    4795           3 :   uriString.StripCRLF();
    4796           3 :   NS_ENSURE_TRUE(!uriString.IsEmpty(), NS_ERROR_FAILURE);
    4797             : 
    4798           3 :   rv = NS_NewURI(getter_AddRefs(uri), uriString);
    4799           3 :   if (uri) {
    4800           3 :     aLoadFlags &= ~LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP;
    4801             :   }
    4802             : 
    4803           6 :   nsCOMPtr<nsIURIFixupInfo> fixupInfo;
    4804           3 :   if (sURIFixup) {
    4805             :     // Call the fixup object.  This will clobber the rv from NS_NewURI
    4806             :     // above, but that's fine with us.  Note that we need to do this even
    4807             :     // if NS_NewURI returned a URI, because fixup handles nested URIs, etc
    4808             :     // (things like view-source:mozilla.org for example).
    4809           3 :     uint32_t fixupFlags = 0;
    4810           3 :     if (aLoadFlags & LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP) {
    4811           0 :       fixupFlags |= nsIURIFixup::FIXUP_FLAG_ALLOW_KEYWORD_LOOKUP;
    4812             :     }
    4813           3 :     if (aLoadFlags & LOAD_FLAGS_FIXUP_SCHEME_TYPOS) {
    4814           0 :       fixupFlags |= nsIURIFixup::FIXUP_FLAG_FIX_SCHEME_TYPOS;
    4815             :     }
    4816           6 :     nsCOMPtr<nsIInputStream> fixupStream;
    4817           9 :     rv = sURIFixup->GetFixupURIInfo(uriString, fixupFlags,
    4818           6 :                                     getter_AddRefs(fixupStream),
    4819           9 :                                     getter_AddRefs(fixupInfo));
    4820             : 
    4821           3 :     if (NS_SUCCEEDED(rv)) {
    4822           3 :       fixupInfo->GetPreferredURI(getter_AddRefs(uri));
    4823           3 :       fixupInfo->SetConsumer(GetAsSupports(this));
    4824             :     }
    4825             : 
    4826           3 :     if (fixupStream) {
    4827             :       // GetFixupURIInfo only returns a post data stream if it succeeded
    4828             :       // and changed the URI, in which case we should override the
    4829             :       // passed-in post data.
    4830           0 :       postStream = fixupStream;
    4831             :     }
    4832             : 
    4833           3 :     if (aLoadFlags & LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP) {
    4834           0 :       nsCOMPtr<nsIObserverService> serv = services::GetObserverService();
    4835           0 :       if (serv) {
    4836           0 :         serv->NotifyObservers(fixupInfo, "keyword-uri-fixup", aURI);
    4837             :       }
    4838             :     }
    4839             :   }
    4840             :   // else no fixup service so just use the URI we created and see
    4841             :   // what happens
    4842             : 
    4843           3 :   if (NS_ERROR_MALFORMED_URI == rv) {
    4844           0 :     if (DisplayLoadError(rv, uri, aURI, nullptr) &&
    4845           0 :         (aLoadFlags & LOAD_FLAGS_ERROR_LOAD_CHANGES_RV) != 0) {
    4846           0 :       return NS_ERROR_LOAD_SHOWED_ERRORPAGE;
    4847             :     }
    4848             :   }
    4849             : 
    4850           3 :   if (NS_FAILED(rv) || !uri) {
    4851           0 :     return NS_ERROR_FAILURE;
    4852             :   }
    4853             : 
    4854             :   PopupControlState popupState;
    4855           3 :   if (aLoadFlags & LOAD_FLAGS_ALLOW_POPUPS) {
    4856           0 :     popupState = openAllowed;
    4857           0 :     aLoadFlags &= ~LOAD_FLAGS_ALLOW_POPUPS;
    4858             :   } else {
    4859           3 :     popupState = openOverridden;
    4860             :   }
    4861           6 :   nsAutoPopupStatePusher statePusher(popupState);
    4862             : 
    4863             :   // Don't pass certain flags that aren't needed and end up confusing
    4864             :   // ConvertLoadTypeToDocShellLoadInfo.  We do need to ensure that they are
    4865             :   // passed to LoadURI though, since it uses them.
    4866           3 :   uint32_t extraFlags = (aLoadFlags & EXTRA_LOAD_FLAGS);
    4867           3 :   aLoadFlags &= ~EXTRA_LOAD_FLAGS;
    4868             : 
    4869           6 :   nsCOMPtr<nsIDocShellLoadInfo> loadInfo;
    4870           3 :   rv = CreateLoadInfo(getter_AddRefs(loadInfo));
    4871           3 :   if (NS_FAILED(rv)) {
    4872           0 :     return rv;
    4873             :   }
    4874             : 
    4875             :   /*
    4876             :    * If the user "Disables Protection on This Page", we have to make sure to
    4877             :    * remember the users decision when opening links in child tabs [Bug 906190]
    4878             :    */
    4879             :   uint32_t loadType;
    4880           3 :   if (aLoadFlags & LOAD_FLAGS_ALLOW_MIXED_CONTENT) {
    4881           0 :     loadType = MAKE_LOAD_TYPE(LOAD_NORMAL_ALLOW_MIXED_CONTENT, aLoadFlags);
    4882             :   } else {
    4883           3 :     loadType = MAKE_LOAD_TYPE(LOAD_NORMAL, aLoadFlags);
    4884             :   }
    4885             : 
    4886           3 :   loadInfo->SetLoadType(ConvertLoadTypeToDocShellLoadInfo(loadType));
    4887           3 :   loadInfo->SetPostDataStream(postStream);
    4888           3 :   loadInfo->SetReferrer(aReferringURI);
    4889           3 :   loadInfo->SetReferrerPolicy(aReferrerPolicy);
    4890           3 :   loadInfo->SetHeadersStream(aHeaderStream);
    4891           3 :   loadInfo->SetBaseURI(aBaseURI);
    4892           3 :   loadInfo->SetTriggeringPrincipal(aTriggeringPrincipal);
    4893             : 
    4894           3 :   if (fixupInfo) {
    4895           6 :     nsAutoString searchProvider, keyword;
    4896           3 :     fixupInfo->GetKeywordProviderName(searchProvider);
    4897           3 :     fixupInfo->GetKeywordAsSent(keyword);
    4898           3 :     MaybeNotifyKeywordSearchLoading(searchProvider, keyword);
    4899             :   }
    4900             : 
    4901           3 :   rv = LoadURI(uri, loadInfo, extraFlags, true);
    4902             : 
    4903             :   // Save URI string in case it's needed later when
    4904             :   // sending to search engine service in EndPageLoad()
    4905           3 :   mOriginalUriString = uriString;
    4906             : 
    4907           3 :   return rv;
    4908             : }
    4909             : 
    4910             : NS_IMETHODIMP
    4911           0 : nsDocShell::DisplayLoadError(nsresult aError, nsIURI* aURI,
    4912             :                              const char16_t* aURL,
    4913             :                              nsIChannel* aFailedChannel,
    4914             :                              bool* aDisplayedErrorPage)
    4915             : {
    4916           0 :   *aDisplayedErrorPage = false;
    4917             :   // Get prompt and string bundle servcies
    4918           0 :   nsCOMPtr<nsIPrompt> prompter;
    4919           0 :   nsCOMPtr<nsIStringBundle> stringBundle;
    4920           0 :   GetPromptAndStringBundle(getter_AddRefs(prompter),
    4921           0 :                            getter_AddRefs(stringBundle));
    4922             : 
    4923           0 :   NS_ENSURE_TRUE(stringBundle, NS_ERROR_FAILURE);
    4924           0 :   NS_ENSURE_TRUE(prompter, NS_ERROR_FAILURE);
    4925             : 
    4926           0 :   nsAutoString error;
    4927           0 :   const uint32_t kMaxFormatStrArgs = 3;
    4928           0 :   nsAutoString formatStrs[kMaxFormatStrArgs];
    4929           0 :   uint32_t formatStrCount = 0;
    4930           0 :   bool addHostPort = false;
    4931           0 :   nsresult rv = NS_OK;
    4932           0 :   nsAutoString messageStr;
    4933           0 :   nsAutoCString cssClass;
    4934           0 :   nsAutoCString errorPage;
    4935             : 
    4936           0 :   errorPage.AssignLiteral("neterror");
    4937             : 
    4938             :   // Turn the error code into a human readable error message.
    4939           0 :   if (NS_ERROR_UNKNOWN_PROTOCOL == aError) {
    4940           0 :     NS_ENSURE_ARG_POINTER(aURI);
    4941             : 
    4942             :     // Extract the schemes into a comma delimited list.
    4943           0 :     nsAutoCString scheme;
    4944           0 :     aURI->GetScheme(scheme);
    4945           0 :     CopyASCIItoUTF16(scheme, formatStrs[0]);
    4946           0 :     nsCOMPtr<nsINestedURI> nestedURI = do_QueryInterface(aURI);
    4947           0 :     while (nestedURI) {
    4948           0 :       nsCOMPtr<nsIURI> tempURI;
    4949             :       nsresult rv2;
    4950           0 :       rv2 = nestedURI->GetInnerURI(getter_AddRefs(tempURI));
    4951           0 :       if (NS_SUCCEEDED(rv2) && tempURI) {
    4952           0 :         tempURI->GetScheme(scheme);
    4953           0 :         formatStrs[0].AppendLiteral(", ");
    4954           0 :         AppendASCIItoUTF16(scheme, formatStrs[0]);
    4955             :       }
    4956           0 :       nestedURI = do_QueryInterface(tempURI);
    4957             :     }
    4958           0 :     formatStrCount = 1;
    4959           0 :     error.AssignLiteral("unknownProtocolFound");
    4960           0 :   } else if (NS_ERROR_FILE_NOT_FOUND == aError) {
    4961           0 :     NS_ENSURE_ARG_POINTER(aURI);
    4962           0 :     error.AssignLiteral("fileNotFound");
    4963           0 :   } else if (NS_ERROR_FILE_ACCESS_DENIED == aError) {
    4964           0 :     NS_ENSURE_ARG_POINTER(aURI);
    4965           0 :     error.AssignLiteral("fileAccessDenied");
    4966           0 :   } else if (NS_ERROR_UNKNOWN_HOST == aError) {
    4967           0 :     NS_ENSURE_ARG_POINTER(aURI);
    4968             :     // Get the host
    4969           0 :     nsAutoCString host;
    4970           0 :     nsCOMPtr<nsIURI> innermostURI = NS_GetInnermostURI(aURI);
    4971           0 :     innermostURI->GetHost(host);
    4972           0 :     CopyUTF8toUTF16(host, formatStrs[0]);
    4973           0 :     formatStrCount = 1;
    4974           0 :     error.AssignLiteral("dnsNotFound");
    4975           0 :   } else if (NS_ERROR_CONNECTION_REFUSED == aError) {
    4976           0 :     NS_ENSURE_ARG_POINTER(aURI);
    4977           0 :     addHostPort = true;
    4978           0 :     error.AssignLiteral("connectionFailure");
    4979           0 :   } else if (NS_ERROR_NET_INTERRUPT == aError) {
    4980           0 :     NS_ENSURE_ARG_POINTER(aURI);
    4981           0 :     addHostPort = true;
    4982           0 :     error.AssignLiteral("netInterrupt");
    4983           0 :   } else if (NS_ERROR_NET_TIMEOUT == aError) {
    4984           0 :     NS_ENSURE_ARG_POINTER(aURI);
    4985             :     // Get the host
    4986           0 :     nsAutoCString host;
    4987           0 :     aURI->GetHost(host);
    4988           0 :     CopyUTF8toUTF16(host, formatStrs[0]);
    4989           0 :     formatStrCount = 1;
    4990           0 :     error.AssignLiteral("netTimeout");
    4991           0 :   } else if (NS_ERROR_CSP_FRAME_ANCESTOR_VIOLATION == aError ||
    4992             :              NS_ERROR_CSP_FORM_ACTION_VIOLATION == aError) {
    4993             :     // CSP error
    4994           0 :     cssClass.AssignLiteral("neterror");
    4995           0 :     error.AssignLiteral("cspBlocked");
    4996           0 :   } else if (NS_ERROR_GET_MODULE(aError) == NS_ERROR_MODULE_SECURITY) {
    4997             :     nsCOMPtr<nsINSSErrorsService> nsserr =
    4998           0 :       do_GetService(NS_NSS_ERRORS_SERVICE_CONTRACTID);
    4999             : 
    5000             :     uint32_t errorClass;
    5001           0 :     if (!nsserr || NS_FAILED(nsserr->GetErrorClass(aError, &errorClass))) {
    5002           0 :       errorClass = nsINSSErrorsService::ERROR_CLASS_SSL_PROTOCOL;
    5003             :     }
    5004             : 
    5005           0 :     nsCOMPtr<nsISupports> securityInfo;
    5006           0 :     nsCOMPtr<nsITransportSecurityInfo> tsi;
    5007           0 :     if (aFailedChannel) {
    5008           0 :       aFailedChannel->GetSecurityInfo(getter_AddRefs(securityInfo));
    5009             :     }
    5010           0 :     tsi = do_QueryInterface(securityInfo);
    5011           0 :     if (tsi) {
    5012             :       uint32_t securityState;
    5013           0 :       tsi->GetSecurityState(&securityState);
    5014           0 :       if (securityState & nsIWebProgressListener::STATE_USES_SSL_3) {
    5015           0 :         error.AssignLiteral("sslv3Used");
    5016           0 :         addHostPort = true;
    5017           0 :       } else if (securityState & nsIWebProgressListener::STATE_USES_WEAK_CRYPTO) {
    5018           0 :         error.AssignLiteral("weakCryptoUsed");
    5019           0 :         addHostPort = true;
    5020             :       } else {
    5021             :         // Usually we should have aFailedChannel and get a detailed message
    5022           0 :         tsi->GetErrorMessage(getter_Copies(messageStr));
    5023             :       }
    5024             :     } else {
    5025             :       // No channel, let's obtain the generic error message
    5026           0 :       if (nsserr) {
    5027           0 :         nsserr->GetErrorMessage(aError, messageStr);
    5028             :       }
    5029             :     }
    5030           0 :     if (!messageStr.IsEmpty()) {
    5031           0 :       if (errorClass == nsINSSErrorsService::ERROR_CLASS_BAD_CERT) {
    5032           0 :         error.AssignLiteral("nssBadCert");
    5033             : 
    5034             :         // If this is an HTTP Strict Transport Security host or a pinned host
    5035             :         // and the certificate is bad, don't allow overrides (RFC 6797 section
    5036             :         // 12.1, HPKP draft spec section 2.6).
    5037             :         uint32_t flags =
    5038           0 :           UsePrivateBrowsing() ? nsISocketProvider::NO_PERMANENT_STORAGE : 0;
    5039           0 :         bool isStsHost = false;
    5040           0 :         bool isPinnedHost = false;
    5041           0 :         if (XRE_IsParentProcess()) {
    5042             :           nsCOMPtr<nsISiteSecurityService> sss =
    5043           0 :             do_GetService(NS_SSSERVICE_CONTRACTID, &rv);
    5044           0 :           NS_ENSURE_SUCCESS(rv, rv);
    5045           0 :           rv = sss->IsSecureURI(nsISiteSecurityService::HEADER_HSTS, aURI,
    5046             :                                 flags, mOriginAttributes, nullptr, nullptr,
    5047           0 :                                 &isStsHost);
    5048           0 :           NS_ENSURE_SUCCESS(rv, rv);
    5049           0 :           rv = sss->IsSecureURI(nsISiteSecurityService::HEADER_HPKP, aURI,
    5050             :                                 flags, mOriginAttributes, nullptr, nullptr,
    5051           0 :                                 &isPinnedHost);
    5052           0 :           NS_ENSURE_SUCCESS(rv, rv);
    5053             :         } else {
    5054             :           mozilla::dom::ContentChild* cc =
    5055           0 :             mozilla::dom::ContentChild::GetSingleton();
    5056           0 :           mozilla::ipc::URIParams uri;
    5057           0 :           SerializeURI(aURI, uri);
    5058           0 :           cc->SendIsSecureURI(nsISiteSecurityService::HEADER_HSTS, uri, flags,
    5059           0 :                               mOriginAttributes, &isStsHost);
    5060           0 :           cc->SendIsSecureURI(nsISiteSecurityService::HEADER_HPKP, uri, flags,
    5061           0 :                               mOriginAttributes, &isPinnedHost);
    5062             :         }
    5063             : 
    5064           0 :         if (Preferences::GetBool(
    5065             :               "browser.xul.error_pages.expert_bad_cert", false)) {
    5066           0 :           cssClass.AssignLiteral("expertBadCert");
    5067             :         }
    5068             : 
    5069             :         // HSTS/pinning takes precedence over the expert bad cert pref. We
    5070             :         // never want to show the "Add Exception" button for these sites.
    5071             :         // In the future we should differentiate between an HSTS host and a
    5072             :         // pinned host and display a more informative message to the user.
    5073           0 :         if (isStsHost || isPinnedHost) {
    5074           0 :           cssClass.AssignLiteral("badStsCert");
    5075             :         }
    5076             : 
    5077             :         uint32_t bucketId;
    5078           0 :         if (isStsHost) {
    5079             :           // measuring STS separately allows us to measure click through
    5080             :           // rates easily
    5081           0 :           bucketId = nsISecurityUITelemetry::WARNING_BAD_CERT_TOP_STS;
    5082             :         } else {
    5083           0 :           bucketId = nsISecurityUITelemetry::WARNING_BAD_CERT_TOP;
    5084             :         }
    5085             : 
    5086             :         // See if an alternate cert error page is registered
    5087             :         nsAdoptingCString alternateErrorPage =
    5088           0 :           Preferences::GetCString("security.alternate_certificate_error_page");
    5089           0 :         if (alternateErrorPage) {
    5090           0 :           errorPage.Assign(alternateErrorPage);
    5091             :         }
    5092             : 
    5093           0 :         if (!IsFrame() && errorPage.EqualsIgnoreCase("certerror")) {
    5094           0 :           Telemetry::Accumulate(mozilla::Telemetry::SECURITY_UI, bucketId);
    5095             :         }
    5096             : 
    5097             :       } else {
    5098           0 :         error.AssignLiteral("nssFailure2");
    5099             :       }
    5100             :     }
    5101           0 :   } else if (NS_ERROR_PHISHING_URI == aError ||
    5102           0 :              NS_ERROR_MALWARE_URI == aError ||
    5103             :              NS_ERROR_UNWANTED_URI == aError) {
    5104           0 :     nsAutoCString host;
    5105           0 :     aURI->GetHost(host);
    5106           0 :     CopyUTF8toUTF16(host, formatStrs[0]);
    5107           0 :     formatStrCount = 1;
    5108             : 
    5109             :     // Malware and phishing detectors may want to use an alternate error
    5110             :     // page, but if the pref's not set, we'll fall back on the standard page
    5111             :     nsAdoptingCString alternateErrorPage =
    5112           0 :       Preferences::GetCString("urlclassifier.alternate_error_page");
    5113           0 :     if (alternateErrorPage) {
    5114           0 :       errorPage.Assign(alternateErrorPage);
    5115             :     }
    5116             : 
    5117             :     uint32_t bucketId;
    5118           0 :     bool sendTelemetry = false;
    5119           0 :     if (NS_ERROR_PHISHING_URI == aError) {
    5120           0 :       sendTelemetry = true;
    5121           0 :       error.AssignLiteral("deceptiveBlocked");
    5122           0 :       bucketId = IsFrame() ? nsISecurityUITelemetry::WARNING_PHISHING_PAGE_FRAME
    5123             :                            : nsISecurityUITelemetry::WARNING_PHISHING_PAGE_TOP;
    5124           0 :     } else if (NS_ERROR_MALWARE_URI == aError) {
    5125           0 :       sendTelemetry = true;
    5126           0 :       error.AssignLiteral("malwareBlocked");
    5127           0 :       bucketId = IsFrame() ? nsISecurityUITelemetry::WARNING_MALWARE_PAGE_FRAME
    5128             :                            : nsISecurityUITelemetry::WARNING_MALWARE_PAGE_TOP;
    5129           0 :     } else if (NS_ERROR_UNWANTED_URI == aError) {
    5130           0 :       sendTelemetry = true;
    5131           0 :       error.AssignLiteral("unwantedBlocked");
    5132           0 :       bucketId = IsFrame() ? nsISecurityUITelemetry::WARNING_UNWANTED_PAGE_FRAME
    5133             :                            : nsISecurityUITelemetry::WARNING_UNWANTED_PAGE_TOP;
    5134             :     }
    5135             : 
    5136           0 :     if (sendTelemetry && errorPage.EqualsIgnoreCase("blocked")) {
    5137           0 :       Telemetry::Accumulate(Telemetry::SECURITY_UI, bucketId);
    5138             :     }
    5139             : 
    5140           0 :     cssClass.AssignLiteral("blacklist");
    5141           0 :   } else if (NS_ERROR_CONTENT_CRASHED == aError) {
    5142           0 :     errorPage.AssignLiteral("tabcrashed");
    5143           0 :     error.AssignLiteral("tabcrashed");
    5144             : 
    5145           0 :     nsCOMPtr<EventTarget> handler = mChromeEventHandler;
    5146           0 :     if (handler) {
    5147           0 :       nsCOMPtr<Element> element = do_QueryInterface(handler);
    5148           0 :       element->GetAttribute(NS_LITERAL_STRING("crashedPageTitle"), messageStr);
    5149             :     }
    5150             : 
    5151             :     // DisplayLoadError requires a non-empty messageStr to proceed and call
    5152             :     // LoadErrorPage. If the page doesn't have a title, we will use a blank
    5153             :     // space which will be trimmed and thus treated as empty by the front-end.
    5154           0 :     if (messageStr.IsEmpty()) {
    5155           0 :       messageStr.AssignLiteral(u" ");
    5156             :     }
    5157             :   } else {
    5158             :     // Errors requiring simple formatting
    5159           0 :     switch (aError) {
    5160             :       case NS_ERROR_MALFORMED_URI:
    5161             :         // URI is malformed
    5162           0 :         error.AssignLiteral("malformedURI");
    5163           0 :         break;
    5164             :       case NS_ERROR_REDIRECT_LOOP:
    5165             :         // Doc failed to load because the server generated too many redirects
    5166           0 :         error.AssignLiteral("redirectLoop");
    5167           0 :         break;
    5168             :       case NS_ERROR_UNKNOWN_SOCKET_TYPE:
    5169             :         // Doc failed to load because PSM is not installed
    5170           0 :         error.AssignLiteral("unknownSocketType");
    5171           0 :         break;
    5172             :       case NS_ERROR_NET_RESET:
    5173             :         // Doc failed to load because the server kept reseting the connection
    5174             :         // before we could read any data from it
    5175           0 :         error.AssignLiteral("netReset");
    5176           0 :         break;
    5177             :       case NS_ERROR_DOCUMENT_NOT_CACHED:
    5178             :         // Doc failed to load because the cache does not contain a copy of
    5179             :         // the document.
    5180           0 :         error.AssignLiteral("notCached");
    5181           0 :         break;
    5182             :       case NS_ERROR_OFFLINE:
    5183             :         // Doc failed to load because we are offline.
    5184           0 :         error.AssignLiteral("netOffline");
    5185           0 :         break;
    5186             :       case NS_ERROR_DOCUMENT_IS_PRINTMODE:
    5187             :         // Doc navigation attempted while Printing or Print Preview
    5188           0 :         error.AssignLiteral("isprinting");
    5189           0 :         break;
    5190             :       case NS_ERROR_PORT_ACCESS_NOT_ALLOWED:
    5191             :         // Port blocked for security reasons
    5192           0 :         addHostPort = true;
    5193           0 :         error.AssignLiteral("deniedPortAccess");
    5194           0 :         break;
    5195             :       case NS_ERROR_UNKNOWN_PROXY_HOST:
    5196             :         // Proxy hostname could not be resolved.
    5197           0 :         error.AssignLiteral("proxyResolveFailure");
    5198           0 :         break;
    5199             :       case NS_ERROR_PROXY_CONNECTION_REFUSED:
    5200             :         // Proxy connection was refused.
    5201           0 :         error.AssignLiteral("proxyConnectFailure");
    5202           0 :         break;
    5203             :       case NS_ERROR_INVALID_CONTENT_ENCODING:
    5204             :         // Bad Content Encoding.
    5205           0 :         error.AssignLiteral("contentEncodingError");
    5206           0 :         break;
    5207             :       case NS_ERROR_REMOTE_XUL:
    5208           0 :         error.AssignLiteral("remoteXUL");
    5209           0 :         break;
    5210             :       case NS_ERROR_UNSAFE_CONTENT_TYPE:
    5211             :         // Channel refused to load from an unrecognized content type.
    5212           0 :         error.AssignLiteral("unsafeContentType");
    5213           0 :         break;
    5214             :       case NS_ERROR_CORRUPTED_CONTENT:
    5215             :         // Broken Content Detected. e.g. Content-MD5 check failure.
    5216           0 :         error.AssignLiteral("corruptedContentErrorv2");
    5217           0 :         break;
    5218             :       case NS_ERROR_INTERCEPTION_FAILED:
    5219             :         // ServiceWorker intercepted request, but something went wrong.
    5220           0 :         error.AssignLiteral("corruptedContentErrorv2");
    5221           0 :         break;
    5222             :       case NS_ERROR_NET_INADEQUATE_SECURITY:
    5223             :         // Server negotiated bad TLS for HTTP/2.
    5224           0 :         error.AssignLiteral("inadequateSecurityError");
    5225           0 :         addHostPort = true;
    5226           0 :         break;
    5227             :       default:
    5228           0 :         break;
    5229             :     }
    5230             :   }
    5231             : 
    5232             :   // Test if the error should be displayed
    5233           0 :   if (error.IsEmpty()) {
    5234           0 :     return NS_OK;
    5235             :   }
    5236             : 
    5237             :   // Test if the error needs to be formatted
    5238           0 :   if (!messageStr.IsEmpty()) {
    5239             :     // already obtained message
    5240             :   } else {
    5241           0 :     if (addHostPort) {
    5242             :       // Build up the host:port string.
    5243           0 :       nsAutoCString hostport;
    5244           0 :       if (aURI) {
    5245           0 :         aURI->GetHostPort(hostport);
    5246             :       } else {
    5247           0 :         hostport.Assign('?');
    5248             :       }
    5249           0 :       CopyUTF8toUTF16(hostport, formatStrs[formatStrCount++]);
    5250             :     }
    5251             : 
    5252           0 :     nsAutoCString spec;
    5253           0 :     rv = NS_ERROR_NOT_AVAILABLE;
    5254           0 :     if (aURI) {
    5255             :       // displaying "file://" is aesthetically unpleasing and could even be
    5256             :       // confusing to the user
    5257           0 :       bool isFileURI = false;
    5258           0 :       rv = aURI->SchemeIs("file", &isFileURI);
    5259           0 :       if (NS_SUCCEEDED(rv) && isFileURI) {
    5260           0 :         aURI->GetPath(spec);
    5261             :       } else {
    5262           0 :         aURI->GetSpec(spec);
    5263             :       }
    5264             : 
    5265           0 :       nsAutoCString charset;
    5266             :       // unescape and convert from origin charset
    5267           0 :       aURI->GetOriginCharset(charset);
    5268             :       nsCOMPtr<nsITextToSubURI> textToSubURI(
    5269           0 :         do_GetService(NS_ITEXTTOSUBURI_CONTRACTID, &rv));
    5270           0 :       if (NS_SUCCEEDED(rv)) {
    5271           0 :         rv = textToSubURI->UnEscapeURIForUI(charset, spec,
    5272           0 :                                             formatStrs[formatStrCount]);
    5273             :       }
    5274             :     } else {
    5275           0 :       spec.Assign('?');
    5276             :     }
    5277           0 :     if (NS_FAILED(rv)) {
    5278           0 :       CopyUTF8toUTF16(spec, formatStrs[formatStrCount]);
    5279             :     }
    5280           0 :     rv = NS_OK;
    5281           0 :     ++formatStrCount;
    5282             : 
    5283             :     const char16_t* strs[kMaxFormatStrArgs];
    5284           0 :     for (uint32_t i = 0; i < formatStrCount; i++) {
    5285           0 :       strs[i] = formatStrs[i].get();
    5286             :     }
    5287           0 :     nsXPIDLString str;
    5288           0 :     rv = stringBundle->FormatStringFromName(error.get(), strs, formatStrCount,
    5289           0 :                                             getter_Copies(str));
    5290           0 :     NS_ENSURE_SUCCESS(rv, rv);
    5291           0 :     messageStr.Assign(str.get());
    5292             :   }
    5293             : 
    5294             :   // Display the error as a page or an alert prompt
    5295           0 :   NS_ENSURE_FALSE(messageStr.IsEmpty(), NS_ERROR_FAILURE);
    5296             : 
    5297           0 :   if (NS_ERROR_NET_INTERRUPT == aError || NS_ERROR_NET_RESET == aError) {
    5298           0 :     bool isSecureURI = false;
    5299           0 :     rv = aURI->SchemeIs("https", &isSecureURI);
    5300           0 :     if (NS_SUCCEEDED(rv) && isSecureURI) {
    5301             :       // Maybe TLS intolerant. Treat this as an SSL error.
    5302           0 :       error.AssignLiteral("nssFailure2");
    5303             :     }
    5304             :   }
    5305             : 
    5306           0 :   if (UseErrorPages()) {
    5307             :     // Display an error page
    5308           0 :     nsresult loadedPage = LoadErrorPage(aURI, aURL, errorPage.get(),
    5309             :                                         error.get(), messageStr.get(),
    5310           0 :                                         cssClass.get(), aFailedChannel);
    5311           0 :     *aDisplayedErrorPage = NS_SUCCEEDED(loadedPage);
    5312             :   } else {
    5313             :     // The prompter reqires that our private window has a document (or it
    5314             :     // asserts). Satisfy that assertion now since GetDoc will force
    5315             :     // creation of one if it hasn't already been created.
    5316           0 :     if (mScriptGlobal) {
    5317           0 :       Unused << mScriptGlobal->GetDoc();
    5318             :     }
    5319             : 
    5320             :     // Display a message box
    5321           0 :     prompter->Alert(nullptr, messageStr.get());
    5322             :   }
    5323             : 
    5324           0 :   return NS_OK;
    5325             : }
    5326             : 
    5327             : #define PREF_SAFEBROWSING_ALLOWOVERRIDE "browser.safebrowsing.allowOverride"
    5328             : 
    5329             : NS_IMETHODIMP
    5330           0 : nsDocShell::LoadErrorPage(nsIURI* aURI, const char16_t* aURL,
    5331             :                           const char* aErrorPage,
    5332             :                           const char16_t* aErrorType,
    5333             :                           const char16_t* aDescription,
    5334             :                           const char* aCSSClass,
    5335             :                           nsIChannel* aFailedChannel)
    5336             : {
    5337             : #if defined(DEBUG)
    5338           0 :   if (MOZ_LOG_TEST(gDocShellLog, LogLevel::Debug)) {
    5339           0 :     nsAutoCString chanName;
    5340           0 :     if (aFailedChannel) {
    5341           0 :       aFailedChannel->GetName(chanName);
    5342             :     } else {
    5343           0 :       chanName.AssignLiteral("<no channel>");
    5344             :     }
    5345             : 
    5346           0 :     MOZ_LOG(gDocShellLog, LogLevel::Debug,
    5347             :            ("nsDocShell[%p]::LoadErrorPage(\"%s\", \"%s\", {...}, [%s])\n", this,
    5348             :             aURI ? aURI->GetSpecOrDefault().get() : "",
    5349             :             NS_ConvertUTF16toUTF8(aURL).get(),
    5350             :             chanName.get()));
    5351             :   }
    5352             : #endif
    5353           0 :   mFailedChannel = aFailedChannel;
    5354           0 :   mFailedURI = aURI;
    5355           0 :   mFailedLoadType = mLoadType;
    5356             : 
    5357           0 :   if (mLSHE) {
    5358             :     // Abandon mLSHE's BFCache entry and create a new one.  This way, if
    5359             :     // we go back or forward to another SHEntry with the same doc
    5360             :     // identifier, the error page won't persist.
    5361           0 :     mLSHE->AbandonBFCacheEntry();
    5362             :   }
    5363             : 
    5364           0 :   nsAutoCString url;
    5365           0 :   nsAutoCString charset;
    5366           0 :   if (aURI) {
    5367           0 :     nsresult rv = aURI->GetSpec(url);
    5368           0 :     NS_ENSURE_SUCCESS(rv, rv);
    5369           0 :     rv = aURI->GetOriginCharset(charset);
    5370           0 :     NS_ENSURE_SUCCESS(rv, rv);
    5371           0 :   } else if (aURL) {
    5372           0 :     CopyUTF16toUTF8(aURL, url);
    5373             :   } else {
    5374           0 :     return NS_ERROR_INVALID_POINTER;
    5375             :   }
    5376             : 
    5377             :   // Create a URL to pass all the error information through to the page.
    5378             : 
    5379             : #undef SAFE_ESCAPE
    5380             : #define SAFE_ESCAPE(output, input, params)                                     \
    5381             :   if (NS_WARN_IF(!NS_Escape(input, output, params))) {                         \
    5382             :     return NS_ERROR_OUT_OF_MEMORY;                                             \
    5383             :   }
    5384             : 
    5385           0 :   nsCString escapedUrl, escapedCharset, escapedError, escapedDescription,
    5386           0 :     escapedCSSClass;
    5387           0 :   SAFE_ESCAPE(escapedUrl, url, url_Path);
    5388           0 :   SAFE_ESCAPE(escapedCharset, charset, url_Path);
    5389           0 :   SAFE_ESCAPE(escapedError, NS_ConvertUTF16toUTF8(aErrorType), url_Path);
    5390           0 :   SAFE_ESCAPE(escapedDescription,
    5391             :               NS_ConvertUTF16toUTF8(aDescription), url_Path);
    5392           0 :   if (aCSSClass) {
    5393           0 :     nsCString cssClass(aCSSClass);
    5394           0 :     SAFE_ESCAPE(escapedCSSClass, cssClass, url_Path);
    5395             :   }
    5396           0 :   nsCString errorPageUrl("about:");
    5397           0 :   errorPageUrl.AppendASCII(aErrorPage);
    5398           0 :   errorPageUrl.AppendLiteral("?e=");
    5399             : 
    5400           0 :   errorPageUrl.AppendASCII(escapedError.get());
    5401           0 :   errorPageUrl.AppendLiteral("&u=");
    5402           0 :   errorPageUrl.AppendASCII(escapedUrl.get());
    5403           0 :   if ((strcmp(aErrorPage, "blocked") == 0) &&
    5404           0 :       Preferences::GetBool(PREF_SAFEBROWSING_ALLOWOVERRIDE, true)) {
    5405           0 :     errorPageUrl.AppendLiteral("&o=1");
    5406             :   }
    5407           0 :   if (!escapedCSSClass.IsEmpty()) {
    5408           0 :     errorPageUrl.AppendLiteral("&s=");
    5409           0 :     errorPageUrl.AppendASCII(escapedCSSClass.get());
    5410             :   }
    5411           0 :   errorPageUrl.AppendLiteral("&c=");
    5412           0 :   errorPageUrl.AppendASCII(escapedCharset.get());
    5413             : 
    5414           0 :   nsAutoCString frameType(FrameTypeToString(mFrameType));
    5415           0 :   errorPageUrl.AppendLiteral("&f=");
    5416           0 :   errorPageUrl.AppendASCII(frameType.get());
    5417             : 
    5418           0 :   nsCOMPtr<nsICaptivePortalService> cps = do_GetService(NS_CAPTIVEPORTAL_CID);
    5419             :   int32_t cpsState;
    5420           0 :   if (cps && NS_SUCCEEDED(cps->GetState(&cpsState)) &&
    5421           0 :       cpsState == nsICaptivePortalService::LOCKED_PORTAL) {
    5422           0 :     errorPageUrl.AppendLiteral("&captive=true");
    5423             :   }
    5424             : 
    5425             :   // netError.xhtml's getDescription only handles the "d" parameter at the
    5426             :   // end of the URL, so append it last.
    5427           0 :   errorPageUrl.AppendLiteral("&d=");
    5428           0 :   errorPageUrl.AppendASCII(escapedDescription.get());
    5429             : 
    5430           0 :   nsCOMPtr<nsIURI> errorPageURI;
    5431           0 :   nsresult rv = NS_NewURI(getter_AddRefs(errorPageURI), errorPageUrl);
    5432           0 :   NS_ENSURE_SUCCESS(rv, rv);
    5433             : 
    5434           0 :   return InternalLoad(errorPageURI, nullptr, Nothing(), false, nullptr,
    5435             :                       mozilla::net::RP_Unset,
    5436             :                       nsContentUtils::GetSystemPrincipal(), nullptr,
    5437           0 :                       INTERNAL_LOAD_FLAGS_NONE, EmptyString(),
    5438           0 :                       nullptr, NullString(), nullptr, nullptr, LOAD_ERROR_PAGE,
    5439           0 :                       nullptr, true, NullString(), this, nullptr, false,
    5440           0 :                       nullptr, nullptr);
    5441             : }
    5442             : 
    5443             : NS_IMETHODIMP
    5444           0 : nsDocShell::Reload(uint32_t aReloadFlags)
    5445             : {
    5446           0 :   if (!IsNavigationAllowed()) {
    5447           0 :     return NS_OK; // JS may not handle returning of an error code
    5448             :   }
    5449             :   nsresult rv;
    5450           0 :   NS_ASSERTION(((aReloadFlags & 0xf) == 0),
    5451             :                "Reload command not updated to use load flags!");
    5452           0 :   NS_ASSERTION((aReloadFlags & EXTRA_LOAD_FLAGS) == 0,
    5453             :                "Don't pass these flags to Reload");
    5454             : 
    5455           0 :   uint32_t loadType = MAKE_LOAD_TYPE(LOAD_RELOAD_NORMAL, aReloadFlags);
    5456           0 :   NS_ENSURE_TRUE(IsValidLoadType(loadType), NS_ERROR_INVALID_ARG);
    5457             : 
    5458             :   // Send notifications to the HistoryListener if any, about the impending
    5459             :   // reload
    5460           0 :   nsCOMPtr<nsISHistory> rootSH;
    5461           0 :   rv = GetRootSessionHistory(getter_AddRefs(rootSH));
    5462           0 :   nsCOMPtr<nsISHistoryInternal> shistInt(do_QueryInterface(rootSH));
    5463           0 :   bool canReload = true;
    5464           0 :   if (rootSH) {
    5465           0 :     shistInt->NotifyOnHistoryReload(mCurrentURI, aReloadFlags, &canReload);
    5466             :   }
    5467             : 
    5468           0 :   if (!canReload) {
    5469           0 :     return NS_OK;
    5470             :   }
    5471             : 
    5472             :   /* If you change this part of code, make sure bug 45297 does not re-occur */
    5473           0 :   if (mOSHE) {
    5474           0 :     rv = LoadHistoryEntry(mOSHE, loadType);
    5475           0 :   } else if (mLSHE) { // In case a reload happened before the current load is done
    5476           0 :     rv = LoadHistoryEntry(mLSHE, loadType);
    5477             :   } else {
    5478           0 :     nsCOMPtr<nsIDocument> doc(GetDocument());
    5479             : 
    5480           0 :     if (!doc) {
    5481           0 :       return NS_OK;
    5482             :     }
    5483             : 
    5484             :     // Do not inherit owner from document
    5485           0 :     uint32_t flags = INTERNAL_LOAD_FLAGS_NONE;
    5486           0 :     nsAutoString srcdoc;
    5487           0 :     nsCOMPtr<nsIURI> baseURI;
    5488           0 :     nsCOMPtr<nsIURI> originalURI;
    5489           0 :     nsCOMPtr<nsIURI> resultPrincipalURI;
    5490           0 :     bool loadReplace = false;
    5491             : 
    5492           0 :     nsIPrincipal* triggeringPrincipal = doc->NodePrincipal();
    5493           0 :     nsAutoString contentTypeHint;
    5494           0 :     doc->GetContentType(contentTypeHint);
    5495             : 
    5496           0 :     if (doc->IsSrcdocDocument()) {
    5497           0 :       doc->GetSrcdocData(srcdoc);
    5498           0 :       flags |= INTERNAL_LOAD_FLAGS_IS_SRCDOC;
    5499           0 :       baseURI = doc->GetBaseURI();
    5500             :     }
    5501           0 :     nsCOMPtr<nsIChannel> chan = doc->GetChannel();
    5502           0 :     if (chan) {
    5503             :       uint32_t loadFlags;
    5504           0 :       chan->GetLoadFlags(&loadFlags);
    5505           0 :       loadReplace = loadFlags & nsIChannel::LOAD_REPLACE;
    5506           0 :       nsCOMPtr<nsIHttpChannel> httpChan(do_QueryInterface(chan));
    5507           0 :       if (httpChan) {
    5508           0 :         httpChan->GetOriginalURI(getter_AddRefs(originalURI));
    5509             :       }
    5510             : 
    5511           0 :       nsCOMPtr<nsILoadInfo> loadInfo = chan->GetLoadInfo();
    5512           0 :       if (loadInfo) {
    5513           0 :         loadInfo->GetResultPrincipalURI(getter_AddRefs(resultPrincipalURI));
    5514             :       }
    5515             :     }
    5516             : 
    5517           0 :     MOZ_ASSERT(triggeringPrincipal, "Need a valid triggeringPrincipal");
    5518             : 
    5519             :     // Stack variables to ensure changes to the member variables don't affect to
    5520             :     // the call.
    5521           0 :     nsCOMPtr<nsIURI> currentURI = mCurrentURI;
    5522           0 :     nsCOMPtr<nsIURI> referrerURI = mReferrerURI;
    5523           0 :     uint32_t referrerPolicy = mReferrerPolicy;
    5524             : 
    5525             :     // Reload always rewrites result principal URI.
    5526           0 :     Maybe<nsCOMPtr<nsIURI>> emplacedResultPrincipalURI;
    5527           0 :     emplacedResultPrincipalURI.emplace(Move(resultPrincipalURI));
    5528           0 :     rv = InternalLoad(currentURI,
    5529             :                       originalURI,
    5530             :                       emplacedResultPrincipalURI,
    5531             :                       loadReplace,
    5532             :                       referrerURI,
    5533             :                       referrerPolicy,
    5534             :                       triggeringPrincipal,
    5535             :                       triggeringPrincipal,
    5536             :                       flags,
    5537           0 :                       EmptyString(),   // No window target
    5538           0 :                       NS_LossyConvertUTF16toASCII(contentTypeHint).get(),
    5539           0 :                       NullString(),    // No forced download
    5540             :                       nullptr,         // No post data
    5541             :                       nullptr,         // No headers data
    5542             :                       loadType,        // Load type
    5543             :                       nullptr,         // No SHEntry
    5544             :                       true,
    5545             :                       srcdoc,          // srcdoc argument for iframe
    5546             :                       this,            // For reloads we are the source
    5547             :                       baseURI,
    5548             :                       false,
    5549             :                       nullptr,         // No nsIDocShell
    5550           0 :                       nullptr);        // No nsIRequest
    5551             :   }
    5552             : 
    5553           0 :   return rv;
    5554             : }
    5555             : 
    5556             : NS_IMETHODIMP
    5557           7 : nsDocShell::Stop(uint32_t aStopFlags)
    5558             : {
    5559             :   // Revoke any pending event related to content viewer restoration
    5560           7 :   mRestorePresentationEvent.Revoke();
    5561             : 
    5562           7 :   if (mLoadType == LOAD_ERROR_PAGE) {
    5563           0 :     if (mLSHE) {
    5564             :       // Since error page loads never unset mLSHE, do so now
    5565           0 :       SetHistoryEntry(&mOSHE, mLSHE);
    5566           0 :       SetHistoryEntry(&mLSHE, nullptr);
    5567             :     }
    5568             : 
    5569           0 :     mFailedChannel = nullptr;
    5570           0 :     mFailedURI = nullptr;
    5571             :   }
    5572             : 
    5573           7 :   if (nsIWebNavigation::STOP_CONTENT & aStopFlags) {
    5574             :     // Stop the document loading
    5575           1 :     if (mContentViewer) {
    5576           2 :       nsCOMPtr<nsIContentViewer> cv = mContentViewer;
    5577           1 :       cv->Stop();
    5578             :     }
    5579             :   }
    5580             : 
    5581           7 :   if (nsIWebNavigation::STOP_NETWORK & aStopFlags) {
    5582             :     // Suspend any timers that were set for this loader.  We'll clear
    5583             :     // them out for good in CreateContentViewer.
    5584           7 :     if (mRefreshURIList) {
    5585           0 :       SuspendRefreshURIs();
    5586           0 :       mSavedRefreshURIList.swap(mRefreshURIList);
    5587           0 :       mRefreshURIList = nullptr;
    5588             :     }
    5589             : 
    5590             :     // XXXbz We could also pass |this| to nsIURILoader::Stop.  That will
    5591             :     // just call Stop() on us as an nsIDocumentLoader... We need fewer
    5592             :     // redundant apis!
    5593           7 :     Stop();
    5594             :   }
    5595             : 
    5596          14 :   nsTObserverArray<nsDocLoader*>::ForwardIterator iter(mChildList);
    5597           7 :   while (iter.HasMore()) {
    5598           0 :     nsCOMPtr<nsIWebNavigation> shellAsNav(do_QueryObject(iter.GetNext()));
    5599           0 :     if (shellAsNav) {
    5600           0 :       shellAsNav->Stop(aStopFlags);
    5601             :     }
    5602             :   }
    5603             : 
    5604          14 :   return NS_OK;
    5605             : }
    5606             : 
    5607             : NS_IMETHODIMP
    5608         393 : nsDocShell::GetDocument(nsIDOMDocument** aDocument)
    5609             : {
    5610         393 :   NS_ENSURE_ARG_POINTER(aDocument);
    5611         393 :   NS_ENSURE_SUCCESS(EnsureContentViewer(), NS_ERROR_FAILURE);
    5612             : 
    5613         393 :   return mContentViewer->GetDOMDocument(aDocument);
    5614             : }
    5615             : 
    5616             : NS_IMETHODIMP
    5617          12 : nsDocShell::GetCurrentURI(nsIURI** aURI)
    5618             : {
    5619          12 :   NS_ENSURE_ARG_POINTER(aURI);
    5620             : 
    5621          12 :   if (mCurrentURI) {
    5622          12 :     return NS_EnsureSafeToReturn(mCurrentURI, aURI);
    5623             :   }
    5624             : 
    5625           0 :   *aURI = nullptr;
    5626           0 :   return NS_OK;
    5627             : }
    5628             : 
    5629             : NS_IMETHODIMP
    5630           0 : nsDocShell::GetReferringURI(nsIURI** aURI)
    5631             : {
    5632           0 :   NS_ENSURE_ARG_POINTER(aURI);
    5633             : 
    5634           0 :   *aURI = mReferrerURI;
    5635           0 :   NS_IF_ADDREF(*aURI);
    5636             : 
    5637           0 :   return NS_OK;
    5638             : }
    5639             : 
    5640             : NS_IMETHODIMP
    5641           2 : nsDocShell::SetSessionHistory(nsISHistory* aSessionHistory)
    5642             : {
    5643           2 :   NS_ENSURE_TRUE(aSessionHistory, NS_ERROR_FAILURE);
    5644             :   // make sure that we are the root docshell and
    5645             :   // set a handle to root docshell in SH.
    5646             : 
    5647           4 :   nsCOMPtr<nsIDocShellTreeItem> root;
    5648             :   /* Get the root docshell. If *this* is the root docshell
    5649             :    * then save a handle to *this* in SH. SH needs it to do
    5650             :    * traversions thro' its entries
    5651             :    */
    5652           2 :   GetSameTypeRootTreeItem(getter_AddRefs(root));
    5653           2 :   NS_ENSURE_TRUE(root, NS_ERROR_FAILURE);
    5654           2 :   if (root.get() == static_cast<nsIDocShellTreeItem*>(this)) {
    5655           2 :     mSessionHistory = aSessionHistory;
    5656             :     nsCOMPtr<nsISHistoryInternal> shPrivate =
    5657           4 :       do_QueryInterface(mSessionHistory);
    5658           2 :     NS_ENSURE_TRUE(shPrivate, NS_ERROR_FAILURE);
    5659           2 :     shPrivate->SetRootDocShell(this);
    5660           2 :     return NS_OK;
    5661             :   }
    5662           0 :   return NS_ERROR_FAILURE;
    5663             : }
    5664             : 
    5665             : NS_IMETHODIMP
    5666          19 : nsDocShell::GetSessionHistory(nsISHistory** aSessionHistory)
    5667             : {
    5668          19 :   NS_ENSURE_ARG_POINTER(aSessionHistory);
    5669          19 :   *aSessionHistory = mSessionHistory;
    5670          19 :   NS_IF_ADDREF(*aSessionHistory);
    5671          19 :   return NS_OK;
    5672             : }
    5673             : 
    5674             : //*****************************************************************************
    5675             : // nsDocShell::nsIWebPageDescriptor
    5676             : //*****************************************************************************
    5677             : 
    5678             : NS_IMETHODIMP
    5679           0 : nsDocShell::LoadPage(nsISupports* aPageDescriptor, uint32_t aDisplayType)
    5680             : {
    5681           0 :   nsCOMPtr<nsISHEntry> shEntryIn(do_QueryInterface(aPageDescriptor));
    5682             : 
    5683             :   // Currently, the opaque 'page descriptor' is an nsISHEntry...
    5684           0 :   if (!shEntryIn) {
    5685           0 :     return NS_ERROR_INVALID_POINTER;
    5686             :   }
    5687             : 
    5688             :   // Now clone shEntryIn, since we might end up modifying it later on, and we
    5689             :   // want a page descriptor to be reusable.
    5690           0 :   nsCOMPtr<nsISHEntry> shEntry;
    5691           0 :   nsresult rv = shEntryIn->Clone(getter_AddRefs(shEntry));
    5692           0 :   NS_ENSURE_SUCCESS(rv, rv);
    5693             : 
    5694             :   // Give our cloned shEntry a new bfcache entry so this load is independent
    5695             :   // of all other loads.  (This is important, in particular, for bugs 582795
    5696             :   // and 585298.)
    5697           0 :   rv = shEntry->AbandonBFCacheEntry();
    5698           0 :   NS_ENSURE_SUCCESS(rv, rv);
    5699             : 
    5700             :   //
    5701             :   // load the page as view-source
    5702             :   //
    5703           0 :   if (nsIWebPageDescriptor::DISPLAY_AS_SOURCE == aDisplayType) {
    5704           0 :     nsCOMPtr<nsIURI> oldUri, newUri;
    5705           0 :     nsCString spec, newSpec;
    5706             : 
    5707             :     // Create a new view-source URI and replace the original.
    5708           0 :     rv = shEntry->GetURI(getter_AddRefs(oldUri));
    5709           0 :     if (NS_FAILED(rv)) {
    5710           0 :       return rv;
    5711             :     }
    5712             : 
    5713           0 :     oldUri->GetSpec(spec);
    5714           0 :     newSpec.AppendLiteral("view-source:");
    5715           0 :     newSpec.Append(spec);
    5716             : 
    5717           0 :     rv = NS_NewURI(getter_AddRefs(newUri), newSpec);
    5718           0 :     if (NS_FAILED(rv)) {
    5719           0 :       return rv;
    5720             :     }
    5721           0 :     shEntry->SetURI(newUri);
    5722           0 :     shEntry->SetOriginalURI(nullptr);
    5723             :     // shEntry's current triggering principal is whoever loaded that page initially.
    5724             :     // But now we're doing another load of the page, via an API that is only exposed
    5725             :     // to system code.  The triggering principal for this load should be the system
    5726             :     // principal.
    5727           0 :     shEntry->SetTriggeringPrincipal(nsContentUtils::GetSystemPrincipal());
    5728             :   }
    5729             : 
    5730           0 :   rv = LoadHistoryEntry(shEntry, LOAD_HISTORY);
    5731           0 :   return rv;
    5732             : }
    5733             : 
    5734             : NS_IMETHODIMP
    5735           0 : nsDocShell::GetCurrentDescriptor(nsISupports** aPageDescriptor)
    5736             : {
    5737           0 :   NS_PRECONDITION(aPageDescriptor, "Null out param?");
    5738             : 
    5739           0 :   *aPageDescriptor = nullptr;
    5740             : 
    5741           0 :   nsISHEntry* src = mOSHE ? mOSHE : mLSHE;
    5742           0 :   if (src) {
    5743           0 :     nsCOMPtr<nsISHEntry> dest;
    5744             : 
    5745           0 :     nsresult rv = src->Clone(getter_AddRefs(dest));
    5746           0 :     if (NS_FAILED(rv)) {
    5747           0 :       return rv;
    5748             :     }
    5749             : 
    5750             :     // null out inappropriate cloned attributes...
    5751           0 :     dest->SetParent(nullptr);
    5752           0 :     dest->SetIsSubFrame(false);
    5753             : 
    5754           0 :     return CallQueryInterface(dest, aPageDescriptor);
    5755             :   }
    5756             : 
    5757           0 :   return NS_ERROR_NOT_AVAILABLE;
    5758             : }
    5759             : 
    5760             : //*****************************************************************************
    5761             : // nsDocShell::nsIBaseWindow
    5762             : //*****************************************************************************
    5763             : 
    5764             : NS_IMETHODIMP
    5765           3 : nsDocShell::InitWindow(nativeWindow aParentNativeWindow,
    5766             :                        nsIWidget* aParentWidget, int32_t aX, int32_t aY,
    5767             :                        int32_t aWidth, int32_t aHeight)
    5768             : {
    5769           3 :   SetParentWidget(aParentWidget);
    5770           3 :   SetPositionAndSize(aX, aY, aWidth, aHeight, 0);
    5771             : 
    5772           3 :   return NS_OK;
    5773             : }
    5774             : 
    5775             : NS_IMETHODIMP
    5776           5 : nsDocShell::Create()
    5777             : {
    5778           5 :   if (mCreated) {
    5779             :     // We've already been created
    5780           0 :     return NS_OK;
    5781             :   }
    5782             : 
    5783           5 :   NS_ASSERTION(mItemType == typeContent || mItemType == typeChrome,
    5784             :                "Unexpected item type in docshell");
    5785             : 
    5786           5 :   NS_ENSURE_TRUE(Preferences::GetRootBranch(), NS_ERROR_FAILURE);
    5787           5 :   mCreated = true;
    5788             : 
    5789           5 :   if (gValidateOrigin == 0xffffffff) {
    5790             :     // Check pref to see if we should prevent frameset spoofing
    5791           2 :     gValidateOrigin =
    5792           2 :       Preferences::GetBool("browser.frame.validate_origin", true);
    5793             :   }
    5794             : 
    5795             :   // Should we use XUL error pages instead of alerts if possible?
    5796           5 :   mUseErrorPages =
    5797           5 :     Preferences::GetBool("browser.xul.error_pages.enabled", mUseErrorPages);
    5798             : 
    5799           5 :   if (!gAddedPreferencesVarCache) {
    5800           2 :     Preferences::AddBoolVarCache(&sUseErrorPages,
    5801             :                                  "browser.xul.error_pages.enabled",
    5802           4 :                                  mUseErrorPages);
    5803           2 :     gAddedPreferencesVarCache = true;
    5804             :   }
    5805             : 
    5806           5 :   mDisableMetaRefreshWhenInactive =
    5807           5 :     Preferences::GetBool("browser.meta_refresh_when_inactive.disabled",
    5808           5 :                          mDisableMetaRefreshWhenInactive);
    5809             : 
    5810           5 :   mDeviceSizeIsPageSize =
    5811           5 :     Preferences::GetBool("docshell.device_size_is_page_size",
    5812           5 :                          mDeviceSizeIsPageSize);
    5813             : 
    5814          10 :   nsCOMPtr<nsIObserverService> serv = services::GetObserverService();
    5815           5 :   if (serv) {
    5816           5 :     const char* msg = mItemType == typeContent ?
    5817           5 :       NS_WEBNAVIGATION_CREATE : NS_CHROME_WEBNAVIGATION_CREATE;
    5818           5 :     serv->NotifyObservers(GetAsSupports(this), msg, nullptr);
    5819             :   }
    5820             : 
    5821           5 :   return NS_OK;
    5822             : }
    5823             : 
    5824             : NS_IMETHODIMP
    5825           1 : nsDocShell::Destroy()
    5826             : {
    5827           1 :   NS_ASSERTION(mItemType == typeContent || mItemType == typeChrome,
    5828             :                "Unexpected item type in docshell");
    5829             : 
    5830           1 :   AssertOriginAttributesMatchPrivateBrowsing();
    5831             : 
    5832           1 :   if (!mIsBeingDestroyed) {
    5833           2 :     nsCOMPtr<nsIObserverService> serv = services::GetObserverService();
    5834           1 :     if (serv) {
    5835           1 :       const char* msg = mItemType == typeContent ?
    5836           1 :         NS_WEBNAVIGATION_DESTROY : NS_CHROME_WEBNAVIGATION_DESTROY;
    5837           1 :       serv->NotifyObservers(GetAsSupports(this), msg, nullptr);
    5838             :     }
    5839             :   }
    5840             : 
    5841           1 :   mIsBeingDestroyed = true;
    5842             : 
    5843             :   // Make sure we don't record profile timeline markers anymore
    5844           1 :   SetRecordProfileTimelineMarkers(false);
    5845             : 
    5846             :   // Remove our pref observers
    5847           1 :   if (mObserveErrorPages) {
    5848           1 :     mObserveErrorPages = false;
    5849             :   }
    5850             : 
    5851             :   // Make sure to blow away our mLoadingURI just in case.  No loads
    5852             :   // from inside this pagehide.
    5853           1 :   mLoadingURI = nullptr;
    5854             : 
    5855             :   // Fire unload event before we blow anything away.
    5856           1 :   (void)FirePageHideNotification(true);
    5857             : 
    5858             :   // Clear pointers to any detached nsEditorData that's lying
    5859             :   // around in shistory entries. Breaks cycle. See bug 430921.
    5860           1 :   if (mOSHE) {
    5861           0 :     mOSHE->SetEditorData(nullptr);
    5862             :   }
    5863           1 :   if (mLSHE) {
    5864           0 :     mLSHE->SetEditorData(nullptr);
    5865             :   }
    5866             : 
    5867             :   // Note: mContentListener can be null if Init() failed and we're being
    5868             :   // called from the destructor.
    5869           1 :   if (mContentListener) {
    5870           1 :     mContentListener->DropDocShellReference();
    5871           1 :     mContentListener->SetParentContentListener(nullptr);
    5872             :     // Note that we do NOT set mContentListener to null here; that
    5873             :     // way if someone tries to do a load in us after this point
    5874             :     // the nsDSURIContentListener will block it.  All of which
    5875             :     // means that we should do this before calling Stop(), of
    5876             :     // course.
    5877             :   }
    5878             : 
    5879             :   // Stop any URLs that are currently being loaded...
    5880           1 :   Stop(nsIWebNavigation::STOP_ALL);
    5881             : 
    5882           1 :   mEditorData = nullptr;
    5883             : 
    5884           1 :   mTransferableHookData = nullptr;
    5885             : 
    5886             :   // Save the state of the current document, before destroying the window.
    5887             :   // This is needed to capture the state of a frameset when the new document
    5888             :   // causes the frameset to be destroyed...
    5889           1 :   PersistLayoutHistoryState();
    5890             : 
    5891             :   // Remove this docshell from its parent's child list
    5892             :   nsCOMPtr<nsIDocShellTreeItem> docShellParentAsItem =
    5893           2 :     do_QueryInterface(GetAsSupports(mParent));
    5894           1 :   if (docShellParentAsItem) {
    5895           1 :     docShellParentAsItem->RemoveChild(this);
    5896             :   }
    5897             : 
    5898           1 :   if (mContentViewer) {
    5899           1 :     mContentViewer->Close(nullptr);
    5900           1 :     mContentViewer->Destroy();
    5901           1 :     mContentViewer = nullptr;
    5902             :   }
    5903             : 
    5904           1 :   nsDocLoader::Destroy();
    5905             : 
    5906           1 :   mParentWidget = nullptr;
    5907           1 :   mCurrentURI = nullptr;
    5908             : 
    5909           1 :   if (mScriptGlobal) {
    5910           1 :     mScriptGlobal->DetachFromDocShell();
    5911           1 :     mScriptGlobal = nullptr;
    5912             :   }
    5913             : 
    5914           1 :   if (mSessionHistory) {
    5915             :     // We want to destroy these content viewers now rather than
    5916             :     // letting their destruction wait for the session history
    5917             :     // entries to get garbage collected.  (Bug 488394)
    5918             :     nsCOMPtr<nsISHistoryInternal> shPrivate =
    5919           2 :       do_QueryInterface(mSessionHistory);
    5920           1 :     if (shPrivate) {
    5921           1 :       shPrivate->EvictAllContentViewers();
    5922             :     }
    5923           1 :     mSessionHistory = nullptr;
    5924             :   }
    5925             : 
    5926           1 :   SetTreeOwner(nullptr);
    5927             : 
    5928           1 :   mOnePermittedSandboxedNavigator = nullptr;
    5929             : 
    5930             :   // required to break ref cycle
    5931           1 :   mSecurityUI = nullptr;
    5932             : 
    5933             :   // Cancel any timers that were set for this docshell; this is needed
    5934             :   // to break the cycle between us and the timers.
    5935           1 :   CancelRefreshURITimers();
    5936             : 
    5937           1 :   if (UsePrivateBrowsing()) {
    5938           0 :     mPrivateBrowsingId = 0;
    5939           0 :     mOriginAttributes.SyncAttributesWithPrivateBrowsing(false);
    5940           0 :     if (mAffectPrivateSessionLifetime) {
    5941           0 :       DecreasePrivateDocShellCount();
    5942             :     }
    5943             :   }
    5944             : 
    5945           2 :   return NS_OK;
    5946             : }
    5947             : 
    5948             : NS_IMETHODIMP
    5949           0 : nsDocShell::GetUnscaledDevicePixelsPerCSSPixel(double* aScale)
    5950             : {
    5951           0 :   if (mParentWidget) {
    5952           0 :     *aScale = mParentWidget->GetDefaultScale().scale;
    5953           0 :     return NS_OK;
    5954             :   }
    5955             : 
    5956           0 :   nsCOMPtr<nsIBaseWindow> ownerWindow(do_QueryInterface(mTreeOwner));
    5957           0 :   if (ownerWindow) {
    5958           0 :     return ownerWindow->GetUnscaledDevicePixelsPerCSSPixel(aScale);
    5959             :   }
    5960             : 
    5961           0 :   *aScale = 1.0;
    5962           0 :   return NS_OK;
    5963             : }
    5964             : 
    5965             : NS_IMETHODIMP
    5966           0 : nsDocShell::GetDevicePixelsPerDesktopPixel(double* aScale)
    5967             : {
    5968           0 :   if (mParentWidget) {
    5969           0 :     *aScale = mParentWidget->GetDesktopToDeviceScale().scale;
    5970           0 :     return NS_OK;
    5971             :   }
    5972             : 
    5973           0 :   nsCOMPtr<nsIBaseWindow> ownerWindow(do_QueryInterface(mTreeOwner));
    5974           0 :   if (ownerWindow) {
    5975           0 :     return ownerWindow->GetDevicePixelsPerDesktopPixel(aScale);
    5976             :   }
    5977             : 
    5978           0 :   *aScale = 1.0;
    5979           0 :   return NS_OK;
    5980             : }
    5981             : 
    5982             : NS_IMETHODIMP
    5983           0 : nsDocShell::SetPosition(int32_t aX, int32_t aY)
    5984             : {
    5985           0 :   mBounds.x = aX;
    5986           0 :   mBounds.y = aY;
    5987             : 
    5988           0 :   if (mContentViewer) {
    5989           0 :     NS_ENSURE_SUCCESS(mContentViewer->Move(aX, aY), NS_ERROR_FAILURE);
    5990             :   }
    5991             : 
    5992           0 :   return NS_OK;
    5993             : }
    5994             : 
    5995             : NS_IMETHODIMP
    5996           0 : nsDocShell::SetPositionDesktopPix(int32_t aX, int32_t aY)
    5997             : {
    5998           0 :   nsCOMPtr<nsIBaseWindow> ownerWindow(do_QueryInterface(mTreeOwner));
    5999           0 :   if (ownerWindow) {
    6000           0 :     return ownerWindow->SetPositionDesktopPix(aX, aY);
    6001             :   }
    6002             : 
    6003           0 :   double scale = 1.0;
    6004           0 :   GetDevicePixelsPerDesktopPixel(&scale);
    6005           0 :   return SetPosition(NSToIntRound(aX * scale), NSToIntRound(aY * scale));
    6006             : }
    6007             : 
    6008             : NS_IMETHODIMP
    6009           0 : nsDocShell::GetPosition(int32_t* aX, int32_t* aY)
    6010             : {
    6011           0 :   return GetPositionAndSize(aX, aY, nullptr, nullptr);
    6012             : }
    6013             : 
    6014             : NS_IMETHODIMP
    6015           0 : nsDocShell::SetSize(int32_t aWidth, int32_t aHeight, bool aRepaint)
    6016             : {
    6017           0 :   int32_t x = 0, y = 0;
    6018           0 :   GetPosition(&x, &y);
    6019           0 :   return SetPositionAndSize(x, y, aWidth, aHeight,
    6020           0 :                             aRepaint ? nsIBaseWindow::eRepaint : 0);
    6021             : }
    6022             : 
    6023             : NS_IMETHODIMP
    6024           1 : nsDocShell::GetSize(int32_t* aWidth, int32_t* aHeight)
    6025             : {
    6026           1 :   return GetPositionAndSize(nullptr, nullptr, aWidth, aHeight);
    6027             : }
    6028             : 
    6029             : NS_IMETHODIMP
    6030           9 : nsDocShell::SetPositionAndSize(int32_t aX, int32_t aY, int32_t aWidth,
    6031             :                                int32_t aHeight, uint32_t aFlags)
    6032             : {
    6033           9 :   mBounds.x = aX;
    6034           9 :   mBounds.y = aY;
    6035           9 :   mBounds.width = aWidth;
    6036           9 :   mBounds.height = aHeight;
    6037             : 
    6038             :   // Hold strong ref, since SetBounds can make us null out mContentViewer
    6039          18 :   nsCOMPtr<nsIContentViewer> viewer = mContentViewer;
    6040           9 :   if (viewer) {
    6041           6 :     uint32_t cvflags = (aFlags & nsIBaseWindow::eDelayResize) ?
    6042           6 :                            nsIContentViewer::eDelayResize : 0;
    6043             :     // XXX Border figured in here or is that handled elsewhere?
    6044           6 :     nsresult rv = viewer->SetBoundsWithFlags(mBounds, cvflags);
    6045           6 :     NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
    6046             :   }
    6047             : 
    6048           9 :   return NS_OK;
    6049             : }
    6050             : 
    6051             : NS_IMETHODIMP
    6052           1 : nsDocShell::GetPositionAndSize(int32_t* aX, int32_t* aY, int32_t* aWidth,
    6053             :                                int32_t* aHeight)
    6054             : {
    6055           1 :   if (mParentWidget) {
    6056             :     // ensure size is up-to-date if window has changed resolution
    6057           1 :     LayoutDeviceIntRect r = mParentWidget->GetClientBounds();
    6058           1 :     SetPositionAndSize(mBounds.x, mBounds.y, r.width, r.height, 0);
    6059             :   }
    6060             : 
    6061             :   // We should really consider just getting this information from
    6062             :   // our window instead of duplicating the storage and code...
    6063           1 :   if (aWidth || aHeight) {
    6064             :     // Caller wants to know our size; make sure to give them up to
    6065             :     // date information.
    6066           2 :     nsCOMPtr<nsIDocument> doc(do_GetInterface(GetAsSupports(mParent)));
    6067           1 :     if (doc) {
    6068           0 :       doc->FlushPendingNotifications(FlushType::Layout);
    6069             :     }
    6070             :   }
    6071             : 
    6072           1 :   DoGetPositionAndSize(aX, aY, aWidth, aHeight);
    6073           1 :   return NS_OK;
    6074             : }
    6075             : 
    6076             : void
    6077           9 : nsDocShell::DoGetPositionAndSize(int32_t* aX, int32_t* aY, int32_t* aWidth,
    6078             :                                  int32_t* aHeight)
    6079             : {
    6080           9 :   if (aX) {
    6081           8 :     *aX = mBounds.x;
    6082             :   }
    6083           9 :   if (aY) {
    6084           8 :     *aY = mBounds.y;
    6085             :   }
    6086           9 :   if (aWidth) {
    6087           9 :     *aWidth = mBounds.width;
    6088             :   }
    6089           9 :   if (aHeight) {
    6090           9 :     *aHeight = mBounds.height;
    6091             :   }
    6092           9 : }
    6093             : 
    6094             : NS_IMETHODIMP
    6095           0 : nsDocShell::Repaint(bool aForce)
    6096             : {
    6097           0 :   nsCOMPtr<nsIPresShell> presShell = GetPresShell();
    6098           0 :   NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE);
    6099             : 
    6100           0 :   nsViewManager* viewManager = presShell->GetViewManager();
    6101           0 :   NS_ENSURE_TRUE(viewManager, NS_ERROR_FAILURE);
    6102             : 
    6103           0 :   viewManager->InvalidateAllViews();
    6104           0 :   return NS_OK;
    6105             : }
    6106             : 
    6107             : NS_IMETHODIMP
    6108          59 : nsDocShell::GetParentWidget(nsIWidget** aParentWidget)
    6109             : {
    6110          59 :   NS_ENSURE_ARG_POINTER(aParentWidget);
    6111             : 
    6112          59 :   *aParentWidget = mParentWidget;
    6113          59 :   NS_IF_ADDREF(*aParentWidget);
    6114             : 
    6115          59 :   return NS_OK;
    6116             : }
    6117             : 
    6118             : NS_IMETHODIMP
    6119           5 : nsDocShell::SetParentWidget(nsIWidget* aParentWidget)
    6120             : {
    6121           5 :   mParentWidget = aParentWidget;
    6122             : 
    6123           5 :   return NS_OK;
    6124             : }
    6125             : 
    6126             : NS_IMETHODIMP
    6127           0 : nsDocShell::GetParentNativeWindow(nativeWindow* aParentNativeWindow)
    6128             : {
    6129           0 :   NS_ENSURE_ARG_POINTER(aParentNativeWindow);
    6130             : 
    6131           0 :   if (mParentWidget) {
    6132           0 :     *aParentNativeWindow = mParentWidget->GetNativeData(NS_NATIVE_WIDGET);
    6133             :   } else {
    6134           0 :     *aParentNativeWindow = nullptr;
    6135             :   }
    6136             : 
    6137           0 :   return NS_OK;
    6138             : }
    6139             : 
    6140             : NS_IMETHODIMP
    6141           0 : nsDocShell::SetParentNativeWindow(nativeWindow aParentNativeWindow)
    6142             : {
    6143           0 :   return NS_ERROR_NOT_IMPLEMENTED;
    6144             : }
    6145             : 
    6146             : NS_IMETHODIMP
    6147           0 : nsDocShell::GetNativeHandle(nsAString& aNativeHandle)
    6148             : {
    6149             :   // the nativeHandle should be accessed from nsIXULWindow
    6150           0 :   return NS_ERROR_NOT_IMPLEMENTED;
    6151             : }
    6152             : 
    6153             : NS_IMETHODIMP
    6154           7 : nsDocShell::GetVisibility(bool* aVisibility)
    6155             : {
    6156           7 :   NS_ENSURE_ARG_POINTER(aVisibility);
    6157             : 
    6158           7 :   *aVisibility = false;
    6159             : 
    6160           7 :   if (!mContentViewer) {
    6161           0 :     return NS_OK;
    6162             :   }
    6163             : 
    6164          14 :   nsCOMPtr<nsIPresShell> presShell = GetPresShell();
    6165           7 :   if (!presShell) {
    6166           0 :     return NS_OK;
    6167             :   }
    6168             : 
    6169             :   // get the view manager
    6170           7 :   nsViewManager* vm = presShell->GetViewManager();
    6171           7 :   NS_ENSURE_TRUE(vm, NS_ERROR_FAILURE);
    6172             : 
    6173             :   // get the root view
    6174           7 :   nsView* view = vm->GetRootView(); // views are not ref counted
    6175           7 :   NS_ENSURE_TRUE(view, NS_ERROR_FAILURE);
    6176             : 
    6177             :   // if our root view is hidden, we are not visible
    6178           7 :   if (view->GetVisibility() == nsViewVisibility_kHide) {
    6179           0 :     return NS_OK;
    6180             :   }
    6181             : 
    6182             :   // otherwise, we must walk up the document and view trees checking
    6183             :   // for a hidden view, unless we're an off screen browser, which
    6184             :   // would make this test meaningless.
    6185             : 
    6186          14 :   RefPtr<nsDocShell> docShell = this;
    6187          14 :   RefPtr<nsDocShell> parentItem = docShell->GetParentDocshell();
    6188           7 :   while (parentItem) {
    6189           0 :     presShell = docShell->GetPresShell();
    6190             : 
    6191           0 :     nsCOMPtr<nsIPresShell> pPresShell = parentItem->GetPresShell();
    6192             : 
    6193             :     // Null-check for crash in bug 267804
    6194           0 :     if (!pPresShell) {
    6195           0 :       NS_NOTREACHED("parent docshell has null pres shell");
    6196           0 :       return NS_OK;
    6197             :     }
    6198             : 
    6199           0 :     vm = presShell->GetViewManager();
    6200           0 :     if (vm) {
    6201           0 :       view = vm->GetRootView();
    6202             :     }
    6203             : 
    6204           0 :     if (view) {
    6205           0 :       view = view->GetParent(); // anonymous inner view
    6206           0 :       if (view) {
    6207           0 :         view = view->GetParent(); // subdocumentframe's view
    6208             :       }
    6209             :     }
    6210             : 
    6211           0 :     nsIFrame* frame = view ? view->GetFrame() : nullptr;
    6212           0 :     bool isDocShellOffScreen = false;
    6213           0 :     docShell->GetIsOffScreenBrowser(&isDocShellOffScreen);
    6214           0 :     if (frame &&
    6215           0 :         !frame->IsVisibleConsideringAncestors(
    6216           0 :           nsIFrame::VISIBILITY_CROSS_CHROME_CONTENT_BOUNDARY) &&
    6217           0 :         !isDocShellOffScreen) {
    6218           0 :       return NS_OK;
    6219             :     }
    6220             : 
    6221           0 :     docShell = parentItem;
    6222           0 :     parentItem = docShell->GetParentDocshell();
    6223             :   }
    6224             : 
    6225          14 :   nsCOMPtr<nsIBaseWindow> treeOwnerAsWin(do_QueryInterface(mTreeOwner));
    6226           7 :   if (!treeOwnerAsWin) {
    6227           0 :     *aVisibility = true;
    6228           0 :     return NS_OK;
    6229             :   }
    6230             : 
    6231             :   // Check with the tree owner as well to give embedders a chance to
    6232             :   // expose visibility as well.
    6233           7 :   return treeOwnerAsWin->GetVisibility(aVisibility);
    6234             : }
    6235             : 
    6236             : NS_IMETHODIMP
    6237           0 : nsDocShell::SetIsOffScreenBrowser(bool aIsOffScreen)
    6238             : {
    6239           0 :   mIsOffScreenBrowser = aIsOffScreen;
    6240           0 :   return NS_OK;
    6241             : }
    6242             : 
    6243             : NS_IMETHODIMP
    6244           0 : nsDocShell::GetIsOffScreenBrowser(bool* aIsOffScreen)
    6245             : {
    6246           0 :   *aIsOffScreen = mIsOffScreenBrowser;
    6247           0 :   return NS_OK;
    6248             : }
    6249             : 
    6250             : NS_IMETHODIMP
    6251           4 : nsDocShell::SetIsActive(bool aIsActive)
    6252             : {
    6253             :   // We disallow setting active on chrome docshells.
    6254           4 :   if (mItemType == nsIDocShellTreeItem::typeChrome) {
    6255           2 :     return NS_ERROR_INVALID_ARG;
    6256             :   }
    6257             : 
    6258             :   // Keep track ourselves.
    6259           2 :   mIsActive = aIsActive;
    6260             : 
    6261             :   // Clear prerender flag if necessary.
    6262           2 :   if (mIsPrerendered && aIsActive) {
    6263           0 :     MOZ_ASSERT(mPrerenderGlobalHistory.get());
    6264           0 :     mIsPrerendered = false;
    6265           0 :     nsCOMPtr<IHistory> history = services::GetHistoryService();
    6266           0 :     nsresult rv = NS_OK;
    6267           0 :     if (history) {
    6268           0 :       rv = mPrerenderGlobalHistory->ApplyChanges(history);
    6269           0 :     } else if (mGlobalHistory) {
    6270           0 :       rv = mPrerenderGlobalHistory->ApplyChanges(mGlobalHistory);
    6271             :     }
    6272           0 :     mPrerenderGlobalHistory = nullptr;
    6273           0 :     NS_ENSURE_SUCCESS(rv, rv);
    6274             :   }
    6275             : 
    6276             :   // Tell the PresShell about it.
    6277           4 :   nsCOMPtr<nsIPresShell> pshell = GetPresShell();
    6278           2 :   if (pshell) {
    6279           0 :     pshell->SetIsActive(aIsActive);
    6280             :   }
    6281             : 
    6282             :   // Tell the window about it
    6283           2 :   if (mScriptGlobal) {
    6284           0 :     mScriptGlobal->SetIsBackground(!aIsActive);
    6285           0 :     if (nsCOMPtr<nsIDocument> doc = mScriptGlobal->GetExtantDoc()) {
    6286             :       // Update orientation when the top-level browsing context becomes active.
    6287           0 :       if (aIsActive) {
    6288           0 :         nsCOMPtr<nsIDocShellTreeItem> parent;
    6289           0 :         GetSameTypeParent(getter_AddRefs(parent));
    6290           0 :         if (!parent) {
    6291             :           // We only care about the top-level browsing context.
    6292           0 :           uint16_t orientation = OrientationLock();
    6293           0 :           ScreenOrientation::UpdateActiveOrientationLock(orientation);
    6294             :         }
    6295             :       }
    6296             : 
    6297           0 :       doc->PostVisibilityUpdateEvent();
    6298             :     }
    6299             :   }
    6300             : 
    6301             :   // Tell the nsDOMNavigationTiming about it
    6302           4 :   RefPtr<nsDOMNavigationTiming> timing = mTiming;
    6303           2 :   if (!timing && mContentViewer) {
    6304           0 :     nsIDocument* doc = mContentViewer->GetDocument();
    6305           0 :     if (doc) {
    6306           0 :       timing = doc->GetNavigationTiming();
    6307             :     }
    6308             :   }
    6309           2 :   if (timing) {
    6310           0 :     timing->NotifyDocShellStateChanged(
    6311             :       aIsActive ? nsDOMNavigationTiming::DocShellState::eActive
    6312           0 :                 : nsDOMNavigationTiming::DocShellState::eInactive);
    6313             :   }
    6314             : 
    6315             :   // Recursively tell all of our children, but don't tell <iframe mozbrowser>
    6316             :   // children; they handle their state separately.
    6317           4 :   nsTObserverArray<nsDocLoader*>::ForwardIterator iter(mChildList);
    6318           2 :   while (iter.HasMore()) {
    6319           0 :     nsCOMPtr<nsIDocShell> docshell = do_QueryObject(iter.GetNext());
    6320           0 :     if (!docshell) {
    6321           0 :       continue;
    6322             :     }
    6323             : 
    6324           0 :     if (!docshell->GetIsMozBrowser()) {
    6325           0 :       docshell->SetIsActive(aIsActive);
    6326             :     }
    6327             :   }
    6328             : 
    6329             :   // Restart or stop meta refresh timers if necessary
    6330           2 :   if (mDisableMetaRefreshWhenInactive) {
    6331           0 :     if (mIsActive) {
    6332           0 :       ResumeRefreshURIs();
    6333             :     } else {
    6334           0 :       SuspendRefreshURIs();
    6335             :     }
    6336             :   }
    6337             : 
    6338           2 :   return NS_OK;
    6339             : }
    6340             : 
    6341             : NS_IMETHODIMP
    6342          16 : nsDocShell::GetIsActive(bool* aIsActive)
    6343             : {
    6344          16 :   *aIsActive = mIsActive;
    6345          16 :   return NS_OK;
    6346             : }
    6347             : 
    6348             : NS_IMETHODIMP
    6349           0 : nsDocShell::SetIsPrerendered()
    6350             : {
    6351           0 :   MOZ_ASSERT(!mIsPrerendered,
    6352             :              "SetIsPrerendered() called on already prerendered docshell");
    6353           0 :   SetIsActive(false);
    6354           0 :   mIsPrerendered = true;
    6355           0 :   mPrerenderGlobalHistory = mozilla::MakeUnique<PendingGlobalHistoryEntry>();
    6356           0 :   return NS_OK;
    6357             : }
    6358             : 
    6359             : NS_IMETHODIMP
    6360          15 : nsDocShell::GetIsPrerendered(bool* aIsPrerendered)
    6361             : {
    6362          15 :   *aIsPrerendered = mIsPrerendered;
    6363          15 :   return NS_OK;
    6364             : }
    6365             : 
    6366             : NS_IMETHODIMP
    6367           1 : nsDocShell::SetIsAppTab(bool aIsAppTab)
    6368             : {
    6369           1 :   mIsAppTab = aIsAppTab;
    6370           1 :   return NS_OK;
    6371             : }
    6372             : 
    6373             : NS_IMETHODIMP
    6374           0 : nsDocShell::GetIsAppTab(bool* aIsAppTab)
    6375             : {
    6376           0 :   *aIsAppTab = mIsAppTab;
    6377           0 :   return NS_OK;
    6378             : }
    6379             : 
    6380             : NS_IMETHODIMP
    6381           2 : nsDocShell::SetSandboxFlags(uint32_t aSandboxFlags)
    6382             : {
    6383           2 :   mSandboxFlags = aSandboxFlags;
    6384           2 :   return NS_OK;
    6385             : }
    6386             : 
    6387             : NS_IMETHODIMP
    6388           3 : nsDocShell::GetSandboxFlags(uint32_t* aSandboxFlags)
    6389             : {
    6390           3 :   *aSandboxFlags = mSandboxFlags;
    6391           3 :   return NS_OK;
    6392             : }
    6393             : 
    6394             : NS_IMETHODIMP
    6395           0 : nsDocShell::SetOnePermittedSandboxedNavigator(nsIDocShell* aSandboxedNavigator)
    6396             : {
    6397           0 :   if (mOnePermittedSandboxedNavigator) {
    6398           0 :     NS_ERROR("One Permitted Sandboxed Navigator should only be set once.");
    6399           0 :     return NS_OK;
    6400             :   }
    6401             : 
    6402           0 :   mOnePermittedSandboxedNavigator = do_GetWeakReference(aSandboxedNavigator);
    6403           0 :   NS_ASSERTION(mOnePermittedSandboxedNavigator,
    6404             :                "One Permitted Sandboxed Navigator must support weak references.");
    6405             : 
    6406           0 :   return NS_OK;
    6407             : }
    6408             : 
    6409             : NS_IMETHODIMP
    6410           0 : nsDocShell::GetOnePermittedSandboxedNavigator(nsIDocShell** aSandboxedNavigator)
    6411             : {
    6412           0 :   NS_ENSURE_ARG_POINTER(aSandboxedNavigator);
    6413             :   nsCOMPtr<nsIDocShell> permittedNavigator =
    6414           0 :     do_QueryReferent(mOnePermittedSandboxedNavigator);
    6415           0 :   permittedNavigator.forget(aSandboxedNavigator);
    6416           0 :   return NS_OK;
    6417             : }
    6418             : 
    6419             : NS_IMETHODIMP
    6420           2 : nsDocShell::SetDefaultLoadFlags(uint32_t aDefaultLoadFlags)
    6421             : {
    6422           2 :   mDefaultLoadFlags = aDefaultLoadFlags;
    6423             : 
    6424             :   // Tell the load group to set these flags all requests in the group
    6425           2 :   if (mLoadGroup) {
    6426           2 :     mLoadGroup->SetDefaultLoadFlags(aDefaultLoadFlags);
    6427             :   } else {
    6428           0 :     NS_WARNING("nsDocShell::SetDefaultLoadFlags has no loadGroup to propagate the flags to");
    6429             :   }
    6430             : 
    6431             :   // Recursively tell all of our children.  We *do not* skip
    6432             :   // <iframe mozbrowser> children - if someone sticks custom flags in this
    6433             :   // docShell then they too get the same flags.
    6434           4 :   nsTObserverArray<nsDocLoader*>::ForwardIterator iter(mChildList);
    6435           2 :   while (iter.HasMore()) {
    6436           0 :     nsCOMPtr<nsIDocShell> docshell = do_QueryObject(iter.GetNext());
    6437           0 :     if (!docshell) {
    6438           0 :       continue;
    6439             :     }
    6440           0 :     docshell->SetDefaultLoadFlags(aDefaultLoadFlags);
    6441             :   }
    6442           4 :   return NS_OK;
    6443             : }
    6444             : 
    6445             : NS_IMETHODIMP
    6446           2 : nsDocShell::GetDefaultLoadFlags(uint32_t* aDefaultLoadFlags)
    6447             : {
    6448           2 :   *aDefaultLoadFlags = mDefaultLoadFlags;
    6449           2 :   return NS_OK;
    6450             : }
    6451             : 
    6452             : NS_IMETHODIMP
    6453           0 : nsDocShell::SetMixedContentChannel(nsIChannel* aMixedContentChannel)
    6454             : {
    6455             : #ifdef DEBUG
    6456             :   // if the channel is non-null
    6457           0 :   if (aMixedContentChannel) {
    6458             :     // Get the root docshell.
    6459           0 :     nsCOMPtr<nsIDocShellTreeItem> root;
    6460           0 :     GetSameTypeRootTreeItem(getter_AddRefs(root));
    6461           0 :     NS_WARNING_ASSERTION(root.get() == static_cast<nsIDocShellTreeItem*>(this),
    6462             :                          "Setting mMixedContentChannel on a docshell that is "
    6463             :                          "not the root docshell");
    6464             :   }
    6465             : #endif
    6466           0 :   mMixedContentChannel = aMixedContentChannel;
    6467           0 :   return NS_OK;
    6468             : }
    6469             : 
    6470             : NS_IMETHODIMP
    6471           0 : nsDocShell::GetFailedChannel(nsIChannel** aFailedChannel)
    6472             : {
    6473           0 :   NS_ENSURE_ARG_POINTER(aFailedChannel);
    6474           0 :   nsIDocument* doc = GetDocument();
    6475           0 :   if (!doc) {
    6476           0 :     *aFailedChannel = nullptr;
    6477           0 :     return NS_OK;
    6478             :   }
    6479           0 :   NS_IF_ADDREF(*aFailedChannel = doc->GetFailedChannel());
    6480           0 :   return NS_OK;
    6481             : }
    6482             : 
    6483             : NS_IMETHODIMP
    6484           0 : nsDocShell::GetMixedContentChannel(nsIChannel** aMixedContentChannel)
    6485             : {
    6486           0 :   NS_ENSURE_ARG_POINTER(aMixedContentChannel);
    6487           0 :   NS_IF_ADDREF(*aMixedContentChannel = mMixedContentChannel);
    6488           0 :   return NS_OK;
    6489             : }
    6490             : 
    6491             : NS_IMETHODIMP
    6492           0 : nsDocShell::GetAllowMixedContentAndConnectionData(bool* aRootHasSecureConnection,
    6493             :                                                   bool* aAllowMixedContent,
    6494             :                                                   bool* aIsRootDocShell)
    6495             : {
    6496           0 :   *aRootHasSecureConnection = true;
    6497           0 :   *aAllowMixedContent = false;
    6498           0 :   *aIsRootDocShell = false;
    6499             : 
    6500           0 :   nsCOMPtr<nsIDocShellTreeItem> sameTypeRoot;
    6501           0 :   GetSameTypeRootTreeItem(getter_AddRefs(sameTypeRoot));
    6502           0 :   NS_ASSERTION(sameTypeRoot,
    6503             :                "No document shell root tree item from document shell tree item!");
    6504           0 :   *aIsRootDocShell =
    6505           0 :     sameTypeRoot.get() == static_cast<nsIDocShellTreeItem*>(this);
    6506             : 
    6507             :   // now get the document from sameTypeRoot
    6508           0 :   nsCOMPtr<nsIDocument> rootDoc = sameTypeRoot->GetDocument();
    6509           0 :   if (rootDoc) {
    6510           0 :     nsCOMPtr<nsIPrincipal> rootPrincipal = rootDoc->NodePrincipal();
    6511             : 
    6512             :     // For things with system principal (e.g. scratchpad) there is no uri
    6513             :     // aRootHasSecureConnection should be false.
    6514           0 :     nsCOMPtr<nsIURI> rootUri;
    6515           0 :     if (nsContentUtils::IsSystemPrincipal(rootPrincipal) ||
    6516           0 :         NS_FAILED(rootPrincipal->GetURI(getter_AddRefs(rootUri))) || !rootUri ||
    6517           0 :         NS_FAILED(rootUri->SchemeIs("https", aRootHasSecureConnection))) {
    6518           0 :       *aRootHasSecureConnection = false;
    6519             :     }
    6520             : 
    6521             :     // Check the root doc's channel against the root docShell's
    6522             :     // mMixedContentChannel to see if they are the same. If they are the same,
    6523             :     // the user has overriden the block.
    6524           0 :     nsCOMPtr<nsIDocShell> rootDocShell = do_QueryInterface(sameTypeRoot);
    6525           0 :     nsCOMPtr<nsIChannel> mixedChannel;
    6526           0 :     rootDocShell->GetMixedContentChannel(getter_AddRefs(mixedChannel));
    6527           0 :     *aAllowMixedContent =
    6528           0 :       mixedChannel && (mixedChannel == rootDoc->GetChannel());
    6529             :   }
    6530             : 
    6531           0 :   return NS_OK;
    6532             : }
    6533             : 
    6534             : NS_IMETHODIMP
    6535           3 : nsDocShell::SetVisibility(bool aVisibility)
    6536             : {
    6537             :   // Show()/Hide() may change mContentViewer.
    6538           6 :   nsCOMPtr<nsIContentViewer> cv = mContentViewer;
    6539           3 :   if (!cv) {
    6540           0 :     return NS_OK;
    6541             :   }
    6542           3 :   if (aVisibility) {
    6543           2 :     cv->Show();
    6544             :   } else {
    6545           1 :     cv->Hide();
    6546             :   }
    6547             : 
    6548           3 :   return NS_OK;
    6549             : }
    6550             : 
    6551             : NS_IMETHODIMP
    6552           0 : nsDocShell::GetEnabled(bool* aEnabled)
    6553             : {
    6554           0 :   NS_ENSURE_ARG_POINTER(aEnabled);
    6555           0 :   *aEnabled = true;
    6556           0 :   return NS_ERROR_NOT_IMPLEMENTED;
    6557             : }
    6558             : 
    6559             : NS_IMETHODIMP
    6560           0 : nsDocShell::SetEnabled(bool aEnabled)
    6561             : {
    6562           0 :   return NS_ERROR_NOT_IMPLEMENTED;
    6563             : }
    6564             : 
    6565             : NS_IMETHODIMP
    6566           0 : nsDocShell::SetFocus()
    6567             : {
    6568           0 :   return NS_OK;
    6569             : }
    6570             : 
    6571             : NS_IMETHODIMP
    6572          59 : nsDocShell::GetMainWidget(nsIWidget** aMainWidget)
    6573             : {
    6574             :   // We don't create our own widget, so simply return the parent one.
    6575          59 :   return GetParentWidget(aMainWidget);
    6576             : }
    6577             : 
    6578             : NS_IMETHODIMP
    6579           0 : nsDocShell::GetTitle(char16_t** aTitle)
    6580             : {
    6581           0 :   NS_ENSURE_ARG_POINTER(aTitle);
    6582             : 
    6583           0 :   *aTitle = ToNewUnicode(mTitle);
    6584           0 :   return NS_OK;
    6585             : }
    6586             : 
    6587             : NS_IMETHODIMP
    6588           3 : nsDocShell::SetTitle(const char16_t* aTitle)
    6589             : {
    6590             :   // Store local title
    6591           3 :   mTitle = aTitle;
    6592             : 
    6593           6 :   nsCOMPtr<nsIDocShellTreeItem> parent;
    6594           3 :   GetSameTypeParent(getter_AddRefs(parent));
    6595             : 
    6596             :   // When title is set on the top object it should then be passed to the
    6597             :   // tree owner.
    6598           3 :   if (!parent) {
    6599           6 :     nsCOMPtr<nsIBaseWindow> treeOwnerAsWin(do_QueryInterface(mTreeOwner));
    6600           3 :     if (treeOwnerAsWin) {
    6601           3 :       treeOwnerAsWin->SetTitle(aTitle);
    6602             :     }
    6603             :   }
    6604             : 
    6605           3 :   AssertOriginAttributesMatchPrivateBrowsing();
    6606           3 :   if (mCurrentURI && mLoadType != LOAD_ERROR_PAGE) {
    6607           3 :     UpdateGlobalHistoryTitle(mCurrentURI);
    6608             :   }
    6609             : 
    6610             :   // Update SessionHistory with the document's title.
    6611           4 :   if (mOSHE && mLoadType != LOAD_BYPASS_HISTORY &&
    6612           1 :       mLoadType != LOAD_ERROR_PAGE) {
    6613           1 :     mOSHE->SetTitle(mTitle);
    6614             :   }
    6615             : 
    6616           6 :   return NS_OK;
    6617             : }
    6618             : 
    6619             : nsresult
    6620           0 : nsDocShell::GetCurScrollPos(int32_t aScrollOrientation, int32_t* aCurPos)
    6621             : {
    6622           0 :   NS_ENSURE_ARG_POINTER(aCurPos);
    6623             : 
    6624           0 :   nsIScrollableFrame* sf = GetRootScrollFrame();
    6625           0 :   if (!sf) {
    6626           0 :     return NS_ERROR_FAILURE;
    6627             :   }
    6628             : 
    6629           0 :   nsPoint pt = sf->GetScrollPosition();
    6630             : 
    6631           0 :   switch (aScrollOrientation) {
    6632             :     case ScrollOrientation_X:
    6633           0 :       *aCurPos = pt.x;
    6634           0 :       return NS_OK;
    6635             : 
    6636             :     case ScrollOrientation_Y:
    6637           0 :       *aCurPos = pt.y;
    6638           0 :       return NS_OK;
    6639             : 
    6640             :     default:
    6641           0 :       NS_ENSURE_TRUE(false, NS_ERROR_INVALID_ARG);
    6642             :   }
    6643             : }
    6644             : 
    6645             : nsresult
    6646           0 : nsDocShell::SetCurScrollPosEx(int32_t aCurHorizontalPos,
    6647             :                               int32_t aCurVerticalPos)
    6648             : {
    6649           0 :   nsIScrollableFrame* sf = GetRootScrollFrame();
    6650           0 :   NS_ENSURE_TRUE(sf, NS_ERROR_FAILURE);
    6651             : 
    6652           0 :   sf->ScrollTo(nsPoint(aCurHorizontalPos, aCurVerticalPos),
    6653           0 :                nsIScrollableFrame::INSTANT);
    6654           0 :   return NS_OK;
    6655             : }
    6656             : 
    6657             : //*****************************************************************************
    6658             : // nsDocShell::nsIScrollable
    6659             : //*****************************************************************************
    6660             : 
    6661             : NS_IMETHODIMP
    6662          98 : nsDocShell::GetDefaultScrollbarPreferences(int32_t aScrollOrientation,
    6663             :                                            int32_t* aScrollbarPref)
    6664             : {
    6665          98 :   NS_ENSURE_ARG_POINTER(aScrollbarPref);
    6666          98 :   switch (aScrollOrientation) {
    6667             :     case ScrollOrientation_X:
    6668          49 :       *aScrollbarPref = mDefaultScrollbarPref.x;
    6669          49 :       return NS_OK;
    6670             : 
    6671             :     case ScrollOrientation_Y:
    6672          49 :       *aScrollbarPref = mDefaultScrollbarPref.y;
    6673          49 :       return NS_OK;
    6674             : 
    6675             :     default:
    6676           0 :       NS_ENSURE_TRUE(false, NS_ERROR_INVALID_ARG);
    6677             :   }
    6678             :   return NS_ERROR_FAILURE;
    6679             : }
    6680             : 
    6681             : NS_IMETHODIMP
    6682           4 : nsDocShell::SetDefaultScrollbarPreferences(int32_t aScrollOrientation,
    6683             :                                            int32_t aScrollbarPref)
    6684             : {
    6685           4 :   switch (aScrollOrientation) {
    6686             :     case ScrollOrientation_X:
    6687           2 :       mDefaultScrollbarPref.x = aScrollbarPref;
    6688           2 :       return NS_OK;
    6689             : 
    6690             :     case ScrollOrientation_Y:
    6691           2 :       mDefaultScrollbarPref.y = aScrollbarPref;
    6692           2 :       return NS_OK;
    6693             : 
    6694             :     default:
    6695           0 :       NS_ENSURE_TRUE(false, NS_ERROR_INVALID_ARG);
    6696             :   }
    6697             :   return NS_ERROR_FAILURE;
    6698             : }
    6699             : 
    6700             : NS_IMETHODIMP
    6701           0 : nsDocShell::GetScrollbarVisibility(bool* aVerticalVisible,
    6702             :                                    bool* aHorizontalVisible)
    6703             : {
    6704           0 :   nsIScrollableFrame* sf = GetRootScrollFrame();
    6705           0 :   NS_ENSURE_TRUE(sf, NS_ERROR_FAILURE);
    6706             : 
    6707           0 :   uint32_t scrollbarVisibility = sf->GetScrollbarVisibility();
    6708           0 :   if (aVerticalVisible) {
    6709           0 :     *aVerticalVisible =
    6710           0 :       (scrollbarVisibility & nsIScrollableFrame::VERTICAL) != 0;
    6711             :   }
    6712           0 :   if (aHorizontalVisible) {
    6713           0 :     *aHorizontalVisible =
    6714           0 :       (scrollbarVisibility & nsIScrollableFrame::HORIZONTAL) != 0;
    6715             :   }
    6716             : 
    6717           0 :   return NS_OK;
    6718             : }
    6719             : 
    6720             : //*****************************************************************************
    6721             : // nsDocShell::nsITextScroll
    6722             : //*****************************************************************************
    6723             : 
    6724             : NS_IMETHODIMP
    6725           0 : nsDocShell::ScrollByLines(int32_t aNumLines)
    6726             : {
    6727           0 :   nsIScrollableFrame* sf = GetRootScrollFrame();
    6728           0 :   NS_ENSURE_TRUE(sf, NS_ERROR_FAILURE);
    6729             : 
    6730           0 :   sf->ScrollBy(nsIntPoint(0, aNumLines), nsIScrollableFrame::LINES,
    6731           0 :                nsIScrollableFrame::SMOOTH);
    6732           0 :   return NS_OK;
    6733             : }
    6734             : 
    6735             : NS_IMETHODIMP
    6736           0 : nsDocShell::ScrollByPages(int32_t aNumPages)
    6737             : {
    6738           0 :   nsIScrollableFrame* sf = GetRootScrollFrame();
    6739           0 :   NS_ENSURE_TRUE(sf, NS_ERROR_FAILURE);
    6740             : 
    6741           0 :   sf->ScrollBy(nsIntPoint(0, aNumPages), nsIScrollableFrame::PAGES,
    6742           0 :                nsIScrollableFrame::SMOOTH);
    6743           0 :   return NS_OK;
    6744             : }
    6745             : 
    6746             : //*****************************************************************************
    6747             : // nsDocShell::nsIRefreshURI
    6748             : //*****************************************************************************
    6749             : 
    6750             : NS_IMETHODIMP
    6751           0 : nsDocShell::RefreshURI(nsIURI* aURI, int32_t aDelay, bool aRepeat,
    6752             :                        bool aMetaRefresh)
    6753             : {
    6754           0 :   NS_ENSURE_ARG(aURI);
    6755             : 
    6756             :   /* Check if Meta refresh/redirects are permitted. Some
    6757             :    * embedded applications may not want to do this.
    6758             :    * Must do this before sending out NOTIFY_REFRESH events
    6759             :    * because listeners may have side effects (e.g. displaying a
    6760             :    * button to manually trigger the refresh later).
    6761             :    */
    6762           0 :   bool allowRedirects = true;
    6763           0 :   GetAllowMetaRedirects(&allowRedirects);
    6764           0 :   if (!allowRedirects) {
    6765           0 :     return NS_OK;
    6766             :   }
    6767             : 
    6768             :   // If any web progress listeners are listening for NOTIFY_REFRESH events,
    6769             :   // give them a chance to block this refresh.
    6770             :   bool sameURI;
    6771           0 :   nsresult rv = aURI->Equals(mCurrentURI, &sameURI);
    6772           0 :   if (NS_FAILED(rv)) {
    6773           0 :     sameURI = false;
    6774             :   }
    6775           0 :   if (!RefreshAttempted(this, aURI, aDelay, sameURI)) {
    6776           0 :     return NS_OK;
    6777             :   }
    6778             : 
    6779           0 :   nsRefreshTimer* refreshTimer = new nsRefreshTimer();
    6780           0 :   uint32_t busyFlags = 0;
    6781           0 :   GetBusyFlags(&busyFlags);
    6782             : 
    6783           0 :   nsCOMPtr<nsISupports> dataRef = refreshTimer;  // Get the ref count to 1
    6784             : 
    6785           0 :   refreshTimer->mDocShell = this;
    6786           0 :   refreshTimer->mURI = aURI;
    6787           0 :   refreshTimer->mDelay = aDelay;
    6788           0 :   refreshTimer->mRepeat = aRepeat;
    6789           0 :   refreshTimer->mMetaRefresh = aMetaRefresh;
    6790             : 
    6791           0 :   if (!mRefreshURIList) {
    6792           0 :     mRefreshURIList = nsArray::Create();
    6793             :   }
    6794             : 
    6795           0 :   if (busyFlags & BUSY_FLAGS_BUSY || (!mIsActive && mDisableMetaRefreshWhenInactive)) {
    6796             :     // We don't  want to create the timer right now. Instead queue up the request
    6797             :     // and trigger the timer in EndPageLoad() or whenever we become active.
    6798           0 :     mRefreshURIList->AppendElement(refreshTimer, /*weak =*/ false);
    6799             :   } else {
    6800             :     // There is no page loading going on right now.  Create the
    6801             :     // timer and fire it right away.
    6802           0 :     nsCOMPtr<nsITimer> timer = do_CreateInstance("@mozilla.org/timer;1");
    6803           0 :     NS_ENSURE_TRUE(timer, NS_ERROR_FAILURE);
    6804           0 :     nsCOMPtr<nsPIDOMWindowOuter> win = GetWindow();
    6805           0 :     NS_ENSURE_TRUE(win, NS_ERROR_FAILURE);
    6806             : 
    6807           0 :     mRefreshURIList->AppendElement(timer, /*weak =*/ false);  // owning timer ref
    6808           0 :     timer->SetTarget(win->TabGroup()->EventTargetFor(TaskCategory::Network));
    6809           0 :     timer->InitWithCallback(refreshTimer, aDelay, nsITimer::TYPE_ONE_SHOT);
    6810             :   }
    6811           0 :   return NS_OK;
    6812             : }
    6813             : 
    6814             : nsresult
    6815           0 : nsDocShell::ForceRefreshURIFromTimer(nsIURI* aURI,
    6816             :                                      int32_t aDelay,
    6817             :                                      bool aMetaRefresh,
    6818             :                                      nsITimer* aTimer)
    6819             : {
    6820           0 :   NS_PRECONDITION(aTimer, "Must have a timer here");
    6821             : 
    6822             :   // Remove aTimer from mRefreshURIList if needed
    6823           0 :   if (mRefreshURIList) {
    6824           0 :     uint32_t n = 0;
    6825           0 :     mRefreshURIList->GetLength(&n);
    6826             : 
    6827           0 :     for (uint32_t i = 0; i < n; ++i) {
    6828           0 :       nsCOMPtr<nsITimer> timer = do_QueryElementAt(mRefreshURIList, i);
    6829           0 :       if (timer == aTimer) {
    6830           0 :         mRefreshURIList->RemoveElementAt(i);
    6831           0 :         break;
    6832             :       }
    6833             :     }
    6834             :   }
    6835             : 
    6836           0 :   return ForceRefreshURI(aURI, aDelay, aMetaRefresh);
    6837             : }
    6838             : 
    6839             : NS_IMETHODIMP
    6840           0 : nsDocShell::ForceRefreshURI(nsIURI* aURI, int32_t aDelay, bool aMetaRefresh)
    6841             : {
    6842           0 :   NS_ENSURE_ARG(aURI);
    6843             : 
    6844           0 :   nsCOMPtr<nsIDocShellLoadInfo> loadInfo;
    6845           0 :   CreateLoadInfo(getter_AddRefs(loadInfo));
    6846           0 :   NS_ENSURE_TRUE(loadInfo, NS_ERROR_OUT_OF_MEMORY);
    6847             : 
    6848             :   /* We do need to pass in a referrer, but we don't want it to
    6849             :    * be sent to the server.
    6850             :    */
    6851           0 :   loadInfo->SetSendReferrer(false);
    6852             : 
    6853             :   /* for most refreshes the current URI is an appropriate
    6854             :    * internal referrer
    6855             :    */
    6856           0 :   loadInfo->SetReferrer(mCurrentURI);
    6857             : 
    6858             :   /* Don't ever "guess" on which principal to use to avoid picking
    6859             :    * the current principal.
    6860             :    */
    6861           0 :   loadInfo->SetPrincipalIsExplicit(true);
    6862             : 
    6863             :   /* Check if this META refresh causes a redirection
    6864             :    * to another site.
    6865             :    */
    6866           0 :   bool equalUri = false;
    6867           0 :   nsresult rv = aURI->Equals(mCurrentURI, &equalUri);
    6868           0 :   if (NS_SUCCEEDED(rv) && (!equalUri) && aMetaRefresh &&
    6869             :       aDelay <= REFRESH_REDIRECT_TIMER) {
    6870             :     /* It is a META refresh based redirection within the threshold time
    6871             :      * we have in mind (15000 ms as defined by REFRESH_REDIRECT_TIMER).
    6872             :      * Pass a REPLACE flag to LoadURI().
    6873             :      */
    6874           0 :     loadInfo->SetLoadType(nsIDocShellLoadInfo::loadNormalReplace);
    6875             : 
    6876             :     /* for redirects we mimic HTTP, which passes the
    6877             :      *  original referrer
    6878             :      */
    6879           0 :     nsCOMPtr<nsIURI> internalReferrer;
    6880           0 :     GetReferringURI(getter_AddRefs(internalReferrer));
    6881           0 :     if (internalReferrer) {
    6882           0 :       loadInfo->SetReferrer(internalReferrer);
    6883             :     }
    6884             :   } else {
    6885           0 :     loadInfo->SetLoadType(nsIDocShellLoadInfo::loadRefresh);
    6886             :   }
    6887             : 
    6888             :   /*
    6889             :    * LoadURI(...) will cancel all refresh timers... This causes the
    6890             :    * Timer and its refreshData instance to be released...
    6891             :    */
    6892           0 :   LoadURI(aURI, loadInfo, nsIWebNavigation::LOAD_FLAGS_NONE, true);
    6893             : 
    6894           0 :   return NS_OK;
    6895             : }
    6896             : 
    6897             : nsresult
    6898           0 : nsDocShell::SetupRefreshURIFromHeader(nsIURI* aBaseURI,
    6899             :                                       nsIPrincipal* aPrincipal,
    6900             :                                       const nsACString& aHeader)
    6901             : {
    6902             :   // Refresh headers are parsed with the following format in mind
    6903             :   // <META HTTP-EQUIV=REFRESH CONTENT="5; URL=http://uri">
    6904             :   // By the time we are here, the following is true:
    6905             :   // header = "REFRESH"
    6906             :   // content = "5; URL=http://uri" // note the URL attribute is
    6907             :   // optional, if it is absent, the currently loaded url is used.
    6908             :   // Also note that the seconds and URL separator can be either
    6909             :   // a ';' or a ','. The ',' separator should be illegal but CNN
    6910             :   // is using it.
    6911             :   //
    6912             :   // We need to handle the following strings, where
    6913             :   //  - X is a set of digits
    6914             :   //  - URI is either a relative or absolute URI
    6915             :   //
    6916             :   // Note that URI should start with "url=" but we allow omission
    6917             :   //
    6918             :   // "" || ";" || ","
    6919             :   //  empty string. use the currently loaded URI
    6920             :   //  and refresh immediately.
    6921             :   // "X" || "X;" || "X,"
    6922             :   //  Refresh the currently loaded URI in X seconds.
    6923             :   // "X; URI" || "X, URI"
    6924             :   //  Refresh using URI as the destination in X seconds.
    6925             :   // "URI" || "; URI" || ", URI"
    6926             :   //  Refresh immediately using URI as the destination.
    6927             :   //
    6928             :   // Currently, anything immediately following the URI, if
    6929             :   // separated by any char in the set "'\"\t\r\n " will be
    6930             :   // ignored. So "10; url=go.html ; foo=bar" will work,
    6931             :   // and so will "10; url='go.html'; foo=bar". However,
    6932             :   // "10; url=go.html; foo=bar" will result in the uri
    6933             :   // "go.html;" since ';' and ',' are valid uri characters.
    6934             :   //
    6935             :   // Note that we need to remove any tokens wrapping the URI.
    6936             :   // These tokens currently include spaces, double and single
    6937             :   // quotes.
    6938             : 
    6939             :   // when done, seconds is 0 or the given number of seconds
    6940             :   //            uriAttrib is empty or the URI specified
    6941           0 :   MOZ_ASSERT(aPrincipal);
    6942             : 
    6943           0 :   nsAutoCString uriAttrib;
    6944           0 :   int32_t seconds = 0;
    6945           0 :   bool specifiesSeconds = false;
    6946             : 
    6947           0 :   nsACString::const_iterator iter, tokenStart, doneIterating;
    6948             : 
    6949           0 :   aHeader.BeginReading(iter);
    6950           0 :   aHeader.EndReading(doneIterating);
    6951             : 
    6952             :   // skip leading whitespace
    6953           0 :   while (iter != doneIterating && nsCRT::IsAsciiSpace(*iter)) {
    6954           0 :     ++iter;
    6955             :   }
    6956             : 
    6957           0 :   tokenStart = iter;
    6958             : 
    6959             :   // skip leading + and -
    6960           0 :   if (iter != doneIterating && (*iter == '-' || *iter == '+')) {
    6961           0 :     ++iter;
    6962             :   }
    6963             : 
    6964             :   // parse number
    6965           0 :   while (iter != doneIterating && (*iter >= '0' && *iter <= '9')) {
    6966           0 :     seconds = seconds * 10 + (*iter - '0');
    6967           0 :     specifiesSeconds = true;
    6968           0 :     ++iter;
    6969             :   }
    6970             : 
    6971           0 :   if (iter != doneIterating) {
    6972             :     // if we started with a '-', number is negative
    6973           0 :     if (*tokenStart == '-') {
    6974           0 :       seconds = -seconds;
    6975             :     }
    6976             : 
    6977             :     // skip to next ';' or ','
    6978           0 :     nsACString::const_iterator iterAfterDigit = iter;
    6979           0 :     while (iter != doneIterating && !(*iter == ';' || *iter == ',')) {
    6980           0 :       if (specifiesSeconds) {
    6981             :         // Non-whitespace characters here mean that the string is
    6982             :         // malformed but tolerate sites that specify a decimal point,
    6983             :         // even though meta refresh only works on whole seconds.
    6984           0 :         if (iter == iterAfterDigit &&
    6985           0 :             !nsCRT::IsAsciiSpace(*iter) && *iter != '.') {
    6986             :           // The characters between the seconds and the next
    6987             :           // section are just garbage!
    6988             :           //   e.g. content="2a0z+,URL=http://www.mozilla.org/"
    6989             :           // Just ignore this redirect.
    6990           0 :           return NS_ERROR_FAILURE;
    6991           0 :         } else if (nsCRT::IsAsciiSpace(*iter)) {
    6992             :           // We've had at least one whitespace so tolerate the mistake
    6993             :           // and drop through.
    6994             :           // e.g. content="10 foo"
    6995           0 :           ++iter;
    6996           0 :           break;
    6997             :         }
    6998             :       }
    6999           0 :       ++iter;
    7000             :     }
    7001             : 
    7002             :     // skip any remaining whitespace
    7003           0 :     while (iter != doneIterating && nsCRT::IsAsciiSpace(*iter)) {
    7004           0 :       ++iter;
    7005             :     }
    7006             : 
    7007             :     // skip ';' or ','
    7008           0 :     if (iter != doneIterating && (*iter == ';' || *iter == ',')) {
    7009           0 :       ++iter;
    7010             :     }
    7011             : 
    7012             :     // skip whitespace
    7013           0 :     while (iter != doneIterating && nsCRT::IsAsciiSpace(*iter)) {
    7014           0 :       ++iter;
    7015             :     }
    7016             :   }
    7017             : 
    7018             :   // possible start of URI
    7019           0 :   tokenStart = iter;
    7020             : 
    7021             :   // skip "url = " to real start of URI
    7022           0 :   if (iter != doneIterating && (*iter == 'u' || *iter == 'U')) {
    7023           0 :     ++iter;
    7024           0 :     if (iter != doneIterating && (*iter == 'r' || *iter == 'R')) {
    7025           0 :       ++iter;
    7026           0 :       if (iter != doneIterating && (*iter == 'l' || *iter == 'L')) {
    7027           0 :         ++iter;
    7028             : 
    7029             :         // skip whitespace
    7030           0 :         while (iter != doneIterating && nsCRT::IsAsciiSpace(*iter)) {
    7031           0 :           ++iter;
    7032             :         }
    7033             : 
    7034           0 :         if (iter != doneIterating && *iter == '=') {
    7035           0 :           ++iter;
    7036             : 
    7037             :           // skip whitespace
    7038           0 :           while (iter != doneIterating && nsCRT::IsAsciiSpace(*iter)) {
    7039           0 :             ++iter;
    7040             :           }
    7041             : 
    7042             :           // found real start of URI
    7043           0 :           tokenStart = iter;
    7044             :         }
    7045             :       }
    7046             :     }
    7047             :   }
    7048             : 
    7049             :   // skip a leading '"' or '\''.
    7050             : 
    7051           0 :   bool isQuotedURI = false;
    7052           0 :   if (tokenStart != doneIterating &&
    7053           0 :       (*tokenStart == '"' || *tokenStart == '\'')) {
    7054           0 :     isQuotedURI = true;
    7055           0 :     ++tokenStart;
    7056             :   }
    7057             : 
    7058             :   // set iter to start of URI
    7059           0 :   iter = tokenStart;
    7060             : 
    7061             :   // tokenStart here points to the beginning of URI
    7062             : 
    7063             :   // grab the rest of the URI
    7064           0 :   while (iter != doneIterating) {
    7065           0 :     if (isQuotedURI && (*iter == '"' || *iter == '\'')) {
    7066           0 :       break;
    7067             :     }
    7068           0 :     ++iter;
    7069             :   }
    7070             : 
    7071             :   // move iter one back if the last character is a '"' or '\''
    7072           0 :   if (iter != tokenStart && isQuotedURI) {
    7073           0 :     --iter;
    7074           0 :     if (!(*iter == '"' || *iter == '\'')) {
    7075           0 :       ++iter;
    7076             :     }
    7077             :   }
    7078             : 
    7079             :   // URI is whatever's contained from tokenStart to iter.
    7080             :   // note: if tokenStart == doneIterating, so is iter.
    7081             : 
    7082           0 :   nsresult rv = NS_OK;
    7083             : 
    7084           0 :   nsCOMPtr<nsIURI> uri;
    7085           0 :   bool specifiesURI = false;
    7086           0 :   if (tokenStart == iter) {
    7087           0 :     uri = aBaseURI;
    7088             :   } else {
    7089           0 :     uriAttrib = Substring(tokenStart, iter);
    7090             :     // NS_NewURI takes care of any whitespace surrounding the URL
    7091           0 :     rv = NS_NewURI(getter_AddRefs(uri), uriAttrib, nullptr, aBaseURI);
    7092           0 :     specifiesURI = true;
    7093             :   }
    7094             : 
    7095             :   // No URI or seconds were specified
    7096           0 :   if (!specifiesSeconds && !specifiesURI) {
    7097             :     // Do nothing because the alternative is to spin around in a refresh
    7098             :     // loop forever!
    7099           0 :     return NS_ERROR_FAILURE;
    7100             :   }
    7101             : 
    7102           0 :   if (NS_SUCCEEDED(rv)) {
    7103             :     nsCOMPtr<nsIScriptSecurityManager> securityManager(
    7104           0 :       do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv));
    7105           0 :     if (NS_SUCCEEDED(rv)) {
    7106           0 :       rv = securityManager->CheckLoadURIWithPrincipal(
    7107             :         aPrincipal, uri,
    7108           0 :         nsIScriptSecurityManager::LOAD_IS_AUTOMATIC_DOCUMENT_REPLACEMENT);
    7109             : 
    7110           0 :       if (NS_SUCCEEDED(rv)) {
    7111           0 :         bool isjs = true;
    7112           0 :         rv = NS_URIChainHasFlags(
    7113             :           uri, nsIProtocolHandler::URI_OPENING_EXECUTES_SCRIPT, &isjs);
    7114           0 :         NS_ENSURE_SUCCESS(rv, rv);
    7115             : 
    7116           0 :         if (isjs) {
    7117           0 :           return NS_ERROR_FAILURE;
    7118             :         }
    7119             :       }
    7120             : 
    7121           0 :       if (NS_SUCCEEDED(rv)) {
    7122             :         // Since we can't travel back in time yet, just pretend
    7123             :         // negative numbers do nothing at all.
    7124           0 :         if (seconds < 0) {
    7125           0 :           return NS_ERROR_FAILURE;
    7126             :         }
    7127             : 
    7128           0 :         rv = RefreshURI(uri, seconds * 1000, false, true);
    7129             :       }
    7130             :     }
    7131             :   }
    7132           0 :   return rv;
    7133             : }
    7134             : 
    7135             : NS_IMETHODIMP
    7136           0 : nsDocShell::SetupRefreshURI(nsIChannel* aChannel)
    7137             : {
    7138             :   nsresult rv;
    7139           0 :   nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aChannel, &rv));
    7140           0 :   if (NS_SUCCEEDED(rv)) {
    7141           0 :     nsAutoCString refreshHeader;
    7142           0 :     rv = httpChannel->GetResponseHeader(NS_LITERAL_CSTRING("refresh"),
    7143           0 :                                         refreshHeader);
    7144             : 
    7145           0 :     if (!refreshHeader.IsEmpty()) {
    7146             :       nsCOMPtr<nsIScriptSecurityManager> secMan =
    7147           0 :         do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
    7148           0 :       NS_ENSURE_SUCCESS(rv, rv);
    7149             : 
    7150           0 :       nsCOMPtr<nsIPrincipal> principal;
    7151           0 :       rv = secMan->GetChannelResultPrincipal(aChannel,
    7152           0 :                                              getter_AddRefs(principal));
    7153           0 :       NS_ENSURE_SUCCESS(rv, rv);
    7154             : 
    7155           0 :       SetupReferrerFromChannel(aChannel);
    7156           0 :       rv = SetupRefreshURIFromHeader(mCurrentURI, principal, refreshHeader);
    7157           0 :       if (NS_SUCCEEDED(rv)) {
    7158           0 :         return NS_REFRESHURI_HEADER_FOUND;
    7159             :       }
    7160             :     }
    7161             :   }
    7162           0 :   return rv;
    7163             : }
    7164             : 
    7165             : static void
    7166           2 : DoCancelRefreshURITimers(nsIMutableArray* aTimerList)
    7167             : {
    7168           2 :   if (!aTimerList) {
    7169           2 :     return;
    7170             :   }
    7171             : 
    7172           0 :   uint32_t n = 0;
    7173           0 :   aTimerList->GetLength(&n);
    7174             : 
    7175           0 :   while (n) {
    7176           0 :     nsCOMPtr<nsITimer> timer(do_QueryElementAt(aTimerList, --n));
    7177             : 
    7178           0 :     aTimerList->RemoveElementAt(n);  // bye bye owning timer ref
    7179             : 
    7180           0 :     if (timer) {
    7181           0 :       timer->Cancel();
    7182             :     }
    7183             :   }
    7184             : }
    7185             : 
    7186             : NS_IMETHODIMP
    7187           1 : nsDocShell::CancelRefreshURITimers()
    7188             : {
    7189           1 :   DoCancelRefreshURITimers(mRefreshURIList);
    7190           1 :   DoCancelRefreshURITimers(mSavedRefreshURIList);
    7191           1 :   mRefreshURIList = nullptr;
    7192           1 :   mSavedRefreshURIList = nullptr;
    7193             : 
    7194           1 :   return NS_OK;
    7195             : }
    7196             : 
    7197             : NS_IMETHODIMP
    7198           0 : nsDocShell::GetRefreshPending(bool* aResult)
    7199             : {
    7200           0 :   if (!mRefreshURIList) {
    7201           0 :     *aResult = false;
    7202           0 :     return NS_OK;
    7203             :   }
    7204             : 
    7205             :   uint32_t count;
    7206           0 :   nsresult rv = mRefreshURIList->GetLength(&count);
    7207           0 :   if (NS_SUCCEEDED(rv)) {
    7208           0 :     *aResult = (count != 0);
    7209             :   }
    7210           0 :   return rv;
    7211             : }
    7212             : 
    7213             : NS_IMETHODIMP
    7214           0 : nsDocShell::SuspendRefreshURIs()
    7215             : {
    7216           0 :   if (mRefreshURIList) {
    7217           0 :     uint32_t n = 0;
    7218           0 :     mRefreshURIList->GetLength(&n);
    7219             : 
    7220           0 :     for (uint32_t i = 0; i < n; ++i) {
    7221           0 :       nsCOMPtr<nsITimer> timer = do_QueryElementAt(mRefreshURIList, i);
    7222           0 :       if (!timer) {
    7223           0 :         continue; // this must be a nsRefreshURI already
    7224             :       }
    7225             : 
    7226             :       // Replace this timer object with a nsRefreshTimer object.
    7227           0 :       nsCOMPtr<nsITimerCallback> callback;
    7228           0 :       timer->GetCallback(getter_AddRefs(callback));
    7229             : 
    7230           0 :       timer->Cancel();
    7231             : 
    7232           0 :       nsCOMPtr<nsITimerCallback> rt = do_QueryInterface(callback);
    7233           0 :       NS_ASSERTION(rt,
    7234             :                    "RefreshURIList timer callbacks should only be RefreshTimer objects");
    7235             : 
    7236           0 :       mRefreshURIList->ReplaceElementAt(rt, i, /*weak =*/ false);
    7237             :     }
    7238             :   }
    7239             : 
    7240             :   // Suspend refresh URIs for our child shells as well.
    7241           0 :   nsTObserverArray<nsDocLoader*>::ForwardIterator iter(mChildList);
    7242           0 :   while (iter.HasMore()) {
    7243           0 :     nsCOMPtr<nsIDocShell> shell = do_QueryObject(iter.GetNext());
    7244           0 :     if (shell) {
    7245           0 :       shell->SuspendRefreshURIs();
    7246             :     }
    7247             :   }
    7248             : 
    7249           0 :   return NS_OK;
    7250             : }
    7251             : 
    7252             : NS_IMETHODIMP
    7253           0 : nsDocShell::ResumeRefreshURIs()
    7254             : {
    7255           0 :   RefreshURIFromQueue();
    7256             : 
    7257             :   // Resume refresh URIs for our child shells as well.
    7258           0 :   nsTObserverArray<nsDocLoader*>::ForwardIterator iter(mChildList);
    7259           0 :   while (iter.HasMore()) {
    7260           0 :     nsCOMPtr<nsIDocShell> shell = do_QueryObject(iter.GetNext());
    7261           0 :     if (shell) {
    7262           0 :       shell->ResumeRefreshURIs();
    7263             :     }
    7264             :   }
    7265             : 
    7266           0 :   return NS_OK;
    7267             : }
    7268             : 
    7269             : nsresult
    7270           6 : nsDocShell::RefreshURIFromQueue()
    7271             : {
    7272           6 :   if (!mRefreshURIList) {
    7273           6 :     return NS_OK;
    7274             :   }
    7275           0 :   uint32_t n = 0;
    7276           0 :   mRefreshURIList->GetLength(&n);
    7277             : 
    7278           0 :   while (n) {
    7279             :     nsCOMPtr<nsITimerCallback> refreshInfo =
    7280           0 :         do_QueryElementAt(mRefreshURIList, --n);
    7281             : 
    7282           0 :     if (refreshInfo) {
    7283             :       // This is the nsRefreshTimer object, waiting to be
    7284             :       // setup in a timer object and fired.
    7285             :       // Create the timer and  trigger it.
    7286             :       uint32_t delay =
    7287             :         static_cast<nsRefreshTimer*>(
    7288           0 :           static_cast<nsITimerCallback*>(refreshInfo))->GetDelay();
    7289           0 :       nsCOMPtr<nsITimer> timer = do_CreateInstance("@mozilla.org/timer;1");
    7290           0 :       nsCOMPtr<nsPIDOMWindowOuter> win = GetWindow();
    7291           0 :       if (timer && win) {
    7292             :         // Replace the nsRefreshTimer element in the queue with
    7293             :         // its corresponding timer object, so that in case another
    7294             :         // load comes through before the timer can go off, the timer will
    7295             :         // get cancelled in CancelRefreshURITimer()
    7296           0 :         mRefreshURIList->ReplaceElementAt(timer, n, /*weak =*/ false);
    7297           0 :         timer->SetTarget(win->TabGroup()->EventTargetFor(TaskCategory::Network));
    7298           0 :         timer->InitWithCallback(refreshInfo, delay, nsITimer::TYPE_ONE_SHOT);
    7299             :       }
    7300             :     }
    7301             :   }
    7302             : 
    7303           0 :   return NS_OK;
    7304             : }
    7305             : 
    7306             : //*****************************************************************************
    7307             : // nsDocShell::nsIContentViewerContainer
    7308             : //*****************************************************************************
    7309             : 
    7310             : NS_IMETHODIMP
    7311           8 : nsDocShell::Embed(nsIContentViewer* aContentViewer,
    7312             :                   const char* aCommand, nsISupports* aExtraInfo)
    7313             : {
    7314             :   // Save the LayoutHistoryState of the previous document, before
    7315             :   // setting up new document
    7316           8 :   PersistLayoutHistoryState();
    7317             : 
    7318           8 :   nsresult rv = SetupNewViewer(aContentViewer);
    7319           8 :   NS_ENSURE_SUCCESS(rv, rv);
    7320             : 
    7321             :   // If we are loading a wyciwyg url from history, change the base URI for
    7322             :   // the document to the original http url that created the document.write().
    7323             :   // This makes sure that all relative urls in a document.written page loaded
    7324             :   // via history work properly.
    7325          12 :   if (mCurrentURI &&
    7326           8 :       (mLoadType & LOAD_CMD_HISTORY ||
    7327           8 :        mLoadType == LOAD_RELOAD_NORMAL ||
    7328          12 :        mLoadType == LOAD_RELOAD_CHARSET_CHANGE)) {
    7329           0 :     bool isWyciwyg = false;
    7330             :     // Check if the url is wyciwyg
    7331           0 :     rv = mCurrentURI->SchemeIs("wyciwyg", &isWyciwyg);
    7332           0 :     if (isWyciwyg && NS_SUCCEEDED(rv)) {
    7333           0 :       SetBaseUrlForWyciwyg(aContentViewer);
    7334             :     }
    7335             :   }
    7336             :   // XXX What if SetupNewViewer fails?
    7337           8 :   if (mLSHE) {
    7338             :     // Restore the editing state, if it's stored in session history.
    7339           1 :     if (mLSHE->HasDetachedEditor()) {
    7340           0 :       ReattachEditorToWindow(mLSHE);
    7341             :     }
    7342             :     // Set history.state
    7343           1 :     SetDocCurrentStateObj(mLSHE);
    7344             : 
    7345           1 :     SetHistoryEntry(&mOSHE, mLSHE);
    7346             :   }
    7347             : 
    7348           8 :   bool updateHistory = true;
    7349             : 
    7350             :   // Determine if this type of load should update history
    7351           8 :   switch (mLoadType) {
    7352             :     case LOAD_NORMAL_REPLACE:
    7353             :     case LOAD_STOP_CONTENT_AND_REPLACE:
    7354             :     case LOAD_RELOAD_BYPASS_CACHE:
    7355             :     case LOAD_RELOAD_BYPASS_PROXY:
    7356             :     case LOAD_RELOAD_BYPASS_PROXY_AND_CACHE:
    7357             :     case LOAD_REPLACE_BYPASS_CACHE:
    7358           0 :       updateHistory = false;
    7359           0 :       break;
    7360             :     default:
    7361           8 :       break;
    7362             :   }
    7363             : 
    7364           8 :   if (!updateHistory) {
    7365           0 :     SetLayoutHistoryState(nullptr);
    7366             :   }
    7367             : 
    7368           8 :   return NS_OK;
    7369             : }
    7370             : 
    7371             : NS_IMETHODIMP
    7372           0 : nsDocShell::SetIsPrinting(bool aIsPrinting)
    7373             : {
    7374           0 :   mIsPrintingOrPP = aIsPrinting;
    7375           0 :   return NS_OK;
    7376             : }
    7377             : 
    7378             : //*****************************************************************************
    7379             : // nsDocShell::nsIWebProgressListener
    7380             : //*****************************************************************************
    7381             : 
    7382             : NS_IMETHODIMP
    7383           0 : nsDocShell::OnProgressChange(nsIWebProgress* aProgress,
    7384             :                              nsIRequest* aRequest,
    7385             :                              int32_t aCurSelfProgress,
    7386             :                              int32_t aMaxSelfProgress,
    7387             :                              int32_t aCurTotalProgress,
    7388             :                              int32_t aMaxTotalProgress)
    7389             : {
    7390           0 :   return NS_OK;
    7391             : }
    7392             : 
    7393             : NS_IMETHODIMP
    7394          27 : nsDocShell::OnStateChange(nsIWebProgress* aProgress, nsIRequest* aRequest,
    7395             :                           uint32_t aStateFlags, nsresult aStatus)
    7396             : {
    7397          27 :   if ((~aStateFlags & (STATE_START | STATE_IS_NETWORK)) == 0) {
    7398             :     // Save timing statistics.
    7399          12 :     nsCOMPtr<nsIChannel> channel(do_QueryInterface(aRequest));
    7400          12 :     nsCOMPtr<nsIURI> uri;
    7401           6 :     channel->GetURI(getter_AddRefs(uri));
    7402          12 :     nsAutoCString aURI;
    7403           6 :     uri->GetAsciiSpec(aURI);
    7404             : 
    7405          12 :     nsCOMPtr<nsIWyciwygChannel> wcwgChannel(do_QueryInterface(aRequest));
    7406             :     nsCOMPtr<nsIWebProgress> webProgress =
    7407          12 :       do_QueryInterface(GetAsSupports(this));
    7408             : 
    7409             :     // We don't update navigation timing for wyciwyg channels
    7410           6 :     if (this == aProgress && !wcwgChannel) {
    7411           6 :       mozilla::Unused << MaybeInitTiming();
    7412           6 :       mTiming->NotifyFetchStart(uri,
    7413           6 :                                 ConvertLoadTypeToNavigationType(mLoadType));
    7414             :     }
    7415             : 
    7416             :     // Was the wyciwyg document loaded on this docshell?
    7417           6 :     if (wcwgChannel && !mLSHE && (mItemType == typeContent) &&
    7418           0 :         aProgress == webProgress.get()) {
    7419           0 :       bool equalUri = true;
    7420             :       // Store the wyciwyg url in session history, only if it is
    7421             :       // being loaded fresh for the first time. We don't want
    7422             :       // multiple entries for successive loads
    7423           0 :       if (mCurrentURI &&
    7424           0 :           NS_SUCCEEDED(uri->Equals(mCurrentURI, &equalUri)) &&
    7425           0 :           !equalUri) {
    7426           0 :         nsCOMPtr<nsIDocShellTreeItem> parentAsItem;
    7427           0 :         GetSameTypeParent(getter_AddRefs(parentAsItem));
    7428           0 :         nsCOMPtr<nsIDocShell> parentDS(do_QueryInterface(parentAsItem));
    7429           0 :         bool inOnLoadHandler = false;
    7430           0 :         if (parentDS) {
    7431           0 :           parentDS->GetIsExecutingOnLoadHandler(&inOnLoadHandler);
    7432             :         }
    7433           0 :         if (inOnLoadHandler) {
    7434             :           // We're handling parent's load event listener, which causes
    7435             :           // document.write in a subdocument.
    7436             :           // Need to clear the session history for all child
    7437             :           // docshells so that we can handle them like they would
    7438             :           // all be added dynamically.
    7439           0 :           nsCOMPtr<nsIDocShell> parent = do_QueryInterface(parentAsItem);
    7440           0 :           if (parent) {
    7441           0 :             bool oshe = false;
    7442           0 :             nsCOMPtr<nsISHEntry> entry;
    7443           0 :             parent->GetCurrentSHEntry(getter_AddRefs(entry), &oshe);
    7444           0 :             static_cast<nsDocShell*>(parent.get())->ClearFrameHistory(entry);
    7445             :           }
    7446             :         }
    7447             : 
    7448             :         // This is a document.write(). Get the made-up url
    7449             :         // from the channel and store it in session history.
    7450             :         // Pass false for aCloneChildren, since we're creating
    7451             :         // a new DOM here.
    7452           0 :         AddToSessionHistory(uri, wcwgChannel, nullptr, nullptr, false,
    7453           0 :                             getter_AddRefs(mLSHE));
    7454           0 :         SetCurrentURI(uri, aRequest, true, 0);
    7455             :         // Save history state of the previous page
    7456           0 :         PersistLayoutHistoryState();
    7457             :         // We'll never get an Embed() for this load, so just go ahead
    7458             :         // and SetHistoryEntry now.
    7459           0 :         SetHistoryEntry(&mOSHE, mLSHE);
    7460             :       }
    7461             :     }
    7462             :     // Page has begun to load
    7463           6 :     mBusyFlags = BUSY_FLAGS_BUSY | BUSY_FLAGS_BEFORE_PAGE_LOAD;
    7464             : 
    7465           6 :     if ((aStateFlags & STATE_RESTORING) == 0) {
    7466             :       // Show the progress cursor if the pref is set
    7467           6 :       if (nsContentUtils::UseActivityCursor()) {
    7468           0 :         nsCOMPtr<nsIWidget> mainWidget;
    7469           0 :         GetMainWidget(getter_AddRefs(mainWidget));
    7470           0 :         if (mainWidget) {
    7471           0 :           mainWidget->SetCursor(eCursor_spinning);
    7472             :         }
    7473             :       }
    7474             :     }
    7475          21 :   } else if ((~aStateFlags & (STATE_TRANSFERRING | STATE_IS_DOCUMENT)) == 0) {
    7476             :     // Page is loading
    7477           5 :     mBusyFlags = BUSY_FLAGS_BUSY | BUSY_FLAGS_PAGE_LOADING;
    7478          16 :   } else if ((aStateFlags & STATE_STOP) && (aStateFlags & STATE_IS_NETWORK)) {
    7479             :     // Page has finished loading
    7480           6 :     mBusyFlags = BUSY_FLAGS_NONE;
    7481             : 
    7482             :     // Hide the progress cursor if the pref is set
    7483           6 :     if (nsContentUtils::UseActivityCursor()) {
    7484           0 :       nsCOMPtr<nsIWidget> mainWidget;
    7485           0 :       GetMainWidget(getter_AddRefs(mainWidget));
    7486           0 :       if (mainWidget) {
    7487           0 :         mainWidget->SetCursor(eCursor_standard);
    7488             :       }
    7489             :     }
    7490             :   }
    7491          27 :   if ((~aStateFlags & (STATE_IS_DOCUMENT | STATE_STOP)) == 0) {
    7492             :     nsCOMPtr<nsIWebProgress> webProgress =
    7493          16 :       do_QueryInterface(GetAsSupports(this));
    7494             :     // Is the document stop notification for this document?
    7495           8 :     if (aProgress == webProgress.get()) {
    7496          12 :       nsCOMPtr<nsIChannel> channel(do_QueryInterface(aRequest));
    7497           6 :       EndPageLoad(aProgress, channel, aStatus);
    7498             :     }
    7499             :   }
    7500             :   // note that redirect state changes will go through here as well, but it
    7501             :   // is better to handle those in OnRedirectStateChange where more
    7502             :   // information is available.
    7503          27 :   return NS_OK;
    7504             : }
    7505             : 
    7506             : NS_IMETHODIMP
    7507           0 : nsDocShell::OnLocationChange(nsIWebProgress* aProgress, nsIRequest* aRequest,
    7508             :                              nsIURI* aURI, uint32_t aFlags)
    7509             : {
    7510           0 :   NS_NOTREACHED("notification excluded in AddProgressListener(...)");
    7511           0 :   return NS_OK;
    7512             : }
    7513             : 
    7514             : void
    7515           0 : nsDocShell::OnRedirectStateChange(nsIChannel* aOldChannel,
    7516             :                                   nsIChannel* aNewChannel,
    7517             :                                   uint32_t aRedirectFlags,
    7518             :                                   uint32_t aStateFlags)
    7519             : {
    7520           0 :   NS_ASSERTION(aStateFlags & STATE_REDIRECTING,
    7521             :                "Calling OnRedirectStateChange when there is no redirect");
    7522             : 
    7523             :   // If mixed content is allowed for the old channel, we forward
    7524             :   // the permission to the new channel if it has the same origin
    7525             :   // as the old one.
    7526           0 :   if (mMixedContentChannel && mMixedContentChannel == aOldChannel) {
    7527           0 :     nsresult rv = nsContentUtils::CheckSameOrigin(mMixedContentChannel, aNewChannel);
    7528           0 :     if (NS_SUCCEEDED(rv)) {
    7529           0 :       SetMixedContentChannel(aNewChannel); // Same origin: forward permission.
    7530             :     } else {
    7531           0 :       SetMixedContentChannel(nullptr); // Different origin: clear mMixedContentChannel.
    7532             :     }
    7533             :   }
    7534             : 
    7535           0 :   if (!(aStateFlags & STATE_IS_DOCUMENT)) {
    7536           0 :     return;  // not a toplevel document
    7537             :   }
    7538             : 
    7539           0 :   nsCOMPtr<nsIURI> oldURI, newURI;
    7540           0 :   aOldChannel->GetURI(getter_AddRefs(oldURI));
    7541           0 :   aNewChannel->GetURI(getter_AddRefs(newURI));
    7542           0 :   if (!oldURI || !newURI) {
    7543           0 :     return;
    7544             :   }
    7545             : 
    7546             :   // Below a URI visit is saved (see AddURIVisit method doc).
    7547             :   // The visit chain looks something like:
    7548             :   //   ...
    7549             :   //   Site N - 1
    7550             :   //                =>  Site N
    7551             :   //   (redirect to =>) Site N + 1 (we are here!)
    7552             : 
    7553             :   // Get N - 1 and transition type
    7554           0 :   nsCOMPtr<nsIURI> previousURI;
    7555           0 :   uint32_t previousFlags = 0;
    7556           0 :   ExtractLastVisit(aOldChannel, getter_AddRefs(previousURI), &previousFlags);
    7557             : 
    7558           0 :   if (aRedirectFlags & nsIChannelEventSink::REDIRECT_INTERNAL ||
    7559           0 :       ChannelIsPost(aOldChannel)) {
    7560             :     // 1. Internal redirects are ignored because they are specific to the
    7561             :     //    channel implementation.
    7562             :     // 2. POSTs are not saved by global history.
    7563             :     //
    7564             :     // Regardless, we need to propagate the previous visit to the new
    7565             :     // channel.
    7566           0 :     SaveLastVisit(aNewChannel, previousURI, previousFlags);
    7567             :   } else {
    7568           0 :     nsCOMPtr<nsIURI> referrer;
    7569             :     // Treat referrer as null if there is an error getting it.
    7570           0 :     (void)NS_GetReferrerFromChannel(aOldChannel, getter_AddRefs(referrer));
    7571             : 
    7572             :     // Get the HTTP response code, if available.
    7573           0 :     uint32_t responseStatus = 0;
    7574           0 :     nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aOldChannel);
    7575           0 :     if (httpChannel) {
    7576           0 :       Unused << httpChannel->GetResponseStatus(&responseStatus);
    7577             :     }
    7578             : 
    7579             :     // Add visit N -1 => N
    7580           0 :     AddURIVisit(oldURI, referrer, previousURI, previousFlags, responseStatus);
    7581             : 
    7582             :     // Since N + 1 could be the final destination, we will not save N => N + 1
    7583             :     // here.  OnNewURI will do that, so we will cache it.
    7584           0 :     SaveLastVisit(aNewChannel, oldURI, aRedirectFlags);
    7585             :   }
    7586             : 
    7587             :   // check if the new load should go through the application cache.
    7588             :   nsCOMPtr<nsIApplicationCacheChannel> appCacheChannel =
    7589           0 :     do_QueryInterface(aNewChannel);
    7590           0 :   if (appCacheChannel) {
    7591           0 :     if (GeckoProcessType_Default != XRE_GetProcessType()) {
    7592             :       // Permission will be checked in the parent process.
    7593           0 :       appCacheChannel->SetChooseApplicationCache(true);
    7594             :     } else {
    7595             :       nsCOMPtr<nsIScriptSecurityManager> secMan =
    7596           0 :         do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID);
    7597             : 
    7598           0 :       if (secMan) {
    7599           0 :         nsCOMPtr<nsIPrincipal> principal;
    7600           0 :         secMan->GetDocShellCodebasePrincipal(newURI, this,
    7601           0 :                                              getter_AddRefs(principal));
    7602           0 :         appCacheChannel->SetChooseApplicationCache(
    7603           0 :           NS_ShouldCheckAppCache(principal));
    7604             :       }
    7605             :     }
    7606             :   }
    7607             : 
    7608           0 :   if (!(aRedirectFlags & nsIChannelEventSink::REDIRECT_INTERNAL) &&
    7609           0 :       mLoadType & (LOAD_CMD_RELOAD | LOAD_CMD_HISTORY)) {
    7610           0 :     mLoadType = LOAD_NORMAL_REPLACE;
    7611           0 :     SetHistoryEntry(&mLSHE, nullptr);
    7612             :   }
    7613             : }
    7614             : 
    7615             : NS_IMETHODIMP
    7616           0 : nsDocShell::OnStatusChange(nsIWebProgress* aWebProgress,
    7617             :                            nsIRequest* aRequest,
    7618             :                            nsresult aStatus, const char16_t* aMessage)
    7619             : {
    7620           0 :   NS_NOTREACHED("notification excluded in AddProgressListener(...)");
    7621           0 :   return NS_OK;
    7622             : }
    7623             : 
    7624             : NS_IMETHODIMP
    7625           0 : nsDocShell::OnSecurityChange(nsIWebProgress* aWebProgress,
    7626             :                              nsIRequest* aRequest, uint32_t aState)
    7627             : {
    7628           0 :   NS_NOTREACHED("notification excluded in AddProgressListener(...)");
    7629           0 :   return NS_OK;
    7630             : }
    7631             : 
    7632             : nsresult
    7633           6 : nsDocShell::EndPageLoad(nsIWebProgress* aProgress,
    7634             :                         nsIChannel* aChannel, nsresult aStatus)
    7635             : {
    7636           6 :   if (!aChannel) {
    7637           0 :     return NS_ERROR_NULL_POINTER;
    7638             :   }
    7639             : 
    7640          12 :   nsCOMPtr<nsIConsoleReportCollector> reporter = do_QueryInterface(aChannel);
    7641           6 :   if (reporter) {
    7642           2 :     nsCOMPtr<nsILoadGroup> loadGroup;
    7643           1 :     aChannel->GetLoadGroup(getter_AddRefs(loadGroup));
    7644           1 :     if (loadGroup) {
    7645           1 :       reporter->FlushConsoleReports(loadGroup);
    7646             :     } else {
    7647           0 :       reporter->FlushConsoleReports(GetDocument());
    7648             :     }
    7649             :   }
    7650             : 
    7651          12 :   nsCOMPtr<nsIURI> url;
    7652           6 :   nsresult rv = aChannel->GetURI(getter_AddRefs(url));
    7653           6 :   if (NS_FAILED(rv)) {
    7654           0 :     return rv;
    7655             :   }
    7656             : 
    7657          12 :   nsCOMPtr<nsITimedChannel> timingChannel = do_QueryInterface(aChannel);
    7658           6 :   if (timingChannel) {
    7659           1 :     TimeStamp channelCreationTime;
    7660           1 :     rv = timingChannel->GetChannelCreation(&channelCreationTime);
    7661           1 :     if (NS_SUCCEEDED(rv) && !channelCreationTime.IsNull()) {
    7662           1 :       Telemetry::AccumulateTimeDelta(Telemetry::TOTAL_CONTENT_PAGE_LOAD_TIME,
    7663           1 :                                      channelCreationTime);
    7664             :       nsCOMPtr<nsPILoadGroupInternal> internalLoadGroup =
    7665           2 :         do_QueryInterface(mLoadGroup);
    7666           1 :       if (internalLoadGroup) {
    7667           1 :         internalLoadGroup->OnEndPageLoad(aChannel);
    7668             :       }
    7669             :     }
    7670             :   }
    7671             : 
    7672             :   // Timing is picked up by the window, we don't need it anymore
    7673           6 :   mTiming = nullptr;
    7674             : 
    7675             :   // clean up reload state for meta charset
    7676           6 :   if (eCharsetReloadRequested == mCharsetReloadState) {
    7677           0 :     mCharsetReloadState = eCharsetReloadStopOrigional;
    7678             :   } else {
    7679           6 :     mCharsetReloadState = eCharsetReloadInit;
    7680             :   }
    7681             : 
    7682             :   // Save a pointer to the currently-loading history entry.
    7683             :   // nsDocShell::EndPageLoad will clear mLSHE, but we may need this history
    7684             :   // entry further down in this method.
    7685          12 :   nsCOMPtr<nsISHEntry> loadingSHE = mLSHE;
    7686             :   mozilla::Unused << loadingSHE; // XXX: Not sure if we need this anymore
    7687             : 
    7688             :   //
    7689             :   // one of many safeguards that prevent death and destruction if
    7690             :   // someone is so very very rude as to bring this window down
    7691             :   // during this load handler.
    7692             :   //
    7693          12 :   nsCOMPtr<nsIDocShell> kungFuDeathGrip(this);
    7694             : 
    7695             :   // Notify the ContentViewer that the Document has finished loading.  This
    7696             :   // will cause any OnLoad(...) and PopState(...) handlers to fire.
    7697           6 :   if (!mEODForCurrentDocument && mContentViewer) {
    7698           6 :     mIsExecutingOnLoadHandler = true;
    7699           6 :     mContentViewer->LoadComplete(aStatus);
    7700           6 :     mIsExecutingOnLoadHandler = false;
    7701             : 
    7702           6 :     mEODForCurrentDocument = true;
    7703             : 
    7704             :     // If all documents have completed their loading
    7705             :     // favor native event dispatch priorities
    7706             :     // over performance
    7707           6 :     if (--gNumberOfDocumentsLoading == 0) {
    7708             :       // Hint to use normal native event dispatch priorities
    7709           2 :       FavorPerformanceHint(false);
    7710             :     }
    7711             :   }
    7712             :   /* Check if the httpChannel has any cache-control related response headers,
    7713             :    * like no-store, no-cache. If so, update SHEntry so that
    7714             :    * when a user goes back/forward to this page, we appropriately do
    7715             :    * form value restoration or load from server.
    7716             :    */
    7717          12 :   nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aChannel));
    7718           6 :   if (!httpChannel) {
    7719             :     // HttpChannel could be hiding underneath a Multipart channel.
    7720           5 :     GetHttpChannel(aChannel, getter_AddRefs(httpChannel));
    7721             :   }
    7722             : 
    7723           6 :   if (httpChannel) {
    7724             :     // figure out if SH should be saving layout state.
    7725           1 :     bool discardLayoutState = ShouldDiscardLayoutState(httpChannel);
    7726           3 :     if (mLSHE && discardLayoutState && (mLoadType & LOAD_CMD_NORMAL) &&
    7727           1 :         (mLoadType != LOAD_BYPASS_HISTORY) && (mLoadType != LOAD_ERROR_PAGE)) {
    7728           0 :       mLSHE->SetSaveLayoutStateFlag(false);
    7729             :     }
    7730             :   }
    7731             : 
    7732             :   // Clear mLSHE after calling the onLoadHandlers. This way, if the
    7733             :   // onLoadHandler tries to load something different in
    7734             :   // itself or one of its children, we can deal with it appropriately.
    7735           6 :   if (mLSHE) {
    7736           1 :     mLSHE->SetLoadType(nsIDocShellLoadInfo::loadHistory);
    7737             : 
    7738             :     // Clear the mLSHE reference to indicate document loading is done one
    7739             :     // way or another.
    7740           1 :     SetHistoryEntry(&mLSHE, nullptr);
    7741             :   }
    7742             :   // if there's a refresh header in the channel, this method
    7743             :   // will set it up for us.
    7744           6 :   if (mIsActive || !mDisableMetaRefreshWhenInactive)
    7745           6 :     RefreshURIFromQueue();
    7746             : 
    7747             :   // Test whether this is the top frame or a subframe
    7748           6 :   bool isTopFrame = true;
    7749          12 :   nsCOMPtr<nsIDocShellTreeItem> targetParentTreeItem;
    7750           6 :   rv = GetSameTypeParent(getter_AddRefs(targetParentTreeItem));
    7751           6 :   if (NS_SUCCEEDED(rv) && targetParentTreeItem) {
    7752           1 :     isTopFrame = false;
    7753             :   }
    7754             : 
    7755             :   //
    7756             :   // If the page load failed, then deal with the error condition...
    7757             :   // Errors are handled as follows:
    7758             :   //   1. Check to see if it's a file not found error or bad content
    7759             :   //      encoding error.
    7760             :   //   2. Send the URI to a keyword server (if enabled)
    7761             :   //   3. If the error was DNS failure, then add www and .com to the URI
    7762             :   //      (if appropriate).
    7763             :   //   4. Throw an error dialog box...
    7764             :   //
    7765           6 :   if (url && NS_FAILED(aStatus)) {
    7766           3 :     if (aStatus == NS_ERROR_FILE_NOT_FOUND ||
    7767           3 :         aStatus == NS_ERROR_FILE_ACCESS_DENIED ||
    7768           3 :         aStatus == NS_ERROR_CORRUPTED_CONTENT ||
    7769             :         aStatus == NS_ERROR_INVALID_CONTENT_ENCODING) {
    7770           0 :       DisplayLoadError(aStatus, url, nullptr, aChannel);
    7771           0 :       return NS_OK;
    7772             :     }
    7773             : 
    7774             :     // Handle iframe document not loading error because source was
    7775             :     // a tracking URL. We make a note of this iframe node by including
    7776             :     // it in a dedicated array of blocked tracking nodes under its parent
    7777             :     // document. (document of parent window of blocked document)
    7778           3 :     if (isTopFrame == false && aStatus == NS_ERROR_TRACKING_URI) {
    7779             :       // frameElement is our nsIContent to be annotated
    7780           0 :       nsCOMPtr<nsIDOMElement> frameElement;
    7781           0 :       nsPIDOMWindowOuter* thisWindow = GetWindow();
    7782           0 :       if (!thisWindow) {
    7783           0 :         return NS_OK;
    7784             :       }
    7785             : 
    7786           0 :       frameElement = thisWindow->GetFrameElement();
    7787           0 :       if (!frameElement) {
    7788           0 :         return NS_OK;
    7789             :       }
    7790             : 
    7791             :       // Parent window
    7792           0 :       nsCOMPtr<nsIDocShellTreeItem> parentItem;
    7793           0 :       GetSameTypeParent(getter_AddRefs(parentItem));
    7794           0 :       if (!parentItem) {
    7795           0 :         return NS_OK;
    7796             :       }
    7797             : 
    7798           0 :       nsCOMPtr<nsIDocument> parentDoc;
    7799           0 :       parentDoc = parentItem->GetDocument();
    7800           0 :       if (!parentDoc) {
    7801           0 :         return NS_OK;
    7802             :       }
    7803             : 
    7804           0 :       nsCOMPtr<nsIContent> cont = do_QueryInterface(frameElement);
    7805           0 :       parentDoc->AddBlockedTrackingNode(cont);
    7806             : 
    7807           0 :       return NS_OK;
    7808             :     }
    7809             : 
    7810           3 :     if (sURIFixup) {
    7811             :       //
    7812             :       // Try and make an alternative URI from the old one
    7813             :       //
    7814           6 :       nsCOMPtr<nsIURI> newURI;
    7815           6 :       nsCOMPtr<nsIInputStream> newPostData;
    7816             : 
    7817           6 :       nsAutoCString oldSpec;
    7818           3 :       url->GetSpec(oldSpec);
    7819             : 
    7820             :       //
    7821             :       // First try keyword fixup
    7822             :       //
    7823           6 :       nsAutoString keywordProviderName, keywordAsSent;
    7824           3 :       if (aStatus == NS_ERROR_UNKNOWN_HOST && mAllowKeywordFixup) {
    7825           0 :         bool keywordsEnabled = Preferences::GetBool("keyword.enabled", false);
    7826             : 
    7827           0 :         nsAutoCString host;
    7828           0 :         url->GetHost(host);
    7829             : 
    7830           0 :         nsAutoCString scheme;
    7831           0 :         url->GetScheme(scheme);
    7832             : 
    7833           0 :         int32_t dotLoc = host.FindChar('.');
    7834             : 
    7835             :         // we should only perform a keyword search under the following
    7836             :         // conditions:
    7837             :         // (0) Pref keyword.enabled is true
    7838             :         // (1) the url scheme is http (or https)
    7839             :         // (2) the url does not have a protocol scheme
    7840             :         // If we don't enforce such a policy, then we end up doing
    7841             :         // keyword searchs on urls we don't intend like imap, file,
    7842             :         // mailbox, etc. This could lead to a security problem where we
    7843             :         // send data to the keyword server that we shouldn't be.
    7844             :         // Someone needs to clean up keywords in general so we can
    7845             :         // determine on a per url basis if we want keywords
    7846             :         // enabled...this is just a bandaid...
    7847           0 :         if (keywordsEnabled && !scheme.IsEmpty() &&
    7848           0 :             (scheme.Find("http") != 0)) {
    7849           0 :           keywordsEnabled = false;
    7850             :         }
    7851             : 
    7852           0 :         if (keywordsEnabled && (kNotFound == dotLoc)) {
    7853           0 :           nsCOMPtr<nsIURIFixupInfo> info;
    7854             :           // only send non-qualified hosts to the keyword server
    7855           0 :           if (!mOriginalUriString.IsEmpty()) {
    7856           0 :             sURIFixup->KeywordToURI(mOriginalUriString,
    7857           0 :                                     getter_AddRefs(newPostData),
    7858           0 :                                     getter_AddRefs(info));
    7859             :           } else {
    7860             :             //
    7861             :             // If this string was passed through nsStandardURL by
    7862             :             // chance, then it may have been converted from UTF-8 to
    7863             :             // ACE, which would result in a completely bogus keyword
    7864             :             // query.  Here we try to recover the original Unicode
    7865             :             // value, but this is not 100% correct since the value may
    7866             :             // have been normalized per the IDN normalization rules.
    7867             :             //
    7868             :             // Since we don't have access to the exact original string
    7869             :             // that was entered by the user, this will just have to do.
    7870             :             bool isACE;
    7871           0 :             nsAutoCString utf8Host;
    7872             :             nsCOMPtr<nsIIDNService> idnSrv =
    7873           0 :               do_GetService(NS_IDNSERVICE_CONTRACTID);
    7874           0 :             if (idnSrv &&
    7875           0 :                 NS_SUCCEEDED(idnSrv->IsACE(host, &isACE)) && isACE &&
    7876           0 :                 NS_SUCCEEDED(idnSrv->ConvertACEtoUTF8(host, utf8Host))) {
    7877           0 :               sURIFixup->KeywordToURI(utf8Host,
    7878           0 :                                       getter_AddRefs(newPostData),
    7879           0 :                                       getter_AddRefs(info));
    7880             :             } else {
    7881           0 :               sURIFixup->KeywordToURI(host,
    7882           0 :                                       getter_AddRefs(newPostData),
    7883           0 :                                       getter_AddRefs(info));
    7884             :             }
    7885             :           }
    7886             : 
    7887           0 :           info->GetPreferredURI(getter_AddRefs(newURI));
    7888           0 :           if (newURI) {
    7889           0 :             info->GetKeywordAsSent(keywordAsSent);
    7890           0 :             info->GetKeywordProviderName(keywordProviderName);
    7891             :           }
    7892             :         } // end keywordsEnabled
    7893             :       }
    7894             : 
    7895             :       //
    7896             :       // Now try change the address, e.g. turn http://foo into
    7897             :       // http://www.foo.com
    7898             :       //
    7899           3 :       if (aStatus == NS_ERROR_UNKNOWN_HOST ||
    7900             :           aStatus == NS_ERROR_NET_RESET) {
    7901           0 :         bool doCreateAlternate = true;
    7902             : 
    7903             :         // Skip fixup for anything except a normal document load
    7904             :         // operation on the topframe.
    7905             : 
    7906           0 :         if (mLoadType != LOAD_NORMAL || !isTopFrame) {
    7907           0 :           doCreateAlternate = false;
    7908             :         } else {
    7909             :           // Test if keyword lookup produced a new URI or not
    7910           0 :           if (newURI) {
    7911           0 :             bool sameURI = false;
    7912           0 :             url->Equals(newURI, &sameURI);
    7913           0 :             if (!sameURI) {
    7914             :               // Keyword lookup made a new URI so no need to try
    7915             :               // an alternate one.
    7916           0 :               doCreateAlternate = false;
    7917             :             }
    7918             :           }
    7919             : 
    7920           0 :           if (doCreateAlternate) {
    7921             :             // Skip doing this if our channel was redirected, because we
    7922             :             // shouldn't be guessing things about the post-redirect URI.
    7923           0 :             nsLoadFlags loadFlags = 0;
    7924           0 :             if (NS_FAILED(aChannel->GetLoadFlags(&loadFlags)) ||
    7925           0 :                 (loadFlags & nsIChannel::LOAD_REPLACE)) {
    7926           0 :               doCreateAlternate = false;
    7927             :             }
    7928             :           }
    7929             :         }
    7930           0 :         if (doCreateAlternate) {
    7931           0 :           newURI = nullptr;
    7932           0 :           newPostData = nullptr;
    7933           0 :           keywordProviderName.Truncate();
    7934           0 :           keywordAsSent.Truncate();
    7935           0 :           sURIFixup->CreateFixupURI(oldSpec,
    7936             :                                     nsIURIFixup::FIXUP_FLAGS_MAKE_ALTERNATE_URI,
    7937           0 :                                     getter_AddRefs(newPostData),
    7938           0 :                                     getter_AddRefs(newURI));
    7939             :         }
    7940             :       }
    7941             : 
    7942             :       // Did we make a new URI that is different to the old one? If so
    7943             :       // load it.
    7944             :       //
    7945           3 :       if (newURI) {
    7946             :         // Make sure the new URI is different from the old one,
    7947             :         // otherwise there's little point trying to load it again.
    7948           0 :         bool sameURI = false;
    7949           0 :         url->Equals(newURI, &sameURI);
    7950           0 :         if (!sameURI) {
    7951           0 :           nsAutoCString newSpec;
    7952           0 :           newURI->GetSpec(newSpec);
    7953           0 :           NS_ConvertUTF8toUTF16 newSpecW(newSpec);
    7954             : 
    7955             :           // This notification is meant for Firefox Health Report so it
    7956             :           // can increment counts from the search engine
    7957           0 :           MaybeNotifyKeywordSearchLoading(keywordProviderName, keywordAsSent);
    7958             : 
    7959           0 :           nsCOMPtr<nsILoadInfo> loadInfo = aChannel->GetLoadInfo();
    7960             :           nsCOMPtr<nsIPrincipal> triggeringPrincipal = loadInfo
    7961           0 :             ? loadInfo->TriggeringPrincipal()
    7962           0 :             : nsContentUtils::GetSystemPrincipal();
    7963           0 :           return LoadURI(newSpecW.get(),       // URI string
    7964             :                          LOAD_FLAGS_NONE,      // Load flags
    7965             :                          nullptr,              // Referring URI
    7966             :                          newPostData,          // Post data stream
    7967             :                          nullptr,              // Headers stream
    7968           0 :                          triggeringPrincipal); // TriggeringPrincipal
    7969             :         }
    7970             :       }
    7971             :     }
    7972             : 
    7973             :     // Well, fixup didn't work :-(
    7974             :     // It is time to throw an error dialog box, and be done with it...
    7975             : 
    7976             :     // Errors to be shown only on top-level frames
    7977           6 :     if ((aStatus == NS_ERROR_UNKNOWN_HOST ||
    7978           3 :          aStatus == NS_ERROR_CONNECTION_REFUSED ||
    7979           3 :          aStatus == NS_ERROR_UNKNOWN_PROXY_HOST ||
    7980           3 :          aStatus == NS_ERROR_PROXY_CONNECTION_REFUSED) &&
    7981           0 :         (isTopFrame || UseErrorPages())) {
    7982           0 :       DisplayLoadError(aStatus, url, nullptr, aChannel);
    7983           6 :     } else if (aStatus == NS_ERROR_NET_TIMEOUT ||
    7984           3 :                aStatus == NS_ERROR_REDIRECT_LOOP ||
    7985           3 :                aStatus == NS_ERROR_UNKNOWN_SOCKET_TYPE ||
    7986           3 :                aStatus == NS_ERROR_NET_INTERRUPT ||
    7987           3 :                aStatus == NS_ERROR_NET_RESET ||
    7988           3 :                aStatus == NS_ERROR_OFFLINE ||
    7989           3 :                aStatus == NS_ERROR_MALWARE_URI ||
    7990           3 :                aStatus == NS_ERROR_PHISHING_URI ||
    7991           3 :                aStatus == NS_ERROR_UNWANTED_URI ||
    7992           3 :                aStatus == NS_ERROR_UNSAFE_CONTENT_TYPE ||
    7993           3 :                aStatus == NS_ERROR_REMOTE_XUL ||
    7994           3 :                aStatus == NS_ERROR_INTERCEPTION_FAILED ||
    7995           6 :                aStatus == NS_ERROR_NET_INADEQUATE_SECURITY ||
    7996           3 :                NS_ERROR_GET_MODULE(aStatus) == NS_ERROR_MODULE_SECURITY) {
    7997             :       // Errors to be shown for any frame
    7998           0 :       DisplayLoadError(aStatus, url, nullptr, aChannel);
    7999           3 :     } else if (aStatus == NS_ERROR_DOCUMENT_NOT_CACHED) {
    8000             :       // Non-caching channels will simply return NS_ERROR_OFFLINE.
    8001             :       // Caching channels would have to look at their flags to work
    8002             :       // out which error to return. Or we can fix up the error here.
    8003           0 :       if (!(mLoadType & LOAD_CMD_HISTORY)) {
    8004           0 :         aStatus = NS_ERROR_OFFLINE;
    8005             :       }
    8006           0 :       DisplayLoadError(aStatus, url, nullptr, aChannel);
    8007             :     }
    8008           3 :   } else if (url && NS_SUCCEEDED(aStatus)) {
    8009             :     // If we have a host
    8010           6 :     nsCOMPtr<nsILoadInfo> loadInfo = aChannel->GetLoadInfo();
    8011           3 :     if (loadInfo) {
    8012           3 :       mozilla::net::PredictorLearnRedirect(url, aChannel,
    8013           6 :                                            loadInfo->GetOriginAttributes());
    8014             :     }
    8015             :   }
    8016             : 
    8017           6 :   return NS_OK;
    8018             : }
    8019             : 
    8020             : //*****************************************************************************
    8021             : // nsDocShell: Content Viewer Management
    8022             : //*****************************************************************************
    8023             : 
    8024             : nsresult
    8025         594 : nsDocShell::EnsureContentViewer()
    8026             : {
    8027         594 :   if (mContentViewer) {
    8028         592 :     return NS_OK;
    8029             :   }
    8030           2 :   if (mIsBeingDestroyed) {
    8031           0 :     return NS_ERROR_FAILURE;
    8032             :   }
    8033             : 
    8034           4 :   nsCOMPtr<nsIURI> baseURI;
    8035           2 :   nsIPrincipal* principal = GetInheritedPrincipal(false);
    8036           4 :   nsCOMPtr<nsIDocShellTreeItem> parentItem;
    8037           2 :   GetSameTypeParent(getter_AddRefs(parentItem));
    8038           2 :   if (parentItem) {
    8039           0 :     if (nsCOMPtr<nsPIDOMWindowOuter> domWin = GetWindow()) {
    8040           0 :       nsCOMPtr<Element> parentElement = domWin->GetFrameElementInternal();
    8041           0 :       if (parentElement) {
    8042           0 :         baseURI = parentElement->GetBaseURI();
    8043             :       }
    8044             :     }
    8045             :   }
    8046             : 
    8047           2 :   nsresult rv = CreateAboutBlankContentViewer(principal, baseURI);
    8048             : 
    8049           2 :   NS_ENSURE_STATE(mContentViewer);
    8050             : 
    8051           2 :   if (NS_SUCCEEDED(rv)) {
    8052           4 :     nsCOMPtr<nsIDocument> doc(GetDocument());
    8053           2 :     NS_ASSERTION(doc,
    8054             :                  "Should have doc if CreateAboutBlankContentViewer "
    8055             :                  "succeeded!");
    8056             : 
    8057           2 :     doc->SetIsInitialDocument(true);
    8058             : 
    8059             :     // Documents created using EnsureContentViewer may be transient
    8060             :     // placeholders created by framescripts before content has a chance to
    8061             :     // load. In some cases, window.open(..., "noopener") will create such a
    8062             :     // document (in a new TabGroup) and then synchronously tear it down, firing
    8063             :     // a "pagehide" event. Doing so violates our assertions about
    8064             :     // DocGroups. It's easier to silence the assertion here than to avoid
    8065             :     // creating the extra document.
    8066           2 :     doc->IgnoreDocGroupMismatches();
    8067             :   }
    8068             : 
    8069           2 :   return rv;
    8070             : }
    8071             : 
    8072             : nsresult
    8073           4 : nsDocShell::CreateAboutBlankContentViewer(nsIPrincipal* aPrincipal,
    8074             :                                           nsIURI* aBaseURI,
    8075             :                                           bool aTryToSaveOldPresentation,
    8076             :                                           bool aCheckPermitUnload)
    8077             : {
    8078           8 :   nsCOMPtr<nsIDocument> blankDoc;
    8079           8 :   nsCOMPtr<nsIContentViewer> viewer;
    8080           4 :   nsresult rv = NS_ERROR_FAILURE;
    8081             : 
    8082             :   /* mCreatingDocument should never be true at this point. However, it's
    8083             :      a theoretical possibility. We want to know about it and make it stop,
    8084             :      and this sounds like a job for an assertion. */
    8085           4 :   NS_ASSERTION(!mCreatingDocument,
    8086             :                "infinite(?) loop creating document averted");
    8087           4 :   if (mCreatingDocument) {
    8088           0 :     return NS_ERROR_FAILURE;
    8089             :   }
    8090             : 
    8091             :   // mContentViewer->PermitUnload may release |this| docshell.
    8092           8 :   nsCOMPtr<nsIDocShell> kungFuDeathGrip(this);
    8093             : 
    8094           8 :   AutoRestore<bool> creatingDocument(mCreatingDocument);
    8095           4 :   mCreatingDocument = true;
    8096             : 
    8097           4 :   if (aPrincipal && !nsContentUtils::IsSystemPrincipal(aPrincipal) &&
    8098           0 :       mItemType != typeChrome) {
    8099           0 :     MOZ_ASSERT(aPrincipal->OriginAttributesRef() == mOriginAttributes);
    8100             :   }
    8101             : 
    8102             :   // Make sure timing is created.  But first record whether we had it
    8103             :   // already, so we don't clobber the timing for an in-progress load.
    8104           4 :   bool hadTiming = mTiming;
    8105           4 :   bool toBeReset = MaybeInitTiming();
    8106           4 :   if (mContentViewer) {
    8107           0 :     if (aCheckPermitUnload) {
    8108             :       // We've got a content viewer already. Make sure the user
    8109             :       // permits us to discard the current document and replace it
    8110             :       // with about:blank. And also ensure we fire the unload events
    8111             :       // in the current document.
    8112             : 
    8113             :       // Unload gets fired first for
    8114             :       // document loaded from the session history.
    8115           0 :       mTiming->NotifyBeforeUnload();
    8116             : 
    8117             :       bool okToUnload;
    8118           0 :       rv = mContentViewer->PermitUnload(&okToUnload);
    8119             : 
    8120           0 :       if (NS_SUCCEEDED(rv) && !okToUnload) {
    8121             :         // The user chose not to unload the page, interrupt the load.
    8122           0 :         MaybeResetInitTiming(toBeReset);
    8123           0 :         return NS_ERROR_FAILURE;
    8124             :       }
    8125           0 :       if (mTiming) {
    8126           0 :         mTiming->NotifyUnloadAccepted(mCurrentURI);
    8127             :       }
    8128             :     }
    8129             : 
    8130           0 :     mSavingOldViewer = aTryToSaveOldPresentation &&
    8131           0 :                        CanSavePresentation(LOAD_NORMAL, nullptr, nullptr);
    8132             : 
    8133             :     // Make sure to blow away our mLoadingURI just in case.  No loads
    8134             :     // from inside this pagehide.
    8135           0 :     mLoadingURI = nullptr;
    8136             : 
    8137             :     // Stop any in-progress loading, so that we don't accidentally trigger any
    8138             :     // PageShow notifications from Embed() interrupting our loading below.
    8139           0 :     Stop();
    8140             : 
    8141             :     // Notify the current document that it is about to be unloaded!!
    8142             :     //
    8143             :     // It is important to fire the unload() notification *before* any state
    8144             :     // is changed within the DocShell - otherwise, javascript will get the
    8145             :     // wrong information :-(
    8146             :     //
    8147           0 :     (void)FirePageHideNotification(!mSavingOldViewer);
    8148             :   }
    8149             : 
    8150             :   // Now make sure we don't think we're in the middle of firing unload after
    8151             :   // this point.  This will make us fire unload when the about:blank document
    8152             :   // unloads... but that's ok, more or less.  Would be nice if it fired load
    8153             :   // too, of course.
    8154           4 :   mFiredUnloadEvent = false;
    8155             : 
    8156             :   nsCOMPtr<nsIDocumentLoaderFactory> docFactory =
    8157           8 :     nsContentUtils::FindInternalContentViewer(NS_LITERAL_CSTRING("text/html"));
    8158             : 
    8159           4 :   if (docFactory) {
    8160           8 :     nsCOMPtr<nsIPrincipal> principal;
    8161           4 :     if (mSandboxFlags & SANDBOXED_ORIGIN) {
    8162           0 :       if (aPrincipal) {
    8163           0 :         principal = NullPrincipal::CreateWithInheritedAttributes(aPrincipal);
    8164             :       } else {
    8165           0 :         principal = NullPrincipal::CreateWithInheritedAttributes(this);
    8166             :       }
    8167             :     } else {
    8168           4 :       principal = aPrincipal;
    8169             :     }
    8170             :     // generate (about:blank) document to load
    8171           8 :     docFactory->CreateBlankDocument(mLoadGroup, principal,
    8172           8 :                                     getter_AddRefs(blankDoc));
    8173           4 :     if (blankDoc) {
    8174             :       // Hack: set the base URI manually, since this document never
    8175             :       // got Reset() with a channel.
    8176           4 :       blankDoc->SetBaseURI(aBaseURI);
    8177             : 
    8178           4 :       blankDoc->SetContainer(this);
    8179             : 
    8180             :       // Copy our sandbox flags to the document. These are immutable
    8181             :       // after being set here.
    8182           4 :       blankDoc->SetSandboxFlags(mSandboxFlags);
    8183             : 
    8184             :       // create a content viewer for us and the new document
    8185           8 :       docFactory->CreateInstanceForDocument(
    8186             :         NS_ISUPPORTS_CAST(nsIDocShell*, this), blankDoc, "view",
    8187           8 :         getter_AddRefs(viewer));
    8188             : 
    8189             :       // hook 'em up
    8190           4 :       if (viewer) {
    8191           4 :         viewer->SetContainer(this);
    8192           4 :         rv = Embed(viewer, "", 0);
    8193           4 :         NS_ENSURE_SUCCESS(rv, rv);
    8194             : 
    8195           4 :         SetCurrentURI(blankDoc->GetDocumentURI(), nullptr, true, 0);
    8196           4 :         rv = mIsBeingDestroyed ? NS_ERROR_NOT_AVAILABLE : NS_OK;
    8197             :       }
    8198             :     }
    8199             :   }
    8200             : 
    8201             :   // The transient about:blank viewer doesn't have a session history entry.
    8202           4 :   SetHistoryEntry(&mOSHE, nullptr);
    8203             : 
    8204             :   // Clear out our mTiming like we would in EndPageLoad, if we didn't
    8205             :   // have one before entering this function.
    8206           4 :   if (!hadTiming) {
    8207           4 :     mTiming = nullptr;
    8208           4 :     mBlankTiming = true;
    8209             :   }
    8210             : 
    8211           4 :   return rv;
    8212             : }
    8213             : 
    8214             : NS_IMETHODIMP
    8215           2 : nsDocShell::CreateAboutBlankContentViewer(nsIPrincipal* aPrincipal)
    8216             : {
    8217           2 :   return CreateAboutBlankContentViewer(aPrincipal, nullptr);
    8218             : }
    8219             : 
    8220             : NS_IMETHODIMP
    8221           0 : nsDocShell::ForceCreateAboutBlankContentViewer(nsIPrincipal* aPrincipal)
    8222             : {
    8223           0 :   return CreateAboutBlankContentViewer(aPrincipal, nullptr, true, false);
    8224             : }
    8225             : 
    8226             : bool
    8227           6 : nsDocShell::CanSavePresentation(uint32_t aLoadType,
    8228             :                                 nsIRequest* aNewRequest,
    8229             :                                 nsIDocument* aNewDocument)
    8230             : {
    8231           6 :   if (!mOSHE) {
    8232           6 :     return false;  // no entry to save into
    8233             :   }
    8234             : 
    8235           0 :   nsCOMPtr<nsIContentViewer> viewer;
    8236           0 :   mOSHE->GetContentViewer(getter_AddRefs(viewer));
    8237           0 :   if (viewer) {
    8238           0 :     NS_WARNING("mOSHE already has a content viewer!");
    8239           0 :     return false;
    8240             :   }
    8241             : 
    8242             :   // Only save presentation for "normal" loads and link loads.  Anything else
    8243             :   // probably wants to refetch the page, so caching the old presentation
    8244             :   // would be incorrect.
    8245           0 :   if (aLoadType != LOAD_NORMAL &&
    8246           0 :       aLoadType != LOAD_HISTORY &&
    8247           0 :       aLoadType != LOAD_LINK &&
    8248           0 :       aLoadType != LOAD_STOP_CONTENT &&
    8249           0 :       aLoadType != LOAD_STOP_CONTENT_AND_REPLACE &&
    8250             :       aLoadType != LOAD_ERROR_PAGE) {
    8251           0 :     return false;
    8252             :   }
    8253             : 
    8254             :   // If the session history entry has the saveLayoutState flag set to false,
    8255             :   // then we should not cache the presentation.
    8256             :   bool canSaveState;
    8257           0 :   mOSHE->GetSaveLayoutStateFlag(&canSaveState);
    8258           0 :   if (!canSaveState) {
    8259           0 :     return false;
    8260             :   }
    8261             : 
    8262             :   // If the document is not done loading, don't cache it.
    8263           0 :   if (!mScriptGlobal || mScriptGlobal->IsLoading()) {
    8264           0 :     return false;
    8265             :   }
    8266             : 
    8267           0 :   if (mScriptGlobal->WouldReuseInnerWindow(aNewDocument)) {
    8268           0 :     return false;
    8269             :   }
    8270             : 
    8271             :   // Avoid doing the work of saving the presentation state in the case where
    8272             :   // the content viewer cache is disabled.
    8273           0 :   if (nsSHistory::GetMaxTotalViewers() == 0) {
    8274           0 :     return false;
    8275             :   }
    8276             : 
    8277             :   // Don't cache the content viewer if we're in a subframe and the subframe
    8278             :   // pref is disabled.
    8279             :   bool cacheFrames =
    8280           0 :     Preferences::GetBool("browser.sessionhistory.cache_subframes", false);
    8281           0 :   if (!cacheFrames) {
    8282           0 :     nsCOMPtr<nsIDocShellTreeItem> root;
    8283           0 :     GetSameTypeParent(getter_AddRefs(root));
    8284           0 :     if (root && root != this) {
    8285           0 :       return false;  // this is a subframe load
    8286             :     }
    8287             :   }
    8288             : 
    8289             :   // If the document does not want its presentation cached, then don't.
    8290           0 :   nsCOMPtr<nsIDocument> doc = mScriptGlobal->GetExtantDoc();
    8291           0 :   return doc && doc->CanSavePresentation(aNewRequest);
    8292             : }
    8293             : 
    8294             : void
    8295           0 : nsDocShell::ReattachEditorToWindow(nsISHEntry* aSHEntry)
    8296             : {
    8297           0 :   NS_ASSERTION(!mEditorData,
    8298             :                "Why reattach an editor when we already have one?");
    8299           0 :   NS_ASSERTION(aSHEntry && aSHEntry->HasDetachedEditor(),
    8300             :                "Reattaching when there's not a detached editor.");
    8301             : 
    8302           0 :   if (mEditorData || !aSHEntry) {
    8303           0 :     return;
    8304             :   }
    8305             : 
    8306           0 :   mEditorData = aSHEntry->ForgetEditorData();
    8307           0 :   if (mEditorData) {
    8308             : #ifdef DEBUG
    8309             :     nsresult rv =
    8310             : #endif
    8311           0 :       mEditorData->ReattachToWindow(this);
    8312           0 :     NS_ASSERTION(NS_SUCCEEDED(rv), "Failed to reattach editing session");
    8313             :   }
    8314             : }
    8315             : 
    8316             : void
    8317           4 : nsDocShell::DetachEditorFromWindow()
    8318             : {
    8319           4 :   if (!mEditorData || mEditorData->WaitingForLoad()) {
    8320             :     // If there's nothing to detach, or if the editor data is actually set
    8321             :     // up for the _new_ page that's coming in, don't detach.
    8322           4 :     return;
    8323             :   }
    8324             : 
    8325           0 :   NS_ASSERTION(!mOSHE || !mOSHE->HasDetachedEditor(),
    8326             :                "Detaching editor when it's already detached.");
    8327             : 
    8328           0 :   nsresult res = mEditorData->DetachFromWindow();
    8329           0 :   NS_ASSERTION(NS_SUCCEEDED(res), "Failed to detach editor");
    8330             : 
    8331           0 :   if (NS_SUCCEEDED(res)) {
    8332             :     // Make mOSHE hold the owning ref to the editor data.
    8333           0 :     if (mOSHE) {
    8334           0 :       mOSHE->SetEditorData(mEditorData.forget());
    8335             :     } else {
    8336           0 :       mEditorData = nullptr;
    8337             :     }
    8338             :   }
    8339             : 
    8340             : #ifdef DEBUG
    8341             :   {
    8342             :     bool isEditable;
    8343           0 :     GetEditable(&isEditable);
    8344           0 :     NS_ASSERTION(!isEditable,
    8345             :                  "Window is still editable after detaching editor.");
    8346             :   }
    8347             : #endif // DEBUG
    8348             : }
    8349             : 
    8350             : nsresult
    8351           0 : nsDocShell::CaptureState()
    8352             : {
    8353           0 :   if (!mOSHE || mOSHE == mLSHE) {
    8354             :     // No entry to save into, or we're replacing the existing entry.
    8355           0 :     return NS_ERROR_FAILURE;
    8356             :   }
    8357             : 
    8358           0 :   if (!mScriptGlobal) {
    8359           0 :     return NS_ERROR_FAILURE;
    8360             :   }
    8361             : 
    8362           0 :   nsCOMPtr<nsISupports> windowState = mScriptGlobal->SaveWindowState();
    8363           0 :   NS_ENSURE_TRUE(windowState, NS_ERROR_FAILURE);
    8364             : 
    8365             : #ifdef DEBUG_PAGE_CACHE
    8366             :   nsCOMPtr<nsIURI> uri;
    8367             :   mOSHE->GetURI(getter_AddRefs(uri));
    8368             :   nsAutoCString spec;
    8369             :   if (uri) {
    8370             :     uri->GetSpec(spec);
    8371             :   }
    8372             :   printf("Saving presentation into session history\n");
    8373             :   printf("  SH URI: %s\n", spec.get());
    8374             : #endif
    8375             : 
    8376           0 :   nsresult rv = mOSHE->SetWindowState(windowState);
    8377           0 :   NS_ENSURE_SUCCESS(rv, rv);
    8378             : 
    8379             :   // Suspend refresh URIs and save off the timer queue
    8380           0 :   rv = mOSHE->SetRefreshURIList(mSavedRefreshURIList);
    8381           0 :   NS_ENSURE_SUCCESS(rv, rv);
    8382             : 
    8383             :   // Capture the current content viewer bounds.
    8384           0 :   if (mContentViewer) {
    8385           0 :     nsIntRect bounds;
    8386           0 :     mContentViewer->GetBounds(bounds);
    8387           0 :     rv = mOSHE->SetViewerBounds(bounds);
    8388           0 :     NS_ENSURE_SUCCESS(rv, rv);
    8389             :   }
    8390             : 
    8391             :   // Capture the docshell hierarchy.
    8392           0 :   mOSHE->ClearChildShells();
    8393             : 
    8394           0 :   uint32_t childCount = mChildList.Length();
    8395           0 :   for (uint32_t i = 0; i < childCount; ++i) {
    8396           0 :     nsCOMPtr<nsIDocShellTreeItem> childShell = do_QueryInterface(ChildAt(i));
    8397           0 :     NS_ASSERTION(childShell, "null child shell");
    8398             : 
    8399           0 :     mOSHE->AddChildShell(childShell);
    8400             :   }
    8401             : 
    8402           0 :   return NS_OK;
    8403             : }
    8404             : 
    8405             : NS_IMETHODIMP
    8406           0 : nsDocShell::RestorePresentationEvent::Run()
    8407             : {
    8408           0 :   if (mDocShell && NS_FAILED(mDocShell->RestoreFromHistory())) {
    8409           0 :     NS_WARNING("RestoreFromHistory failed");
    8410             :   }
    8411           0 :   return NS_OK;
    8412             : }
    8413             : 
    8414             : NS_IMETHODIMP
    8415           0 : nsDocShell::BeginRestore(nsIContentViewer* aContentViewer, bool aTop)
    8416             : {
    8417             :   nsresult rv;
    8418           0 :   if (!aContentViewer) {
    8419           0 :     rv = EnsureContentViewer();
    8420           0 :     NS_ENSURE_SUCCESS(rv, rv);
    8421             : 
    8422           0 :     aContentViewer = mContentViewer;
    8423             :   }
    8424             : 
    8425             :   // Dispatch events for restoring the presentation.  We try to simulate
    8426             :   // the progress notifications loading the document would cause, so we add
    8427             :   // the document's channel to the loadgroup to initiate stateChange
    8428             :   // notifications.
    8429             : 
    8430           0 :   nsCOMPtr<nsIDOMDocument> domDoc;
    8431           0 :   aContentViewer->GetDOMDocument(getter_AddRefs(domDoc));
    8432           0 :   nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc);
    8433           0 :   if (doc) {
    8434           0 :     nsIChannel* channel = doc->GetChannel();
    8435           0 :     if (channel) {
    8436           0 :       mEODForCurrentDocument = false;
    8437           0 :       mIsRestoringDocument = true;
    8438           0 :       mLoadGroup->AddRequest(channel, nullptr);
    8439           0 :       mIsRestoringDocument = false;
    8440             :     }
    8441             :   }
    8442             : 
    8443           0 :   if (!aTop) {
    8444             :     // This point corresponds to us having gotten OnStartRequest or
    8445             :     // STATE_START, so do the same thing that CreateContentViewer does at
    8446             :     // this point to ensure that unload/pagehide events for this document
    8447             :     // will fire when it's unloaded again.
    8448           0 :     mFiredUnloadEvent = false;
    8449             : 
    8450             :     // For non-top frames, there is no notion of making sure that the
    8451             :     // previous document is in the domwindow when STATE_START notifications
    8452             :     // happen.  We can just call BeginRestore for all of the child shells
    8453             :     // now.
    8454           0 :     rv = BeginRestoreChildren();
    8455           0 :     NS_ENSURE_SUCCESS(rv, rv);
    8456             :   }
    8457             : 
    8458           0 :   return NS_OK;
    8459             : }
    8460             : 
    8461             : nsresult
    8462           0 : nsDocShell::BeginRestoreChildren()
    8463             : {
    8464           0 :   nsTObserverArray<nsDocLoader*>::ForwardIterator iter(mChildList);
    8465           0 :   while (iter.HasMore()) {
    8466           0 :     nsCOMPtr<nsIDocShell> child = do_QueryObject(iter.GetNext());
    8467           0 :     if (child) {
    8468           0 :       nsresult rv = child->BeginRestore(nullptr, false);
    8469           0 :       NS_ENSURE_SUCCESS(rv, rv);
    8470             :     }
    8471             :   }
    8472           0 :   return NS_OK;
    8473             : }
    8474             : 
    8475             : NS_IMETHODIMP
    8476           0 : nsDocShell::FinishRestore()
    8477             : {
    8478             :   // First we call finishRestore() on our children.  In the simulated load,
    8479             :   // all of the child frames finish loading before the main document.
    8480             : 
    8481           0 :   nsTObserverArray<nsDocLoader*>::ForwardIterator iter(mChildList);
    8482           0 :   while (iter.HasMore()) {
    8483           0 :     nsCOMPtr<nsIDocShell> child = do_QueryObject(iter.GetNext());
    8484           0 :     if (child) {
    8485           0 :       child->FinishRestore();
    8486             :     }
    8487             :   }
    8488             : 
    8489           0 :   if (mOSHE && mOSHE->HasDetachedEditor()) {
    8490           0 :     ReattachEditorToWindow(mOSHE);
    8491             :   }
    8492             : 
    8493           0 :   nsCOMPtr<nsIDocument> doc = GetDocument();
    8494           0 :   if (doc) {
    8495             :     // Finally, we remove the request from the loadgroup.  This will
    8496             :     // cause onStateChange(STATE_STOP) to fire, which will fire the
    8497             :     // pageshow event to the chrome.
    8498             : 
    8499           0 :     nsIChannel* channel = doc->GetChannel();
    8500           0 :     if (channel) {
    8501           0 :       mIsRestoringDocument = true;
    8502           0 :       mLoadGroup->RemoveRequest(channel, nullptr, NS_OK);
    8503           0 :       mIsRestoringDocument = false;
    8504             :     }
    8505             :   }
    8506             : 
    8507           0 :   return NS_OK;
    8508             : }
    8509             : 
    8510             : NS_IMETHODIMP
    8511          66 : nsDocShell::GetRestoringDocument(bool* aRestoring)
    8512             : {
    8513          66 :   *aRestoring = mIsRestoringDocument;
    8514          66 :   return NS_OK;
    8515             : }
    8516             : 
    8517             : nsresult
    8518           0 : nsDocShell::RestorePresentation(nsISHEntry* aSHEntry, bool* aRestoring)
    8519             : {
    8520           0 :   NS_ASSERTION(mLoadType & LOAD_CMD_HISTORY,
    8521             :                "RestorePresentation should only be called for history loads");
    8522             : 
    8523           0 :   nsCOMPtr<nsIContentViewer> viewer;
    8524           0 :   aSHEntry->GetContentViewer(getter_AddRefs(viewer));
    8525             : 
    8526             : #ifdef DEBUG_PAGE_CACHE
    8527             :   nsCOMPtr<nsIURI> uri;
    8528             :   aSHEntry->GetURI(getter_AddRefs(uri));
    8529             : 
    8530             :   nsAutoCString spec;
    8531             :   if (uri) {
    8532             :     uri->GetSpec(spec);
    8533             :   }
    8534             : #endif
    8535             : 
    8536           0 :   *aRestoring = false;
    8537             : 
    8538           0 :   if (!viewer) {
    8539             : #ifdef DEBUG_PAGE_CACHE
    8540             :     printf("no saved presentation for uri: %s\n", spec.get());
    8541             : #endif
    8542           0 :     return NS_OK;
    8543             :   }
    8544             : 
    8545             :   // We need to make sure the content viewer's container is this docshell.
    8546             :   // In subframe navigation, it's possible for the docshell that the
    8547             :   // content viewer was originally loaded into to be replaced with a
    8548             :   // different one.  We don't currently support restoring the presentation
    8549             :   // in that case.
    8550             : 
    8551           0 :   nsCOMPtr<nsIDocShell> container;
    8552           0 :   viewer->GetContainer(getter_AddRefs(container));
    8553           0 :   if (!::SameCOMIdentity(container, GetAsSupports(this))) {
    8554             : #ifdef DEBUG_PAGE_CACHE
    8555             :     printf("No valid container, clearing presentation\n");
    8556             : #endif
    8557           0 :     aSHEntry->SetContentViewer(nullptr);
    8558           0 :     return NS_ERROR_FAILURE;
    8559             :   }
    8560             : 
    8561           0 :   NS_ASSERTION(mContentViewer != viewer, "Restoring existing presentation");
    8562             : 
    8563             : #ifdef DEBUG_PAGE_CACHE
    8564             :   printf("restoring presentation from session history: %s\n", spec.get());
    8565             : #endif
    8566             : 
    8567           0 :   SetHistoryEntry(&mLSHE, aSHEntry);
    8568             : 
    8569             :   // Post an event that will remove the request after we've returned
    8570             :   // to the event loop.  This mimics the way it is called by nsIChannel
    8571             :   // implementations.
    8572             : 
    8573             :   // Revoke any pending restore (just in case)
    8574           0 :   NS_ASSERTION(!mRestorePresentationEvent.IsPending(),
    8575             :                "should only have one RestorePresentationEvent");
    8576           0 :   mRestorePresentationEvent.Revoke();
    8577             : 
    8578           0 :   RefPtr<RestorePresentationEvent> evt = new RestorePresentationEvent(this);
    8579           0 :   nsresult rv = DispatchToTabGroup("nsDocShell::RestorePresentationEvent",
    8580             :                                    TaskCategory::Other,
    8581           0 :                                    RefPtr<RestorePresentationEvent>(evt).forget());
    8582           0 :   if (NS_SUCCEEDED(rv)) {
    8583           0 :     mRestorePresentationEvent = evt.get();
    8584             :     // The rest of the restore processing will happen on our event
    8585             :     // callback.
    8586           0 :     *aRestoring = true;
    8587             :   }
    8588             : 
    8589           0 :   return rv;
    8590             : }
    8591             : 
    8592             : namespace {
    8593             : class MOZ_STACK_CLASS PresentationEventForgetter
    8594             : {
    8595             : public:
    8596           0 :   explicit PresentationEventForgetter(
    8597             :         nsRevocableEventPtr<nsDocShell::RestorePresentationEvent>&
    8598             :           aRestorePresentationEvent)
    8599           0 :     : mRestorePresentationEvent(aRestorePresentationEvent)
    8600           0 :     , mEvent(aRestorePresentationEvent.get())
    8601             :   {
    8602           0 :   }
    8603             : 
    8604           0 :   ~PresentationEventForgetter()
    8605           0 :   {
    8606           0 :     Forget();
    8607           0 :   }
    8608             : 
    8609           0 :   void Forget()
    8610             :   {
    8611           0 :     if (mRestorePresentationEvent.get() == mEvent) {
    8612           0 :       mRestorePresentationEvent.Forget();
    8613           0 :       mEvent = nullptr;
    8614             :     }
    8615           0 :   }
    8616             : 
    8617             : private:
    8618             :   nsRevocableEventPtr<nsDocShell::RestorePresentationEvent>&
    8619             :     mRestorePresentationEvent;
    8620             :   RefPtr<nsDocShell::RestorePresentationEvent> mEvent;
    8621             : };
    8622             : 
    8623             : } // namespace
    8624             : 
    8625             : nsresult
    8626           0 : nsDocShell::RestoreFromHistory()
    8627             : {
    8628           0 :   MOZ_ASSERT(mRestorePresentationEvent.IsPending());
    8629           0 :   PresentationEventForgetter forgetter(mRestorePresentationEvent);
    8630             : 
    8631             :   // This section of code follows the same ordering as CreateContentViewer.
    8632           0 :   if (!mLSHE) {
    8633           0 :     return NS_ERROR_FAILURE;
    8634             :   }
    8635             : 
    8636           0 :   nsCOMPtr<nsIContentViewer> viewer;
    8637           0 :   mLSHE->GetContentViewer(getter_AddRefs(viewer));
    8638           0 :   if (!viewer) {
    8639           0 :     return NS_ERROR_FAILURE;
    8640             :   }
    8641             : 
    8642           0 :   if (mSavingOldViewer) {
    8643             :     // We determined that it was safe to cache the document presentation
    8644             :     // at the time we initiated the new load.  We need to check whether
    8645             :     // it's still safe to do so, since there may have been DOM mutations
    8646             :     // or new requests initiated.
    8647           0 :     nsCOMPtr<nsIDOMDocument> domDoc;
    8648           0 :     viewer->GetDOMDocument(getter_AddRefs(domDoc));
    8649           0 :     nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc);
    8650           0 :     nsIRequest* request = nullptr;
    8651           0 :     if (doc) {
    8652           0 :       request = doc->GetChannel();
    8653             :     }
    8654           0 :     mSavingOldViewer = CanSavePresentation(mLoadType, request, doc);
    8655             :   }
    8656             : 
    8657           0 :   nsCOMPtr<nsIContentViewer> oldCv(mContentViewer);
    8658           0 :   nsCOMPtr<nsIContentViewer> newCv(viewer);
    8659           0 :   int32_t minFontSize = 0;
    8660           0 :   float textZoom = 1.0f;
    8661           0 :   float pageZoom = 1.0f;
    8662           0 :   float overrideDPPX = 0.0f;
    8663             : 
    8664           0 :   bool styleDisabled = false;
    8665           0 :   if (oldCv && newCv) {
    8666           0 :     oldCv->GetMinFontSize(&minFontSize);
    8667           0 :     oldCv->GetTextZoom(&textZoom);
    8668           0 :     oldCv->GetFullZoom(&pageZoom);
    8669           0 :     oldCv->GetOverrideDPPX(&overrideDPPX);
    8670           0 :     oldCv->GetAuthorStyleDisabled(&styleDisabled);
    8671             :   }
    8672             : 
    8673             :   // Protect against mLSHE going away via a load triggered from
    8674             :   // pagehide or unload.
    8675           0 :   nsCOMPtr<nsISHEntry> origLSHE = mLSHE;
    8676             : 
    8677             :   // Make sure to blow away our mLoadingURI just in case.  No loads
    8678             :   // from inside this pagehide.
    8679           0 :   mLoadingURI = nullptr;
    8680             : 
    8681             :   // Notify the old content viewer that it's being hidden.
    8682           0 :   FirePageHideNotification(!mSavingOldViewer);
    8683             : 
    8684             :   // If mLSHE was changed as a result of the pagehide event, then
    8685             :   // something else was loaded.  Don't finish restoring.
    8686           0 :   if (mLSHE != origLSHE) {
    8687           0 :     return NS_OK;
    8688             :   }
    8689             : 
    8690             :   // Add the request to our load group.  We do this before swapping out
    8691             :   // the content viewers so that consumers of STATE_START can access
    8692             :   // the old document.  We only deal with the toplevel load at this time --
    8693             :   // to be consistent with normal document loading, subframes cannot start
    8694             :   // loading until after data arrives, which is after STATE_START completes.
    8695             : 
    8696             :   RefPtr<RestorePresentationEvent> currentPresentationRestoration =
    8697           0 :     mRestorePresentationEvent.get();
    8698           0 :   Stop();
    8699             :   // Make sure we're still restoring the same presentation.
    8700             :   // If we aren't, docshell is in process doing another load already.
    8701           0 :   NS_ENSURE_STATE(currentPresentationRestoration ==
    8702             :                   mRestorePresentationEvent.get());
    8703           0 :   BeginRestore(viewer, true);
    8704           0 :   NS_ENSURE_STATE(currentPresentationRestoration ==
    8705             :                   mRestorePresentationEvent.get());
    8706           0 :   forgetter.Forget();
    8707             : 
    8708             :   // Set mFiredUnloadEvent = false so that the unload handler for the
    8709             :   // *new* document will fire.
    8710           0 :   mFiredUnloadEvent = false;
    8711             : 
    8712           0 :   mURIResultedInDocument = true;
    8713           0 :   nsCOMPtr<nsISHistory> rootSH;
    8714           0 :   GetRootSessionHistory(getter_AddRefs(rootSH));
    8715           0 :   if (rootSH) {
    8716           0 :     nsCOMPtr<nsISHistoryInternal> hist = do_QueryInterface(rootSH);
    8717           0 :     rootSH->GetIndex(&mPreviousTransIndex);
    8718           0 :     hist->UpdateIndex();
    8719           0 :     rootSH->GetIndex(&mLoadedTransIndex);
    8720             : #ifdef DEBUG_PAGE_CACHE
    8721             :     printf("Previous index: %d, Loaded index: %d\n\n", mPreviousTransIndex,
    8722             :            mLoadedTransIndex);
    8723             : #endif
    8724             :   }
    8725             : 
    8726             :   // Rather than call Embed(), we will retrieve the viewer from the session
    8727             :   // history entry and swap it in.
    8728             :   // XXX can we refactor this so that we can just call Embed()?
    8729           0 :   PersistLayoutHistoryState();
    8730             :   nsresult rv;
    8731           0 :   if (mContentViewer) {
    8732           0 :     if (mSavingOldViewer && NS_FAILED(CaptureState())) {
    8733           0 :       if (mOSHE) {
    8734           0 :         mOSHE->SyncPresentationState();
    8735             :       }
    8736           0 :       mSavingOldViewer = false;
    8737             :     }
    8738             :   }
    8739             : 
    8740           0 :   mSavedRefreshURIList = nullptr;
    8741             : 
    8742             :   // In cases where we use a transient about:blank viewer between loads,
    8743             :   // we never show the transient viewer, so _its_ previous viewer is never
    8744             :   // unhooked from the view hierarchy.  Destroy any such previous viewer now,
    8745             :   // before we grab the root view sibling, so that we don't grab a view
    8746             :   // that's about to go away.
    8747             : 
    8748           0 :   if (mContentViewer) {
    8749           0 :     nsCOMPtr<nsIContentViewer> previousViewer;
    8750           0 :     mContentViewer->GetPreviousViewer(getter_AddRefs(previousViewer));
    8751           0 :     if (previousViewer) {
    8752           0 :       mContentViewer->SetPreviousViewer(nullptr);
    8753           0 :       previousViewer->Destroy();
    8754             :     }
    8755             :   }
    8756             : 
    8757             :   // Save off the root view's parent and sibling so that we can insert the
    8758             :   // new content viewer's root view at the same position.  Also save the
    8759             :   // bounds of the root view's widget.
    8760             : 
    8761           0 :   nsView* rootViewSibling = nullptr;
    8762           0 :   nsView* rootViewParent = nullptr;
    8763           0 :   nsIntRect newBounds(0, 0, 0, 0);
    8764             : 
    8765           0 :   nsCOMPtr<nsIPresShell> oldPresShell = GetPresShell();
    8766           0 :   if (oldPresShell) {
    8767           0 :     nsViewManager* vm = oldPresShell->GetViewManager();
    8768           0 :     if (vm) {
    8769           0 :       nsView* oldRootView = vm->GetRootView();
    8770             : 
    8771           0 :       if (oldRootView) {
    8772           0 :         rootViewSibling = oldRootView->GetNextSibling();
    8773           0 :         rootViewParent = oldRootView->GetParent();
    8774             : 
    8775           0 :         mContentViewer->GetBounds(newBounds);
    8776             :       }
    8777             :     }
    8778             :   }
    8779             : 
    8780           0 :   nsCOMPtr<nsIContent> container;
    8781           0 :   nsCOMPtr<nsIDocument> sibling;
    8782           0 :   if (rootViewParent && rootViewParent->GetParent()) {
    8783           0 :     nsIFrame* frame = rootViewParent->GetParent()->GetFrame();
    8784           0 :     container = frame ? frame->GetContent() : nullptr;
    8785             :   }
    8786           0 :   if (rootViewSibling) {
    8787           0 :     nsIFrame* frame = rootViewSibling->GetFrame();
    8788             :     sibling =
    8789           0 :       frame ? frame->PresContext()->PresShell()->GetDocument() : nullptr;
    8790             :   }
    8791             : 
    8792             :   // Transfer ownership to mContentViewer.  By ensuring that either the
    8793             :   // docshell or the session history, but not both, have references to the
    8794             :   // content viewer, we prevent the viewer from being torn down after
    8795             :   // Destroy() is called.
    8796             : 
    8797           0 :   if (mContentViewer) {
    8798           0 :     mContentViewer->Close(mSavingOldViewer ? mOSHE.get() : nullptr);
    8799           0 :     viewer->SetPreviousViewer(mContentViewer);
    8800             :   }
    8801           0 :   if (mOSHE && (!mContentViewer || !mSavingOldViewer)) {
    8802             :     // We don't plan to save a viewer in mOSHE; tell it to drop
    8803             :     // any other state it's holding.
    8804           0 :     mOSHE->SyncPresentationState();
    8805             :   }
    8806             : 
    8807             :   // Order the mContentViewer setup just like Embed does.
    8808           0 :   mContentViewer = nullptr;
    8809             : 
    8810             :   // Now that we're about to switch documents, forget all of our children.
    8811             :   // Note that we cached them as needed up in CaptureState above.
    8812           0 :   DestroyChildren();
    8813             : 
    8814           0 :   mContentViewer.swap(viewer);
    8815             : 
    8816             :   // Grab all of the related presentation from the SHEntry now.
    8817             :   // Clearing the viewer from the SHEntry will clear all of this state.
    8818           0 :   nsCOMPtr<nsISupports> windowState;
    8819           0 :   mLSHE->GetWindowState(getter_AddRefs(windowState));
    8820           0 :   mLSHE->SetWindowState(nullptr);
    8821             : 
    8822             :   bool sticky;
    8823           0 :   mLSHE->GetSticky(&sticky);
    8824             : 
    8825           0 :   nsCOMPtr<nsIDOMDocument> domDoc;
    8826           0 :   mContentViewer->GetDOMDocument(getter_AddRefs(domDoc));
    8827             : 
    8828           0 :   nsCOMArray<nsIDocShellTreeItem> childShells;
    8829           0 :   int32_t i = 0;
    8830           0 :   nsCOMPtr<nsIDocShellTreeItem> child;
    8831           0 :   while (NS_SUCCEEDED(mLSHE->ChildShellAt(i++, getter_AddRefs(child))) &&
    8832           0 :          child) {
    8833           0 :     childShells.AppendObject(child);
    8834             :   }
    8835             : 
    8836             :   // get the previous content viewer size
    8837           0 :   nsIntRect oldBounds(0, 0, 0, 0);
    8838           0 :   mLSHE->GetViewerBounds(oldBounds);
    8839             : 
    8840             :   // Restore the refresh URI list.  The refresh timers will be restarted
    8841             :   // when EndPageLoad() is called.
    8842           0 :   nsCOMPtr<nsIMutableArray> refreshURIList;
    8843           0 :   mLSHE->GetRefreshURIList(getter_AddRefs(refreshURIList));
    8844             : 
    8845             :   // Reattach to the window object.
    8846           0 :   mIsRestoringDocument = true; // for MediaDocument::BecomeInteractive
    8847           0 :   rv = mContentViewer->Open(windowState, mLSHE);
    8848           0 :   mIsRestoringDocument = false;
    8849             : 
    8850             :   // Hack to keep nsDocShellEditorData alive across the
    8851             :   // SetContentViewer(nullptr) call below.
    8852           0 :   nsAutoPtr<nsDocShellEditorData> data(mLSHE->ForgetEditorData());
    8853             : 
    8854             :   // Now remove it from the cached presentation.
    8855           0 :   mLSHE->SetContentViewer(nullptr);
    8856           0 :   mEODForCurrentDocument = false;
    8857             : 
    8858           0 :   mLSHE->SetEditorData(data.forget());
    8859             : 
    8860             : #ifdef DEBUG
    8861             :   {
    8862           0 :     nsCOMPtr<nsIMutableArray> refreshURIs;
    8863           0 :     mLSHE->GetRefreshURIList(getter_AddRefs(refreshURIs));
    8864           0 :     nsCOMPtr<nsIDocShellTreeItem> childShell;
    8865           0 :     mLSHE->ChildShellAt(0, getter_AddRefs(childShell));
    8866           0 :     NS_ASSERTION(!refreshURIs && !childShell,
    8867             :                  "SHEntry should have cleared presentation state");
    8868             :   }
    8869             : #endif
    8870             : 
    8871             :   // Restore the sticky state of the viewer.  The viewer has set this state
    8872             :   // on the history entry in Destroy() just before marking itself non-sticky,
    8873             :   // to avoid teardown of the presentation.
    8874           0 :   mContentViewer->SetSticky(sticky);
    8875             : 
    8876           0 :   NS_ENSURE_SUCCESS(rv, rv);
    8877             : 
    8878             :   // mLSHE is now our currently-loaded document.
    8879           0 :   SetHistoryEntry(&mOSHE, mLSHE);
    8880             : 
    8881             :   // XXX special wyciwyg handling in Embed()?
    8882             : 
    8883             :   // We aren't going to restore any items from the LayoutHistoryState,
    8884             :   // but we don't want them to stay around in case the page is reloaded.
    8885           0 :   SetLayoutHistoryState(nullptr);
    8886             : 
    8887             :   // This is the end of our Embed() replacement
    8888             : 
    8889           0 :   mSavingOldViewer = false;
    8890           0 :   mEODForCurrentDocument = false;
    8891             : 
    8892             :   // Tell the event loop to favor plevents over user events, see comments
    8893             :   // in CreateContentViewer.
    8894           0 :   if (++gNumberOfDocumentsLoading == 1) {
    8895           0 :     FavorPerformanceHint(true);
    8896             :   }
    8897             : 
    8898           0 :   if (oldCv && newCv) {
    8899           0 :     newCv->SetMinFontSize(minFontSize);
    8900           0 :     newCv->SetTextZoom(textZoom);
    8901           0 :     newCv->SetFullZoom(pageZoom);
    8902           0 :     newCv->SetOverrideDPPX(overrideDPPX);
    8903           0 :     newCv->SetAuthorStyleDisabled(styleDisabled);
    8904             :   }
    8905             : 
    8906           0 :   nsCOMPtr<nsIDocument> document = do_QueryInterface(domDoc);
    8907           0 :   if (document) {
    8908           0 :     RefPtr<nsDocShell> parent = GetParentDocshell();
    8909           0 :     if (parent) {
    8910           0 :       nsCOMPtr<nsIDocument> d = parent->GetDocument();
    8911           0 :       if (d) {
    8912           0 :         if (d->EventHandlingSuppressed()) {
    8913           0 :           document->SuppressEventHandling(d->EventHandlingSuppressed());
    8914             :         }
    8915             :       }
    8916             :     }
    8917             : 
    8918             :     // Use the uri from the mLSHE we had when we entered this function
    8919             :     // (which need not match the document's URI if anchors are involved),
    8920             :     // since that's the history entry we're loading.  Note that if we use
    8921             :     // origLSHE we don't have to worry about whether the entry in question
    8922             :     // is still mLSHE or whether it's now mOSHE.
    8923           0 :     nsCOMPtr<nsIURI> uri;
    8924           0 :     origLSHE->GetURI(getter_AddRefs(uri));
    8925           0 :     SetCurrentURI(uri, document->GetChannel(), true, 0);
    8926             :   }
    8927             : 
    8928             :   // This is the end of our CreateContentViewer() replacement.
    8929             :   // Now we simulate a load.  First, we restore the state of the javascript
    8930             :   // window object.
    8931           0 :   nsCOMPtr<nsPIDOMWindowOuter> privWin = GetWindow();
    8932           0 :   NS_ASSERTION(privWin, "could not get nsPIDOMWindow interface");
    8933             : 
    8934             :   // Now, dispatch a title change event which would happen as the
    8935             :   // <head> is parsed.
    8936           0 :   document->NotifyPossibleTitleChange(false);
    8937             : 
    8938             :   // Now we simulate appending child docshells for subframes.
    8939           0 :   for (i = 0; i < childShells.Count(); ++i) {
    8940           0 :     nsIDocShellTreeItem* childItem = childShells.ObjectAt(i);
    8941           0 :     nsCOMPtr<nsIDocShell> childShell = do_QueryInterface(childItem);
    8942             : 
    8943             :     // Make sure to not clobber the state of the child.  Since AddChild
    8944             :     // always clobbers it, save it off first.
    8945             :     bool allowPlugins;
    8946           0 :     childShell->GetAllowPlugins(&allowPlugins);
    8947             : 
    8948             :     bool allowJavascript;
    8949           0 :     childShell->GetAllowJavascript(&allowJavascript);
    8950             : 
    8951             :     bool allowRedirects;
    8952           0 :     childShell->GetAllowMetaRedirects(&allowRedirects);
    8953             : 
    8954             :     bool allowSubframes;
    8955           0 :     childShell->GetAllowSubframes(&allowSubframes);
    8956             : 
    8957             :     bool allowImages;
    8958           0 :     childShell->GetAllowImages(&allowImages);
    8959             : 
    8960           0 :     bool allowMedia = childShell->GetAllowMedia();
    8961             : 
    8962             :     bool allowDNSPrefetch;
    8963           0 :     childShell->GetAllowDNSPrefetch(&allowDNSPrefetch);
    8964             : 
    8965           0 :     bool allowContentRetargeting = childShell->GetAllowContentRetargeting();
    8966             :     bool allowContentRetargetingOnChildren =
    8967           0 :       childShell->GetAllowContentRetargetingOnChildren();
    8968             : 
    8969             :     uint32_t defaultLoadFlags;
    8970           0 :     childShell->GetDefaultLoadFlags(&defaultLoadFlags);
    8971             : 
    8972             :     // this.AddChild(child) calls child.SetDocLoaderParent(this), meaning that
    8973             :     // the child inherits our state. Among other things, this means that the
    8974             :     // child inherits our mIsActive, mIsPrerendered and mPrivateBrowsingId,
    8975             :     // which is what we want.
    8976           0 :     AddChild(childItem);
    8977             : 
    8978           0 :     childShell->SetAllowPlugins(allowPlugins);
    8979           0 :     childShell->SetAllowJavascript(allowJavascript);
    8980           0 :     childShell->SetAllowMetaRedirects(allowRedirects);
    8981           0 :     childShell->SetAllowSubframes(allowSubframes);
    8982           0 :     childShell->SetAllowImages(allowImages);
    8983           0 :     childShell->SetAllowMedia(allowMedia);
    8984           0 :     childShell->SetAllowDNSPrefetch(allowDNSPrefetch);
    8985           0 :     childShell->SetAllowContentRetargeting(allowContentRetargeting);
    8986           0 :     childShell->SetAllowContentRetargetingOnChildren(
    8987           0 :       allowContentRetargetingOnChildren);
    8988           0 :     childShell->SetDefaultLoadFlags(defaultLoadFlags);
    8989             : 
    8990           0 :     rv = childShell->BeginRestore(nullptr, false);
    8991           0 :     NS_ENSURE_SUCCESS(rv, rv);
    8992             :   }
    8993             : 
    8994             :   // Make sure to restore the window state after adding the child shells back
    8995             :   // to the tree.  This is necessary for Thaw() and Resume() to propagate
    8996             :   // properly.
    8997           0 :   rv = privWin->RestoreWindowState(windowState);
    8998           0 :   NS_ENSURE_SUCCESS(rv, rv);
    8999             : 
    9000           0 :   nsCOMPtr<nsIPresShell> shell = GetPresShell();
    9001             : 
    9002             :   // We may be displayed on a different monitor (or in a different
    9003             :   // HiDPI mode) than when we got into the history list.  So we need
    9004             :   // to check if this has happened. See bug 838239.
    9005             : 
    9006             :   // Because the prescontext normally handles resolution changes via
    9007             :   // a runnable (see nsPresContext::UIResolutionChanged), its device
    9008             :   // context won't be -immediately- updated as a result of calling
    9009             :   // shell->BackingScaleFactorChanged().
    9010             : 
    9011             :   // But we depend on that device context when adjusting the view size
    9012             :   // via mContentViewer->SetBounds(newBounds) below. So we need to
    9013             :   // explicitly tell it to check for changed resolution here.
    9014           0 :   if (shell && shell->GetPresContext()->DeviceContext()->CheckDPIChange()) {
    9015           0 :     shell->BackingScaleFactorChanged();
    9016             :   }
    9017             : 
    9018           0 :   nsViewManager* newVM = shell ? shell->GetViewManager() : nullptr;
    9019           0 :   nsView* newRootView = newVM ? newVM->GetRootView() : nullptr;
    9020             : 
    9021             :   // Insert the new root view at the correct location in the view tree.
    9022           0 :   if (container) {
    9023             :     nsSubDocumentFrame* subDocFrame =
    9024           0 :       do_QueryFrame(container->GetPrimaryFrame());
    9025           0 :     rootViewParent = subDocFrame ? subDocFrame->EnsureInnerView() : nullptr;
    9026             :   } else {
    9027           0 :     rootViewParent = nullptr;
    9028             :   }
    9029           0 :   if (sibling &&
    9030           0 :       sibling->GetShell() &&
    9031           0 :       sibling->GetShell()->GetViewManager()) {
    9032           0 :     rootViewSibling = sibling->GetShell()->GetViewManager()->GetRootView();
    9033             :   } else {
    9034           0 :     rootViewSibling = nullptr;
    9035             :   }
    9036           0 :   if (rootViewParent && newRootView &&
    9037           0 :       newRootView->GetParent() != rootViewParent) {
    9038           0 :     nsViewManager* parentVM = rootViewParent->GetViewManager();
    9039           0 :     if (parentVM) {
    9040             :       // InsertChild(parent, child, sib, true) inserts the child after
    9041             :       // sib in content order, which is before sib in view order. BUT
    9042             :       // when sib is null it inserts at the end of the the document
    9043             :       // order, i.e., first in view order.  But when oldRootSibling is
    9044             :       // null, the old root as at the end of the view list --- last in
    9045             :       // content order --- and we want to call InsertChild(parent, child,
    9046             :       // nullptr, false) in that case.
    9047           0 :       parentVM->InsertChild(rootViewParent, newRootView,
    9048             :                             rootViewSibling,
    9049           0 :                             rootViewSibling ? true : false);
    9050             : 
    9051           0 :       NS_ASSERTION(newRootView->GetNextSibling() == rootViewSibling,
    9052             :                    "error in InsertChild");
    9053             :     }
    9054             :   }
    9055             : 
    9056           0 :   nsCOMPtr<nsPIDOMWindowInner> privWinInner = privWin->GetCurrentInnerWindow();
    9057             : 
    9058             :   // If parent is suspended, increase suspension count.
    9059             :   // This can't be done as early as event suppression since this
    9060             :   // depends on docshell tree.
    9061           0 :   privWinInner->SyncStateFromParentWindow();
    9062             : 
    9063             :   // Now that all of the child docshells have been put into place, we can
    9064             :   // restart the timers for the window and all of the child frames.
    9065           0 :   privWinInner->Resume();
    9066             : 
    9067             :   // Restore the refresh URI list.  The refresh timers will be restarted
    9068             :   // when EndPageLoad() is called.
    9069           0 :   mRefreshURIList = refreshURIList;
    9070             : 
    9071             :   // Meta-refresh timers have been restarted for this shell, but not
    9072             :   // for our children.  Walk the child shells and restart their timers.
    9073           0 :   nsTObserverArray<nsDocLoader*>::ForwardIterator iter(mChildList);
    9074           0 :   while (iter.HasMore()) {
    9075           0 :     nsCOMPtr<nsIDocShell> child = do_QueryObject(iter.GetNext());
    9076           0 :     if (child) {
    9077           0 :       child->ResumeRefreshURIs();
    9078             :     }
    9079             :   }
    9080             : 
    9081             :   // Make sure this presentation is the same size as the previous
    9082             :   // presentation.  If this is not the same size we showed it at last time,
    9083             :   // then we need to resize the widget.
    9084             : 
    9085             :   // XXXbryner   This interacts poorly with Firefox's infobar.  If the old
    9086             :   // presentation had the infobar visible, then we will resize the new
    9087             :   // presentation to that smaller size.  However, firing the locationchanged
    9088             :   // event will hide the infobar, which will immediately resize the window
    9089             :   // back to the larger size.  A future optimization might be to restore
    9090             :   // the presentation at the "wrong" size, then fire the locationchanged
    9091             :   // event and check whether the docshell's new size is the same as the
    9092             :   // cached viewer size (skipping the resize if they are equal).
    9093             : 
    9094           0 :   if (newRootView) {
    9095           0 :     if (!newBounds.IsEmpty() && !newBounds.IsEqualEdges(oldBounds)) {
    9096             : #ifdef DEBUG_PAGE_CACHE
    9097             :       printf("resize widget(%d, %d, %d, %d)\n", newBounds.x,
    9098             :              newBounds.y, newBounds.width, newBounds.height);
    9099             : #endif
    9100           0 :       mContentViewer->SetBounds(newBounds);
    9101             :     } else {
    9102             :       nsIScrollableFrame* rootScrollFrame =
    9103           0 :         shell->GetRootScrollFrameAsScrollableExternal();
    9104           0 :       if (rootScrollFrame) {
    9105           0 :         rootScrollFrame->PostScrolledAreaEventForCurrentArea();
    9106             :       }
    9107             :     }
    9108             :   }
    9109             : 
    9110             :   // The FinishRestore call below can kill these, null them out so we don't
    9111             :   // have invalid pointer lying around.
    9112           0 :   newRootView = rootViewSibling = rootViewParent = nullptr;
    9113           0 :   newVM = nullptr;
    9114             : 
    9115             :   // Simulate the completion of the load.
    9116           0 :   nsDocShell::FinishRestore();
    9117             : 
    9118             :   // Restart plugins, and paint the content.
    9119           0 :   if (shell) {
    9120           0 :     shell->Thaw();
    9121             :   }
    9122             : 
    9123           0 :   return privWin->FireDelayedDOMEvents();
    9124             : }
    9125             : 
    9126             : nsresult
    9127           4 : nsDocShell::CreateContentViewer(const nsACString& aContentType,
    9128             :                                 nsIRequest* aRequest,
    9129             :                                 nsIStreamListener** aContentHandler)
    9130             : {
    9131           4 :   *aContentHandler = nullptr;
    9132             : 
    9133           4 :   if (!mTreeOwner) {
    9134             :     // If we don't have a tree owner, then we're in the process of being
    9135             :     // destroyed. Rather than continue trying to load something, just give up.
    9136           0 :     return NS_ERROR_DOCSHELL_DYING;
    9137             :   }
    9138             : 
    9139             :   // Can we check the content type of the current content viewer
    9140             :   // and reuse it without destroying it and re-creating it?
    9141             : 
    9142           4 :   NS_ASSERTION(mLoadGroup, "Someone ignored return from Init()?");
    9143             : 
    9144             :   // Instantiate the content viewer object
    9145           8 :   nsCOMPtr<nsIContentViewer> viewer;
    9146           4 :   nsresult rv = NewContentViewerObj(aContentType, aRequest, mLoadGroup,
    9147           8 :                                     aContentHandler, getter_AddRefs(viewer));
    9148             : 
    9149           4 :   if (NS_FAILED(rv)) {
    9150           0 :     return rv;
    9151             :   }
    9152             : 
    9153             :   // Notify the current document that it is about to be unloaded!!
    9154             :   //
    9155             :   // It is important to fire the unload() notification *before* any state
    9156             :   // is changed within the DocShell - otherwise, javascript will get the
    9157             :   // wrong information :-(
    9158             :   //
    9159             : 
    9160           4 :   if (mSavingOldViewer) {
    9161             :     // We determined that it was safe to cache the document presentation
    9162             :     // at the time we initiated the new load.  We need to check whether
    9163             :     // it's still safe to do so, since there may have been DOM mutations
    9164             :     // or new requests initiated.
    9165           0 :     nsCOMPtr<nsIDOMDocument> domDoc;
    9166           0 :     viewer->GetDOMDocument(getter_AddRefs(domDoc));
    9167           0 :     nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc);
    9168           0 :     mSavingOldViewer = CanSavePresentation(mLoadType, aRequest, doc);
    9169             :   }
    9170             : 
    9171           4 :   NS_ASSERTION(!mLoadingURI, "Re-entering unload?");
    9172             : 
    9173           8 :   nsCOMPtr<nsIChannel> aOpenedChannel = do_QueryInterface(aRequest);
    9174           4 :   if (aOpenedChannel) {
    9175           4 :     aOpenedChannel->GetURI(getter_AddRefs(mLoadingURI));
    9176             :   }
    9177           4 :   FirePageHideNotification(!mSavingOldViewer);
    9178           4 :   mLoadingURI = nullptr;
    9179             : 
    9180             :   // Set mFiredUnloadEvent = false so that the unload handler for the
    9181             :   // *new* document will fire.
    9182           4 :   mFiredUnloadEvent = false;
    9183             : 
    9184             :   // we've created a new document so go ahead and call
    9185             :   // OnLoadingSite(), but don't fire OnLocationChange()
    9186             :   // notifications before we've called Embed(). See bug 284993.
    9187           4 :   mURIResultedInDocument = true;
    9188             : 
    9189           4 :   if (mLoadType == LOAD_ERROR_PAGE) {
    9190             :     // We need to set the SH entry and our current URI here and not
    9191             :     // at the moment we load the page. We want the same behavior
    9192             :     // of Stop() as for a normal page load. See bug 514232 for details.
    9193             : 
    9194             :     // Revert mLoadType to load type to state the page load failed,
    9195             :     // following function calls need it.
    9196           0 :     mLoadType = mFailedLoadType;
    9197             : 
    9198           0 :     nsCOMPtr<nsIChannel> failedChannel = mFailedChannel;
    9199             : 
    9200           0 :     nsIDocument* doc = viewer->GetDocument();
    9201           0 :     if (doc) {
    9202           0 :       doc->SetFailedChannel(failedChannel);
    9203             :     }
    9204             : 
    9205             :     // Make sure we have a URI to set currentURI.
    9206           0 :     nsCOMPtr<nsIURI> failedURI;
    9207           0 :     nsCOMPtr<nsIPrincipal> triggeringPrincipal;
    9208           0 :     if (failedChannel) {
    9209           0 :       NS_GetFinalChannelURI(failedChannel, getter_AddRefs(failedURI));
    9210             :     }
    9211             :      else {
    9212             :        // if there is no failed channel we have to explicitly provide
    9213             :        // a triggeringPrincipal for the history entry.
    9214           0 :        triggeringPrincipal = nsContentUtils::GetSystemPrincipal();
    9215             :     }
    9216             : 
    9217           0 :     if (!failedURI) {
    9218           0 :       failedURI = mFailedURI;
    9219             :     }
    9220           0 :     if (!failedURI) {
    9221             :       // We need a URI object to store a session history entry, so make up a URI
    9222           0 :       NS_NewURI(getter_AddRefs(failedURI), "about:blank");
    9223             :     }
    9224             : 
    9225             :     // When we don't have failedURI, something wrong will happen. See
    9226             :     // bug 291876.
    9227           0 :     MOZ_ASSERT(failedURI, "We don't have a URI for history APIs.");
    9228             : 
    9229           0 :     mFailedChannel = nullptr;
    9230           0 :     mFailedURI = nullptr;
    9231             : 
    9232             :     // Create an shistory entry for the old load.
    9233           0 :     if (failedURI) {
    9234           0 :       bool errorOnLocationChangeNeeded = OnNewURI(
    9235             :         failedURI, failedChannel, triggeringPrincipal,
    9236           0 :         nullptr, mLoadType, false, false, false);
    9237             : 
    9238           0 :       if (errorOnLocationChangeNeeded) {
    9239           0 :         FireOnLocationChange(this, failedChannel, failedURI,
    9240           0 :                              LOCATION_CHANGE_ERROR_PAGE);
    9241             :       }
    9242             :     }
    9243             : 
    9244             :     // Be sure to have a correct mLSHE, it may have been cleared by
    9245             :     // EndPageLoad. See bug 302115.
    9246           0 :     if (mSessionHistory && !mLSHE) {
    9247             :       int32_t idx;
    9248           0 :       mSessionHistory->GetRequestedIndex(&idx);
    9249           0 :       if (idx == -1) {
    9250           0 :         mSessionHistory->GetIndex(&idx);
    9251             :       }
    9252           0 :       mSessionHistory->GetEntryAtIndex(idx, false, getter_AddRefs(mLSHE));
    9253             :     }
    9254             : 
    9255           0 :     mLoadType = LOAD_ERROR_PAGE;
    9256             :   }
    9257             : 
    9258           4 :   bool onLocationChangeNeeded = OnLoadingSite(aOpenedChannel, false);
    9259             : 
    9260             :   // let's try resetting the load group if we need to...
    9261           8 :   nsCOMPtr<nsILoadGroup> currentLoadGroup;
    9262           4 :   NS_ENSURE_SUCCESS(
    9263             :     aOpenedChannel->GetLoadGroup(getter_AddRefs(currentLoadGroup)),
    9264             :     NS_ERROR_FAILURE);
    9265             : 
    9266           4 :   if (currentLoadGroup != mLoadGroup) {
    9267           0 :     nsLoadFlags loadFlags = 0;
    9268             : 
    9269             :     // Cancel any URIs that are currently loading...
    9270             :     // XXX: Need to do this eventually      Stop();
    9271             :     //
    9272             :     // Retarget the document to this loadgroup...
    9273             :     //
    9274             :     /* First attach the channel to the right loadgroup
    9275             :      * and then remove from the old loadgroup. This
    9276             :      * puts the notifications in the right order and
    9277             :      * we don't null-out mLSHE in OnStateChange() for
    9278             :      * all redirected urls
    9279             :      */
    9280           0 :     aOpenedChannel->SetLoadGroup(mLoadGroup);
    9281             : 
    9282             :     // Mark the channel as being a document URI...
    9283           0 :     aOpenedChannel->GetLoadFlags(&loadFlags);
    9284           0 :     loadFlags |= nsIChannel::LOAD_DOCUMENT_URI;
    9285             : 
    9286           0 :     aOpenedChannel->SetLoadFlags(loadFlags);
    9287             : 
    9288           0 :     mLoadGroup->AddRequest(aRequest, nullptr);
    9289           0 :     if (currentLoadGroup) {
    9290           0 :       currentLoadGroup->RemoveRequest(aRequest, nullptr, NS_BINDING_RETARGETED);
    9291             :     }
    9292             : 
    9293             :     // Update the notification callbacks, so that progress and
    9294             :     // status information are sent to the right docshell...
    9295           0 :     aOpenedChannel->SetNotificationCallbacks(this);
    9296             :   }
    9297             : 
    9298           4 :   NS_ENSURE_SUCCESS(Embed(viewer, "", nullptr), NS_ERROR_FAILURE);
    9299             : 
    9300           4 :   mSavedRefreshURIList = nullptr;
    9301           4 :   mSavingOldViewer = false;
    9302           4 :   mEODForCurrentDocument = false;
    9303             : 
    9304             :   // if this document is part of a multipart document,
    9305             :   // the ID can be used to distinguish it from the other parts.
    9306           8 :   nsCOMPtr<nsIMultiPartChannel> multiPartChannel(do_QueryInterface(aRequest));
    9307           4 :   if (multiPartChannel) {
    9308           0 :     nsCOMPtr<nsIPresShell> shell = GetPresShell();
    9309           0 :     if (NS_SUCCEEDED(rv) && shell) {
    9310           0 :       nsIDocument* doc = shell->GetDocument();
    9311           0 :       if (doc) {
    9312             :         uint32_t partID;
    9313           0 :         multiPartChannel->GetPartID(&partID);
    9314           0 :         doc->SetPartID(partID);
    9315             :       }
    9316             :     }
    9317             :   }
    9318             : 
    9319             :   // Give hint to native plevent dispatch mechanism. If a document
    9320             :   // is loading the native plevent dispatch mechanism should favor
    9321             :   // performance over normal native event dispatch priorities.
    9322           4 :   if (++gNumberOfDocumentsLoading == 1) {
    9323             :     // Hint to favor performance for the plevent notification mechanism.
    9324             :     // We want the pages to load as fast as possible even if its means
    9325             :     // native messages might be starved.
    9326           2 :     FavorPerformanceHint(true);
    9327             :   }
    9328             : 
    9329           4 :   if (onLocationChangeNeeded) {
    9330           3 :     FireOnLocationChange(this, aRequest, mCurrentURI, 0);
    9331             :   }
    9332             : 
    9333           4 :   return NS_OK;
    9334             : }
    9335             : 
    9336             : nsresult
    9337           4 : nsDocShell::NewContentViewerObj(const nsACString& aContentType,
    9338             :                                 nsIRequest* aRequest, nsILoadGroup* aLoadGroup,
    9339             :                                 nsIStreamListener** aContentHandler,
    9340             :                                 nsIContentViewer** aViewer)
    9341             : {
    9342           8 :   nsCOMPtr<nsIChannel> aOpenedChannel = do_QueryInterface(aRequest);
    9343             : 
    9344             :   nsCOMPtr<nsIDocumentLoaderFactory> docLoaderFactory =
    9345           8 :     nsContentUtils::FindInternalContentViewer(aContentType);
    9346           4 :   if (!docLoaderFactory) {
    9347           0 :     return NS_ERROR_FAILURE;
    9348             :   }
    9349             : 
    9350             :   // Now create an instance of the content viewer nsLayoutDLF makes the
    9351             :   // determination if it should be a "view-source" instead of "view"
    9352           8 :   nsresult rv = docLoaderFactory->CreateInstance("view",
    9353             :                                                  aOpenedChannel,
    9354             :                                                  aLoadGroup, aContentType,
    9355             :                                                  this,
    9356             :                                                  nullptr,
    9357             :                                                  aContentHandler,
    9358           8 :                                                  aViewer);
    9359           4 :   NS_ENSURE_SUCCESS(rv, rv);
    9360             : 
    9361           4 :   (*aViewer)->SetContainer(this);
    9362           4 :   return NS_OK;
    9363             : }
    9364             : 
    9365             : nsresult
    9366           8 : nsDocShell::SetupNewViewer(nsIContentViewer* aNewViewer)
    9367             : {
    9368             :   //
    9369             :   // Copy content viewer state from previous or parent content viewer.
    9370             :   //
    9371             :   // The following logic is mirrored in nsHTMLDocument::StartDocumentLoad!
    9372             :   //
    9373             :   // Do NOT to maintain a reference to the old content viewer outside
    9374             :   // of this "copying" block, or it will not be destroyed until the end of
    9375             :   // this routine and all <SCRIPT>s and event handlers fail! (bug 20315)
    9376             :   //
    9377             :   // In this block of code, if we get an error result, we return it
    9378             :   // but if we get a null pointer, that's perfectly legal for parent
    9379             :   // and parentContentViewer.
    9380             :   //
    9381             : 
    9382           8 :   int32_t x = 0;
    9383           8 :   int32_t y = 0;
    9384           8 :   int32_t cx = 0;
    9385           8 :   int32_t cy = 0;
    9386             : 
    9387             :   // This will get the size from the current content viewer or from the
    9388             :   // Init settings
    9389           8 :   DoGetPositionAndSize(&x, &y, &cx, &cy);
    9390             : 
    9391          16 :   nsCOMPtr<nsIDocShellTreeItem> parentAsItem;
    9392           8 :   NS_ENSURE_SUCCESS(GetSameTypeParent(getter_AddRefs(parentAsItem)),
    9393             :                     NS_ERROR_FAILURE);
    9394          16 :   nsCOMPtr<nsIDocShell> parent(do_QueryInterface(parentAsItem));
    9395             : 
    9396           8 :   const Encoding* forceCharset = nullptr;
    9397           8 :   const Encoding* hintCharset = nullptr;
    9398             :   int32_t hintCharsetSource;
    9399             :   int32_t minFontSize;
    9400             :   float textZoom;
    9401             :   float pageZoom;
    9402             :   float overrideDPPX;
    9403             :   bool styleDisabled;
    9404             :   // |newMUDV| also serves as a flag to set the data from the above vars
    9405          16 :   nsCOMPtr<nsIContentViewer> newCv;
    9406             : 
    9407           8 :   if (mContentViewer || parent) {
    9408           8 :     nsCOMPtr<nsIContentViewer> oldCv;
    9409           4 :     if (mContentViewer) {
    9410             :       // Get any interesting state from old content viewer
    9411             :       // XXX: it would be far better to just reuse the document viewer ,
    9412             :       //      since we know we're just displaying the same document as before
    9413           3 :       oldCv = mContentViewer;
    9414             : 
    9415             :       // Tell the old content viewer to hibernate in session history when
    9416             :       // it is destroyed.
    9417             : 
    9418           3 :       if (mSavingOldViewer && NS_FAILED(CaptureState())) {
    9419           0 :         if (mOSHE) {
    9420           0 :           mOSHE->SyncPresentationState();
    9421             :         }
    9422           0 :         mSavingOldViewer = false;
    9423             :       }
    9424             :     } else {
    9425             :       // No old content viewer, so get state from parent's content viewer
    9426           1 :       parent->GetContentViewer(getter_AddRefs(oldCv));
    9427             :     }
    9428             : 
    9429           4 :     if (oldCv) {
    9430           4 :       newCv = aNewViewer;
    9431           4 :       if (newCv) {
    9432           4 :         forceCharset = oldCv->GetForceCharset();
    9433           4 :         hintCharset = oldCv->GetHintCharset();
    9434           4 :         NS_ENSURE_SUCCESS(oldCv->GetHintCharacterSetSource(&hintCharsetSource),
    9435             :                           NS_ERROR_FAILURE);
    9436           4 :         NS_ENSURE_SUCCESS(oldCv->GetMinFontSize(&minFontSize),
    9437             :                           NS_ERROR_FAILURE);
    9438           4 :         NS_ENSURE_SUCCESS(oldCv->GetTextZoom(&textZoom),
    9439             :                           NS_ERROR_FAILURE);
    9440           4 :         NS_ENSURE_SUCCESS(oldCv->GetFullZoom(&pageZoom),
    9441             :                           NS_ERROR_FAILURE);
    9442           4 :         NS_ENSURE_SUCCESS(oldCv->GetOverrideDPPX(&overrideDPPX),
    9443             :                           NS_ERROR_FAILURE);
    9444           4 :         NS_ENSURE_SUCCESS(oldCv->GetAuthorStyleDisabled(&styleDisabled),
    9445             :                           NS_ERROR_FAILURE);
    9446             :       }
    9447             :     }
    9448             :   }
    9449             : 
    9450           8 :   nscolor bgcolor = NS_RGBA(0, 0, 0, 0);
    9451             :   // Ensure that the content viewer is destroyed *after* the GC - bug 71515
    9452          16 :   nsCOMPtr<nsIContentViewer> contentViewer = mContentViewer;
    9453           8 :   if (contentViewer) {
    9454             :     // Stop any activity that may be happening in the old document before
    9455             :     // releasing it...
    9456           3 :     contentViewer->Stop();
    9457             : 
    9458             :     // Try to extract the canvas background color from the old
    9459             :     // presentation shell, so we can use it for the next document.
    9460           6 :     nsCOMPtr<nsIPresShell> shell;
    9461           3 :     contentViewer->GetPresShell(getter_AddRefs(shell));
    9462             : 
    9463           3 :     if (shell) {
    9464           3 :       bgcolor = shell->GetCanvasBackground();
    9465             :     }
    9466             : 
    9467           3 :     contentViewer->Close(mSavingOldViewer ? mOSHE.get() : nullptr);
    9468           3 :     aNewViewer->SetPreviousViewer(contentViewer);
    9469             :   }
    9470           8 :   if (mOSHE && (!mContentViewer || !mSavingOldViewer)) {
    9471             :     // We don't plan to save a viewer in mOSHE; tell it to drop
    9472             :     // any other state it's holding.
    9473           0 :     mOSHE->SyncPresentationState();
    9474             :   }
    9475             : 
    9476           8 :   mContentViewer = nullptr;
    9477             : 
    9478             :   // Now that we're about to switch documents, forget all of our children.
    9479             :   // Note that we cached them as needed up in CaptureState above.
    9480           8 :   DestroyChildren();
    9481             : 
    9482           8 :   mContentViewer = aNewViewer;
    9483             : 
    9484          16 :   nsCOMPtr<nsIWidget> widget;
    9485           8 :   NS_ENSURE_SUCCESS(GetMainWidget(getter_AddRefs(widget)), NS_ERROR_FAILURE);
    9486             : 
    9487           8 :   nsIntRect bounds(x, y, cx, cy);
    9488             : 
    9489           8 :   mContentViewer->SetNavigationTiming(mTiming);
    9490             : 
    9491           8 :   if (NS_FAILED(mContentViewer->Init(widget, bounds))) {
    9492           0 :     mContentViewer = nullptr;
    9493           0 :     NS_WARNING("ContentViewer Initialization failed");
    9494           0 :     return NS_ERROR_FAILURE;
    9495             :   }
    9496             : 
    9497             :   // If we have old state to copy, set the old state onto the new content
    9498             :   // viewer
    9499           8 :   if (newCv) {
    9500           4 :     newCv->SetForceCharset(forceCharset);
    9501           4 :     newCv->SetHintCharset(hintCharset);
    9502           4 :     NS_ENSURE_SUCCESS(newCv->SetHintCharacterSetSource(hintCharsetSource),
    9503             :                       NS_ERROR_FAILURE);
    9504           4 :     NS_ENSURE_SUCCESS(newCv->SetMinFontSize(minFontSize),
    9505             :                       NS_ERROR_FAILURE);
    9506           4 :     NS_ENSURE_SUCCESS(newCv->SetTextZoom(textZoom),
    9507             :                       NS_ERROR_FAILURE);
    9508           4 :     NS_ENSURE_SUCCESS(newCv->SetFullZoom(pageZoom),
    9509             :                       NS_ERROR_FAILURE);
    9510           4 :     NS_ENSURE_SUCCESS(newCv->SetOverrideDPPX(overrideDPPX),
    9511             :                       NS_ERROR_FAILURE);
    9512           4 :     NS_ENSURE_SUCCESS(newCv->SetAuthorStyleDisabled(styleDisabled),
    9513             :                       NS_ERROR_FAILURE);
    9514             :   }
    9515             : 
    9516             :   // Stuff the bgcolor from the old pres shell into the new
    9517             :   // pres shell. This improves page load continuity.
    9518          16 :   nsCOMPtr<nsIPresShell> shell;
    9519           8 :   mContentViewer->GetPresShell(getter_AddRefs(shell));
    9520             : 
    9521           8 :   if (shell) {
    9522           7 :     shell->SetCanvasBackground(bgcolor);
    9523             :   }
    9524             : 
    9525             :   // XXX: It looks like the LayoutState gets restored again in Embed()
    9526             :   //      right after the call to SetupNewViewer(...)
    9527             : 
    9528             :   // We don't show the mContentViewer yet, since we want to draw the old page
    9529             :   // until we have enough of the new page to show.  Just return with the new
    9530             :   // viewer still set to hidden.
    9531             : 
    9532           8 :   return NS_OK;
    9533             : }
    9534             : 
    9535             : nsresult
    9536           1 : nsDocShell::SetDocCurrentStateObj(nsISHEntry* aShEntry)
    9537             : {
    9538           1 :   NS_ENSURE_STATE(mContentViewer);
    9539           2 :   nsCOMPtr<nsIDocument> document = GetDocument();
    9540           1 :   NS_ENSURE_TRUE(document, NS_ERROR_FAILURE);
    9541             : 
    9542           2 :   nsCOMPtr<nsIStructuredCloneContainer> scContainer;
    9543           1 :   if (aShEntry) {
    9544           1 :     nsresult rv = aShEntry->GetStateData(getter_AddRefs(scContainer));
    9545           1 :     NS_ENSURE_SUCCESS(rv, rv);
    9546             : 
    9547             :     // If aShEntry is null, just set the document's state object to null.
    9548             :   }
    9549             : 
    9550             :   // It's OK for scContainer too be null here; that just means there's no
    9551             :   // state data associated with this history entry.
    9552           1 :   document->SetStateObject(scContainer);
    9553             : 
    9554           1 :   return NS_OK;
    9555             : }
    9556             : 
    9557             : nsresult
    9558           6 : nsDocShell::CheckLoadingPermissions()
    9559             : {
    9560             :   // This method checks whether the caller may load content into
    9561             :   // this docshell. Even though we've done our best to hide windows
    9562             :   // from code that doesn't have the right to access them, it's
    9563             :   // still possible for an evil site to open a window and access
    9564             :   // frames in the new window through window.frames[] (which is
    9565             :   // allAccess for historic reasons), so we still need to do this
    9566             :   // check on load.
    9567           6 :   nsresult rv = NS_OK;
    9568             : 
    9569           6 :   if (!gValidateOrigin || !IsFrame()) {
    9570             :     // Origin validation was turned off, or we're not a frame.
    9571             :     // Permit all loads.
    9572             : 
    9573           5 :     return rv;
    9574             :   }
    9575             : 
    9576             :   // Note - The check for a current JSContext here isn't necessarily sensical.
    9577             :   // It's just designed to preserve the old semantics during a mass-conversion
    9578             :   // patch.
    9579           1 :   if (!nsContentUtils::GetCurrentJSContext()) {
    9580           1 :     return NS_OK;
    9581             :   }
    9582             : 
    9583             :   // Check if the caller is from the same origin as this docshell,
    9584             :   // or any of its ancestors.
    9585           0 :   nsCOMPtr<nsIDocShellTreeItem> item(this);
    9586           0 :   do {
    9587           0 :     nsCOMPtr<nsIScriptGlobalObject> sgo = do_GetInterface(item);
    9588           0 :     nsCOMPtr<nsIScriptObjectPrincipal> sop(do_QueryInterface(sgo));
    9589             : 
    9590             :     nsIPrincipal* p;
    9591           0 :     if (!sop || !(p = sop->GetPrincipal())) {
    9592           0 :       return NS_ERROR_UNEXPECTED;
    9593             :     }
    9594             : 
    9595           0 :     if (nsContentUtils::SubjectPrincipal()->Subsumes(p)) {
    9596             :       // Same origin, permit load
    9597           0 :       return NS_OK;
    9598             :     }
    9599             : 
    9600           0 :     nsCOMPtr<nsIDocShellTreeItem> tmp;
    9601           0 :     item->GetSameTypeParent(getter_AddRefs(tmp));
    9602           0 :     item.swap(tmp);
    9603             :   } while (item);
    9604             : 
    9605           0 :   return NS_ERROR_DOM_PROP_ACCESS_DENIED;
    9606             : }
    9607             : 
    9608             : //*****************************************************************************
    9609             : // nsDocShell: Site Loading
    9610             : //*****************************************************************************
    9611             : 
    9612             : void
    9613           0 : nsDocShell::CopyFavicon(nsIURI* aOldURI,
    9614             :                         nsIURI* aNewURI,
    9615             :                         nsIPrincipal* aLoadingPrincipal,
    9616             :                         bool aInPrivateBrowsing)
    9617             : {
    9618           0 :   if (XRE_IsContentProcess()) {
    9619           0 :     dom::ContentChild* contentChild = dom::ContentChild::GetSingleton();
    9620           0 :     if (contentChild) {
    9621           0 :       mozilla::ipc::URIParams oldURI, newURI;
    9622           0 :       SerializeURI(aOldURI, oldURI);
    9623           0 :       SerializeURI(aNewURI, newURI);
    9624           0 :       contentChild->SendCopyFavicon(oldURI, newURI,
    9625           0 :                                     IPC::Principal(aLoadingPrincipal),
    9626           0 :                                     aInPrivateBrowsing);
    9627             :     }
    9628           0 :     return;
    9629             :   }
    9630             : 
    9631             : #ifdef MOZ_PLACES
    9632             :   nsCOMPtr<mozIAsyncFavicons> favSvc =
    9633           0 :     do_GetService("@mozilla.org/browser/favicon-service;1");
    9634           0 :   if (favSvc) {
    9635           0 :     favSvc->CopyFavicons(aOldURI, aNewURI,
    9636             :       aInPrivateBrowsing ? nsIFaviconService::FAVICON_LOAD_PRIVATE
    9637           0 :                          : nsIFaviconService::FAVICON_LOAD_NON_PRIVATE, nullptr);
    9638             :   }
    9639             : #endif
    9640             : }
    9641             : 
    9642           0 : class InternalLoadEvent : public Runnable
    9643             : {
    9644             : public:
    9645           0 :   InternalLoadEvent(nsDocShell* aDocShell,
    9646             :                     nsIURI* aURI,
    9647             :                     nsIURI* aOriginalURI,
    9648             :                     Maybe<nsCOMPtr<nsIURI>> const& aResultPrincipalURI,
    9649             :                     bool aLoadReplace,
    9650             :                     nsIURI* aReferrer, uint32_t aReferrerPolicy,
    9651             :                     nsIPrincipal* aTriggeringPrincipal,
    9652             :                     nsIPrincipal* aPrincipalToInherit,
    9653             :                     uint32_t aFlags,
    9654             :                     const char* aTypeHint,
    9655             :                     nsIInputStream* aPostData,
    9656             :                     nsIInputStream* aHeadersData,
    9657             :                     uint32_t aLoadType,
    9658             :                     nsISHEntry* aSHEntry,
    9659             :                     bool aFirstParty,
    9660             :                     const nsAString& aSrcdoc,
    9661             :                     nsIDocShell* aSourceDocShell,
    9662             :                     nsIURI* aBaseURI,
    9663             :                     bool aCheckForPrerender)
    9664           0 :     : mozilla::Runnable("InternalLoadEvent")
    9665             :     , mSrcdoc(aSrcdoc)
    9666             :     , mDocShell(aDocShell)
    9667             :     , mURI(aURI)
    9668             :     , mOriginalURI(aOriginalURI)
    9669             :     , mResultPrincipalURI(aResultPrincipalURI)
    9670             :     , mLoadReplace(aLoadReplace)
    9671             :     , mReferrer(aReferrer)
    9672             :     , mReferrerPolicy(aReferrerPolicy)
    9673             :     , mTriggeringPrincipal(aTriggeringPrincipal)
    9674             :     , mPrincipalToInherit(aPrincipalToInherit)
    9675             :     , mPostData(aPostData)
    9676             :     , mHeadersData(aHeadersData)
    9677             :     , mSHEntry(aSHEntry)
    9678             :     , mFlags(aFlags)
    9679             :     , mLoadType(aLoadType)
    9680             :     , mFirstParty(aFirstParty)
    9681             :     , mSourceDocShell(aSourceDocShell)
    9682             :     , mBaseURI(aBaseURI)
    9683           0 :     , mCheckForPrerender(aCheckForPrerender)
    9684             :   {
    9685             :     // Make sure to keep null things null as needed
    9686           0 :     if (aTypeHint) {
    9687           0 :       mTypeHint = aTypeHint;
    9688             :     }
    9689           0 :   }
    9690             : 
    9691             :   NS_IMETHOD
    9692           0 :   Run() override
    9693             :   {
    9694           0 :     return mDocShell->InternalLoad(mURI, mOriginalURI, mResultPrincipalURI,
    9695           0 :                                    mLoadReplace,
    9696             :                                    mReferrer,
    9697             :                                    mReferrerPolicy,
    9698             :                                    mTriggeringPrincipal, mPrincipalToInherit,
    9699           0 :                                    mFlags, EmptyString(), mTypeHint.get(),
    9700           0 :                                    NullString(), mPostData, mHeadersData,
    9701           0 :                                    mLoadType, mSHEntry, mFirstParty,
    9702             :                                    mSrcdoc, mSourceDocShell, mBaseURI,
    9703           0 :                                    mCheckForPrerender, nullptr, nullptr);
    9704             :   }
    9705             : 
    9706             : private:
    9707             :   // Use IDL strings so .get() returns null by default
    9708             :   nsXPIDLString mWindowTarget;
    9709             :   nsXPIDLCString mTypeHint;
    9710             :   nsString mSrcdoc;
    9711             : 
    9712             :   RefPtr<nsDocShell> mDocShell;
    9713             :   nsCOMPtr<nsIURI> mURI;
    9714             :   nsCOMPtr<nsIURI> mOriginalURI;
    9715             :   Maybe<nsCOMPtr<nsIURI>> mResultPrincipalURI;
    9716             :   bool mLoadReplace;
    9717             :   nsCOMPtr<nsIURI> mReferrer;
    9718             :   uint32_t mReferrerPolicy;
    9719             :   nsCOMPtr<nsIPrincipal> mTriggeringPrincipal;
    9720             :   nsCOMPtr<nsIPrincipal> mPrincipalToInherit;
    9721             :   nsCOMPtr<nsIInputStream> mPostData;
    9722             :   nsCOMPtr<nsIInputStream> mHeadersData;
    9723             :   nsCOMPtr<nsISHEntry> mSHEntry;
    9724             :   uint32_t mFlags;
    9725             :   uint32_t mLoadType;
    9726             :   bool mFirstParty;
    9727             :   nsCOMPtr<nsIDocShell> mSourceDocShell;
    9728             :   nsCOMPtr<nsIURI> mBaseURI;
    9729             :   bool mCheckForPrerender;
    9730             : };
    9731             : 
    9732             : /**
    9733             :  * Returns true if we started an asynchronous load (i.e., from the network), but
    9734             :  * the document we're loading there hasn't yet become this docshell's active
    9735             :  * document.
    9736             :  *
    9737             :  * When JustStartedNetworkLoad is true, you should be careful about modifying
    9738             :  * mLoadType and mLSHE.  These are both set when the asynchronous load first
    9739             :  * starts, and the load expects that, when it eventually runs InternalLoad,
    9740             :  * mLoadType and mLSHE will have their original values.
    9741             :  */
    9742             : bool
    9743           0 : nsDocShell::JustStartedNetworkLoad()
    9744             : {
    9745           0 :   return mDocumentRequest && mDocumentRequest != GetCurrentDocChannel();
    9746             : }
    9747             : 
    9748             : nsresult
    9749           0 : nsDocShell::CreatePrincipalFromReferrer(nsIURI* aReferrer,
    9750             :                                         nsIPrincipal** aResult)
    9751             : {
    9752             :   nsCOMPtr<nsIPrincipal> prin =
    9753           0 :     BasePrincipal::CreateCodebasePrincipal(aReferrer, mOriginAttributes);
    9754           0 :   prin.forget(aResult);
    9755             : 
    9756           0 :   return *aResult ? NS_OK : NS_ERROR_FAILURE;
    9757             : }
    9758             : 
    9759             : NS_IMETHODIMP
    9760           6 : nsDocShell::InternalLoad(nsIURI* aURI,
    9761             :                          nsIURI* aOriginalURI,
    9762             :                          Maybe<nsCOMPtr<nsIURI>> const& aResultPrincipalURI,
    9763             :                          bool aLoadReplace,
    9764             :                          nsIURI* aReferrer,
    9765             :                          uint32_t aReferrerPolicy,
    9766             :                          nsIPrincipal* aTriggeringPrincipal,
    9767             :                          nsIPrincipal* aPrincipalToInherit,
    9768             :                          uint32_t aFlags,
    9769             :                          const nsAString& aWindowTarget,
    9770             :                          const char* aTypeHint,
    9771             :                          const nsAString& aFileName,
    9772             :                          nsIInputStream* aPostData,
    9773             :                          nsIInputStream* aHeadersData,
    9774             :                          uint32_t aLoadType,
    9775             :                          nsISHEntry* aSHEntry,
    9776             :                          bool aFirstParty,
    9777             :                          const nsAString& aSrcdoc,
    9778             :                          nsIDocShell* aSourceDocShell,
    9779             :                          nsIURI* aBaseURI,
    9780             :                          bool aCheckForPrerender,
    9781             :                          nsIDocShell** aDocShell,
    9782             :                          nsIRequest** aRequest)
    9783             : {
    9784           6 :   MOZ_ASSERT(aTriggeringPrincipal, "need a valid TriggeringPrincipal");
    9785             : 
    9786           6 :   nsresult rv = NS_OK;
    9787           6 :   mOriginalUriString.Truncate();
    9788             : 
    9789           6 :   MOZ_LOG(gDocShellLeakLog, LogLevel::Debug,
    9790             :           ("DOCSHELL %p InternalLoad %s\n",
    9791             :            this, aURI ? aURI->GetSpecOrDefault().get() : ""));
    9792             :   // Initialize aDocShell/aRequest
    9793           6 :   if (aDocShell) {
    9794           0 :     *aDocShell = nullptr;
    9795             :   }
    9796           6 :   if (aRequest) {
    9797           0 :     *aRequest = nullptr;
    9798             :   }
    9799             : 
    9800           6 :   if (!aURI) {
    9801           0 :     return NS_ERROR_NULL_POINTER;
    9802             :   }
    9803             : 
    9804           6 :   NS_ENSURE_TRUE(IsValidLoadType(aLoadType), NS_ERROR_INVALID_ARG);
    9805             : 
    9806           6 :   NS_ENSURE_TRUE(!mIsBeingDestroyed, NS_ERROR_NOT_AVAILABLE);
    9807             : 
    9808           6 :   rv = EnsureScriptEnvironment();
    9809           6 :   if (NS_FAILED(rv)) {
    9810           0 :     return rv;
    9811             :   }
    9812             : 
    9813             :   // wyciwyg urls can only be loaded through history. Any normal load of
    9814             :   // wyciwyg through docshell is  illegal. Disallow such loads.
    9815           6 :   if (aLoadType & LOAD_CMD_NORMAL) {
    9816           6 :     bool isWyciwyg = false;
    9817           6 :     rv = aURI->SchemeIs("wyciwyg", &isWyciwyg);
    9818           6 :     if ((isWyciwyg && NS_SUCCEEDED(rv)) || NS_FAILED(rv)) {
    9819           0 :       return NS_ERROR_FAILURE;
    9820             :     }
    9821             :   }
    9822             : 
    9823           6 :   bool isJavaScript = false;
    9824           6 :   if (NS_FAILED(aURI->SchemeIs("javascript", &isJavaScript))) {
    9825           0 :     isJavaScript = false;
    9826             :   }
    9827             : 
    9828           6 :   bool isTargetTopLevelDocShell = false;
    9829          12 :   nsCOMPtr<nsIDocShell> targetDocShell;
    9830           6 :   if (!aWindowTarget.IsEmpty()) {
    9831             :     // Locate the target DocShell.
    9832           0 :     nsCOMPtr<nsIDocShellTreeItem> targetItem;
    9833             :     // Only _self, _parent, and _top are supported in noopener case.  But we
    9834             :     // have to be careful to not apply that to the noreferrer case.  See bug
    9835             :     // 1358469.
    9836           0 :     bool allowNamedTarget = !(aFlags & INTERNAL_LOAD_FLAGS_NO_OPENER) ||
    9837           0 :                             (aFlags & INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER);
    9838           0 :     if (allowNamedTarget ||
    9839           0 :         aWindowTarget.LowerCaseEqualsLiteral("_self") ||
    9840           0 :         aWindowTarget.LowerCaseEqualsLiteral("_parent") ||
    9841           0 :         aWindowTarget.LowerCaseEqualsLiteral("_top")) {
    9842           0 :       rv = FindItemWithName(aWindowTarget, nullptr, this, false,
    9843           0 :                             getter_AddRefs(targetItem));
    9844           0 :       NS_ENSURE_SUCCESS(rv, rv);
    9845             :     }
    9846             : 
    9847           0 :     targetDocShell = do_QueryInterface(targetItem);
    9848           0 :     if (targetDocShell) {
    9849             :       // If the targetDocShell and the rootDocShell are the same, then the
    9850             :       // targetDocShell is the top level document and hence we should
    9851             :       // consider this TYPE_DOCUMENT
    9852             :       //
    9853             :       // For example:
    9854             :       // 1. target="_top"
    9855             :       // 2. target="_parent", where this docshell is in the 2nd level of
    9856             :       //    docshell tree.
    9857           0 :       nsCOMPtr<nsIDocShellTreeItem> sameTypeRoot;
    9858           0 :       targetDocShell->GetSameTypeRootTreeItem(getter_AddRefs(sameTypeRoot));
    9859           0 :       NS_ASSERTION(sameTypeRoot,
    9860             :                    "No document shell root tree item from targetDocShell!");
    9861           0 :       nsCOMPtr<nsIDocShell> rootShell = do_QueryInterface(sameTypeRoot);
    9862           0 :       NS_ASSERTION(rootShell,
    9863             :                    "No root docshell from document shell root tree item.");
    9864           0 :       isTargetTopLevelDocShell = targetDocShell == rootShell;
    9865             :     } else {
    9866             :       // If the targetDocShell doesn't exist, then this is a new docShell
    9867             :       // and we should consider this a TYPE_DOCUMENT load
    9868             :       //
    9869             :       // For example, when target="_blank"
    9870           0 :       isTargetTopLevelDocShell = true;
    9871             :     }
    9872             :   }
    9873             : 
    9874             :   // The contentType will be INTERNAL_(I)FRAME if:
    9875             :   // 1. This docshell is for iframe.
    9876             :   // 2. AND aWindowTarget is not a new window, nor a top-level window.
    9877             :   //
    9878             :   // This variable will be used when we call NS_CheckContentLoadPolicy, and
    9879             :   // later when we call DoURILoad.
    9880             :   uint32_t contentType;
    9881           6 :   if (IsFrame() && !isTargetTopLevelDocShell) {
    9882             :     nsCOMPtr<Element> requestingElement =
    9883           2 :       mScriptGlobal->AsOuter()->GetFrameElementInternal();
    9884           1 :     if (requestingElement) {
    9885           1 :       contentType = requestingElement->IsHTMLElement(nsGkAtoms::iframe) ?
    9886             :         nsIContentPolicy::TYPE_INTERNAL_IFRAME : nsIContentPolicy::TYPE_INTERNAL_FRAME;
    9887             :     } else {
    9888             :       // If we have lost our frame element by now, just assume we're
    9889             :       // an iframe since that's more common.
    9890           0 :       contentType = nsIContentPolicy::TYPE_INTERNAL_IFRAME;
    9891             :     }
    9892             :   } else {
    9893           5 :     contentType = nsIContentPolicy::TYPE_DOCUMENT;
    9894           5 :     isTargetTopLevelDocShell = true;
    9895             :   }
    9896             : 
    9897             :   // If there's no targetDocShell, that means we are about to create a new window,
    9898             :   // perform a content policy check before creating the window.
    9899           6 :   if (!targetDocShell) {
    9900          12 :     nsCOMPtr<Element> requestingElement;
    9901           6 :     nsISupports* requestingContext = nullptr;
    9902             : 
    9903           6 :     if (contentType == nsIContentPolicy::TYPE_DOCUMENT) {
    9904           5 :       if (XRE_IsContentProcess()) {
    9905             :         // In e10s the child process doesn't have access to the element that
    9906             :         // contains the browsing context (because that element is in the chrome
    9907             :         // process). So we just pass mScriptGlobal.
    9908           2 :         requestingContext = ToSupports(mScriptGlobal);
    9909             :       } else {
    9910             :         // This is for loading non-e10s tabs and toplevel windows of various
    9911             :         // sorts.
    9912             :         // For the toplevel window cases, requestingElement will be null.
    9913           3 :         requestingElement = mScriptGlobal->AsOuter()->GetFrameElementInternal();
    9914           3 :         requestingContext = requestingElement;
    9915             :       }
    9916             :     } else {
    9917           1 :       requestingElement = mScriptGlobal->AsOuter()->GetFrameElementInternal();
    9918           1 :       requestingContext = requestingElement;
    9919             : 
    9920             : #ifdef DEBUG
    9921           1 :       if (requestingElement) {
    9922             :         // Get the docshell type for requestingElement.
    9923           2 :         nsCOMPtr<nsIDocument> requestingDoc = requestingElement->OwnerDoc();
    9924           2 :         nsCOMPtr<nsIDocShell> elementDocShell = requestingDoc->GetDocShell();
    9925             : 
    9926             :         // requestingElement docshell type = current docshell type.
    9927           1 :         MOZ_ASSERT(mItemType == elementDocShell->ItemType(),
    9928             :                   "subframes should have the same docshell type as their parent");
    9929             :       }
    9930             : #endif
    9931             :     }
    9932             : 
    9933             :     // Since Content Policy checks are performed within docShell as well as
    9934             :     // the ContentSecurityManager we need a reliable way to let certain
    9935             :     // nsIContentPolicy consumers ignore duplicate calls. Let's use the 'extra'
    9936             :     // argument to pass a specific identifier.
    9937             :     nsCOMPtr<nsISupportsString> extraStr =
    9938          12 :       do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID, &rv);
    9939           6 :     NS_ENSURE_SUCCESS(rv, rv);
    9940           6 :     NS_NAMED_LITERAL_STRING(msg, "conPolCheckFromDocShell");
    9941           6 :     rv = extraStr->SetData(msg);
    9942           6 :     NS_ENSURE_SUCCESS(rv, rv);
    9943             : 
    9944           6 :     int16_t shouldLoad = nsIContentPolicy::ACCEPT;
    9945           6 :     rv = NS_CheckContentLoadPolicy(contentType,
    9946             :                                    aURI,
    9947             :                                    aTriggeringPrincipal,
    9948             :                                    requestingContext,
    9949           6 :                                    EmptyCString(),  // mime guess
    9950             :                                    extraStr,  // extra
    9951           6 :                                    &shouldLoad);
    9952             : 
    9953           6 :     if (NS_FAILED(rv) || NS_CP_REJECTED(shouldLoad)) {
    9954           0 :       if (NS_SUCCEEDED(rv) && shouldLoad == nsIContentPolicy::REJECT_TYPE) {
    9955           0 :         return NS_ERROR_CONTENT_BLOCKED_SHOW_ALT;
    9956             :       }
    9957             : 
    9958           0 :       return NS_ERROR_CONTENT_BLOCKED;
    9959             :     }
    9960             : 
    9961             :     // If HSTS priming was set by nsMixedContentBlocker::ShouldLoad, and we
    9962             :     // would block due to mixed content, go ahead and block here. If we try to
    9963             :     // proceed with priming, we will error out later on.
    9964          12 :     nsCOMPtr<nsIDocShell> docShell = NS_CP_GetDocShellFromContext(requestingContext);
    9965             :     // When loading toplevel windows, requestingContext can be null.  We don't
    9966             :     // really care about HSTS in that situation, though; loads in toplevel
    9967             :     // windows should all be browser UI.
    9968           6 :     if (docShell) {
    9969           4 :       nsIDocument* document = docShell->GetDocument();
    9970           4 :       NS_ENSURE_TRUE(document, NS_OK);
    9971             : 
    9972           4 :       HSTSPrimingState state = document->GetHSTSPrimingStateForLocation(aURI);
    9973           4 :       if (state == HSTSPrimingState::eHSTS_PRIMING_BLOCK) {
    9974             :         // HSTS Priming currently disabled for InternalLoad, so we need to clear
    9975             :         // the location that was added by nsMixedContentBlocker::ShouldLoad
    9976             :         // Bug 1269815 will address images loaded via InternalLoad
    9977           0 :         document->ClearHSTSPrimingLocation(aURI);
    9978           0 :         return NS_ERROR_CONTENT_BLOCKED;
    9979             :       }
    9980             :     }
    9981             :   }
    9982             : 
    9983          12 :   nsCOMPtr<nsIPrincipal> principalToInherit = aPrincipalToInherit;
    9984             :   //
    9985             :   // Get a principal from the current document if necessary.  Note that we only
    9986             :   // do this for URIs that inherit a security context and local file URIs;
    9987             :   // in particular we do NOT do this for about:blank.  This way, random
    9988             :   // about:blank loads that have no principal (which basically means they were
    9989             :   // done by someone from chrome manually messing with our nsIWebNavigation
    9990             :   // or by C++ setting document.location) don't get a funky principal.  If
    9991             :   // callers want something interesting to happen with the about:blank
    9992             :   // principal in this case, they should pass aPrincipalToInherit in.
    9993             :   //
    9994             :   {
    9995             :     bool inherits;
    9996             :     // One more twist: Don't inherit the principal for external loads.
    9997          14 :     if (aLoadType != LOAD_NORMAL_EXTERNAL && !principalToInherit &&
    9998           4 :         (aFlags & INTERNAL_LOAD_FLAGS_INHERIT_PRINCIPAL) &&
    9999           2 :          NS_SUCCEEDED(nsContentUtils::URIInheritsSecurityContext(aURI,
   10000           8 :                                                                  &inherits)) &&
   10001             :          inherits) {
   10002           0 :       principalToInherit = GetInheritedPrincipal(true);
   10003             :     }
   10004             :   }
   10005             : 
   10006             :   // Don't allow loads that would inherit our security context
   10007             :   // if this document came from an unsafe channel.
   10008             :   {
   10009             :     bool willInherit;
   10010             :     // This condition needs to match the one in
   10011             :     // nsContentUtils::ChannelShouldInheritPrincipal.
   10012             :     // Except we reverse the rv check to be safe in case
   10013             :     // nsContentUtils::URIInheritsSecurityContext fails here and
   10014             :     // succeeds there.
   10015           6 :     rv = nsContentUtils::URIInheritsSecurityContext(aURI, &willInherit);
   10016           6 :     if (NS_FAILED(rv) || willInherit || NS_IsAboutBlank(aURI)) {
   10017           6 :       nsCOMPtr<nsIDocShellTreeItem> treeItem = this;
   10018           4 :       do {
   10019           8 :         nsCOMPtr<nsIDocShell> itemDocShell = do_QueryInterface(treeItem);
   10020             :         bool isUnsafe;
   10021           8 :         if (itemDocShell &&
   10022           8 :             NS_SUCCEEDED(itemDocShell->GetChannelIsUnsafe(&isUnsafe)) &&
   10023             :             isUnsafe) {
   10024           0 :           return NS_ERROR_DOM_SECURITY_ERR;
   10025             :         }
   10026             : 
   10027           8 :         nsCOMPtr<nsIDocShellTreeItem> parent;
   10028           4 :         treeItem->GetSameTypeParent(getter_AddRefs(parent));
   10029           4 :         parent.swap(treeItem);
   10030             :       } while (treeItem);
   10031             :     }
   10032             :   }
   10033             : 
   10034             :   //
   10035             :   // Resolve the window target before going any further...
   10036             :   // If the load has been targeted to another DocShell, then transfer the
   10037             :   // load to it...
   10038             :   //
   10039           6 :   if (!aWindowTarget.IsEmpty()) {
   10040             :     // We've already done our owner-inheriting.  Mask out that bit, so we
   10041             :     // don't try inheriting an owner from the target window if we came up
   10042             :     // with a null owner above.
   10043           0 :     aFlags = aFlags & ~INTERNAL_LOAD_FLAGS_INHERIT_PRINCIPAL;
   10044             : 
   10045           0 :     bool isNewWindow = false;
   10046           0 :     if (!targetDocShell) {
   10047             :       // If the docshell's document is sandboxed, only open a new window
   10048             :       // if the document's SANDBOXED_AUXILLARY_NAVIGATION flag is not set.
   10049             :       // (i.e. if allow-popups is specified)
   10050           0 :       NS_ENSURE_TRUE(mContentViewer, NS_ERROR_FAILURE);
   10051           0 :       nsIDocument* doc = mContentViewer->GetDocument();
   10052           0 :       uint32_t sandboxFlags = 0;
   10053             : 
   10054           0 :       if (doc) {
   10055           0 :         sandboxFlags = doc->GetSandboxFlags();
   10056           0 :         if (sandboxFlags & SANDBOXED_AUXILIARY_NAVIGATION) {
   10057           0 :           return NS_ERROR_DOM_INVALID_ACCESS_ERR;
   10058             :         }
   10059             :       }
   10060             : 
   10061           0 :       nsCOMPtr<nsPIDOMWindowOuter> win = GetWindow();
   10062           0 :       NS_ENSURE_TRUE(win, NS_ERROR_NOT_AVAILABLE);
   10063             : 
   10064           0 :       nsCOMPtr<nsPIDOMWindowOuter> newWin;
   10065           0 :       nsAutoCString spec;
   10066           0 :       if (aURI) {
   10067           0 :         aURI->GetSpec(spec);
   10068             :       }
   10069             :       // If we are a noopener load, we just hand the whole thing over to our
   10070             :       // window.
   10071           0 :       if (aFlags & INTERNAL_LOAD_FLAGS_NO_OPENER) {
   10072             :         // Various asserts that we know to hold because NO_OPENER loads can only
   10073             :         // happen for links.
   10074           0 :         MOZ_ASSERT(!aLoadReplace);
   10075           0 :         MOZ_ASSERT(aPrincipalToInherit == aTriggeringPrincipal);
   10076           0 :         MOZ_ASSERT(aFlags == INTERNAL_LOAD_FLAGS_NO_OPENER ||
   10077             :                    aFlags == (INTERNAL_LOAD_FLAGS_NO_OPENER |
   10078             :                               INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER));
   10079           0 :         MOZ_ASSERT(!aPostData);
   10080           0 :         MOZ_ASSERT(!aHeadersData);
   10081           0 :         MOZ_ASSERT(aLoadType == LOAD_LINK);
   10082           0 :         MOZ_ASSERT(!aSHEntry);
   10083           0 :         MOZ_ASSERT(aFirstParty); // Windowwatcher will assume this.
   10084             : 
   10085           0 :         nsCOMPtr<nsIDocShellLoadInfo> loadInfo;
   10086           0 :         rv = CreateLoadInfo(getter_AddRefs(loadInfo));
   10087           0 :         if (NS_FAILED(rv)) {
   10088           0 :           return rv;
   10089             :         }
   10090             : 
   10091             :         // Set up our loadinfo so it will do the load as much like we would have
   10092             :         // as possible.
   10093           0 :         loadInfo->SetReferrer(aReferrer);
   10094           0 :         loadInfo->SetReferrerPolicy(aReferrerPolicy);
   10095           0 :         loadInfo->SetSendReferrer(!(aFlags &
   10096           0 :                                     INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER));
   10097           0 :         loadInfo->SetOriginalURI(aOriginalURI);
   10098           0 :         SetMaybeResultPrincipalURI(loadInfo, aResultPrincipalURI);
   10099           0 :         loadInfo->SetLoadReplace(aLoadReplace);
   10100           0 :         loadInfo->SetTriggeringPrincipal(aTriggeringPrincipal);
   10101           0 :         loadInfo->SetInheritPrincipal(
   10102           0 :           aFlags & INTERNAL_LOAD_FLAGS_INHERIT_PRINCIPAL);
   10103             :         // Explicit principal because we do not want any guesses as to what the
   10104             :         // principal to inherit is: it should be aTriggeringPrincipal.
   10105           0 :         loadInfo->SetPrincipalIsExplicit(true);
   10106           0 :         loadInfo->SetLoadType(ConvertLoadTypeToDocShellLoadInfo(LOAD_LINK));
   10107             : 
   10108           0 :         rv = win->Open(NS_ConvertUTF8toUTF16(spec),
   10109             :                        aWindowTarget, // window name
   10110           0 :                        EmptyString(), // Features
   10111             :                        loadInfo,
   10112             :                        true, // aForceNoOpener
   10113           0 :                        getter_AddRefs(newWin));
   10114           0 :         MOZ_ASSERT(!newWin);
   10115           0 :         return rv;
   10116             :       }
   10117             : 
   10118           0 :       rv = win->OpenNoNavigate(NS_ConvertUTF8toUTF16(spec),
   10119             :                                aWindowTarget,  // window name
   10120           0 :                                EmptyString(), // Features
   10121           0 :                                getter_AddRefs(newWin));
   10122             : 
   10123             :       // In some cases the Open call doesn't actually result in a new
   10124             :       // window being opened.  We can detect these cases by examining the
   10125             :       // document in |newWin|, if any.
   10126           0 :       nsCOMPtr<nsPIDOMWindowOuter> piNewWin = do_QueryInterface(newWin);
   10127           0 :       if (piNewWin) {
   10128           0 :         nsCOMPtr<nsIDocument> newDoc = piNewWin->GetExtantDoc();
   10129           0 :         if (!newDoc || newDoc->IsInitialDocument()) {
   10130           0 :           isNewWindow = true;
   10131           0 :           aFlags |= INTERNAL_LOAD_FLAGS_FIRST_LOAD;
   10132             :         }
   10133             :       }
   10134             : 
   10135           0 :       nsCOMPtr<nsIWebNavigation> webNav = do_GetInterface(newWin);
   10136           0 :       targetDocShell = do_QueryInterface(webNav);
   10137             :     }
   10138             : 
   10139             :     //
   10140             :     // Transfer the load to the target DocShell...  Pass nullptr as the
   10141             :     // window target name from to prevent recursive retargeting!
   10142             :     //
   10143           0 :     if (NS_SUCCEEDED(rv) && targetDocShell) {
   10144           0 :       rv = targetDocShell->InternalLoad(aURI,
   10145             :                                         aOriginalURI,
   10146             :                                         aResultPrincipalURI,
   10147             :                                         aLoadReplace,
   10148             :                                         aReferrer,
   10149             :                                         aReferrerPolicy,
   10150             :                                         aTriggeringPrincipal,
   10151             :                                         principalToInherit,
   10152             :                                         aFlags,
   10153           0 :                                         EmptyString(),   // No window target
   10154             :                                         aTypeHint,
   10155           0 :                                         NullString(),    // No forced download
   10156             :                                         aPostData,
   10157             :                                         aHeadersData,
   10158             :                                         aLoadType,
   10159             :                                         aSHEntry,
   10160             :                                         aFirstParty,
   10161             :                                         aSrcdoc,
   10162             :                                         aSourceDocShell,
   10163             :                                         aBaseURI,
   10164             :                                         aCheckForPrerender,
   10165             :                                         aDocShell,
   10166           0 :                                         aRequest);
   10167           0 :       if (rv == NS_ERROR_NO_CONTENT) {
   10168             :         // XXXbz except we never reach this code!
   10169           0 :         if (isNewWindow) {
   10170             :           //
   10171             :           // At this point, a new window has been created, but the
   10172             :           // URI did not have any data associated with it...
   10173             :           //
   10174             :           // So, the best we can do, is to tear down the new window
   10175             :           // that was just created!
   10176             :           //
   10177           0 :           if (nsCOMPtr<nsPIDOMWindowOuter> domWin = targetDocShell->GetWindow()) {
   10178           0 :             domWin->Close();
   10179             :           }
   10180             :         }
   10181             :         //
   10182             :         // NS_ERROR_NO_CONTENT should not be returned to the
   10183             :         // caller... This is an internal error code indicating that
   10184             :         // the URI had no data associated with it - probably a
   10185             :         // helper-app style protocol (ie. mailto://)
   10186             :         //
   10187           0 :         rv = NS_OK;
   10188             :       } else if (isNewWindow) {
   10189             :         // XXX: Once new windows are created hidden, the new
   10190             :         //      window will need to be made visible...  For now,
   10191             :         //      do nothing.
   10192             :       }
   10193             : 
   10194           0 :       if (NS_SUCCEEDED(rv)) {
   10195             :         // Switch to target tab if we're currently focused window.
   10196             :         // Take loadDivertedInBackground into account so the behavior would be
   10197             :         // the same as how the tab first opened.
   10198           0 :         bool isTargetActive = false;
   10199           0 :         targetDocShell->GetIsActive(&isTargetActive);
   10200           0 :         nsCOMPtr<nsPIDOMWindowOuter> domWin = targetDocShell->GetWindow();
   10201           0 :         if (mIsActive && !isTargetActive && domWin &&
   10202           0 :             !Preferences::GetBool("browser.tabs.loadDivertedInBackground", false)) {
   10203           0 :           if (NS_FAILED(nsContentUtils::DispatchFocusChromeEvent(domWin))) {
   10204           0 :             return NS_ERROR_FAILURE;
   10205             :           }
   10206             :         }
   10207             :       }
   10208             :     }
   10209             : 
   10210             :     // Else we ran out of memory, or were a popup and got blocked,
   10211             :     // or something.
   10212             : 
   10213           0 :     return rv;
   10214             :   }
   10215             : 
   10216             :   //
   10217             :   // Load is being targetted at this docshell so return an error if the
   10218             :   // docshell is in the process of being destroyed.
   10219             :   //
   10220           6 :   if (mIsBeingDestroyed) {
   10221           0 :     return NS_ERROR_FAILURE;
   10222             :   }
   10223             : 
   10224           6 :   NS_ENSURE_STATE(!HasUnloadedParent());
   10225             : 
   10226           6 :   rv = CheckLoadingPermissions();
   10227           6 :   if (NS_FAILED(rv)) {
   10228           0 :     return rv;
   10229             :   }
   10230             : 
   10231           6 :   if (mFiredUnloadEvent) {
   10232           0 :     if (IsOKToLoadURI(aURI)) {
   10233           0 :       NS_PRECONDITION(aWindowTarget.IsEmpty(),
   10234             :                       "Shouldn't have a window target here!");
   10235             : 
   10236             :       // If this is a replace load, make whatever load triggered
   10237             :       // the unload event also a replace load, so we don't
   10238             :       // create extra history entries.
   10239           0 :       if (LOAD_TYPE_HAS_FLAGS(aLoadType, LOAD_FLAGS_REPLACE_HISTORY)) {
   10240           0 :         mLoadType = LOAD_NORMAL_REPLACE;
   10241             :       }
   10242             : 
   10243             :       // Do this asynchronously
   10244             :       nsCOMPtr<nsIRunnable> ev =
   10245             :         new InternalLoadEvent(this, aURI, aOriginalURI, aResultPrincipalURI,
   10246             :                               aLoadReplace, aReferrer, aReferrerPolicy,
   10247             :                               aTriggeringPrincipal, principalToInherit,
   10248             :                               aFlags, aTypeHint, aPostData, aHeadersData,
   10249             :                               aLoadType, aSHEntry, aFirstParty, aSrcdoc,
   10250           0 :                               aSourceDocShell, aBaseURI, false);
   10251             :       return DispatchToTabGroup("nsDocShell::InternalLoadEvent",
   10252           0 :                                 TaskCategory::Other, ev.forget());
   10253             :     }
   10254             : 
   10255             :     // Just ignore this load attempt
   10256           0 :     return NS_OK;
   10257             :   }
   10258             : 
   10259             :   // If a source docshell has been passed, check to see if we are sandboxed
   10260             :   // from it as the result of an iframe or CSP sandbox.
   10261           6 :   if (aSourceDocShell && aSourceDocShell->IsSandboxedFrom(this)) {
   10262           0 :     return NS_ERROR_DOM_INVALID_ACCESS_ERR;
   10263             :   }
   10264             : 
   10265             :   // If this docshell is owned by a frameloader, make sure to cancel
   10266             :   // possible frameloader initialization before loading a new page.
   10267          12 :   nsCOMPtr<nsIDocShellTreeItem> parent = GetParentDocshell();
   10268           6 :   if (parent) {
   10269           4 :     nsCOMPtr<nsIDocument> doc = parent->GetDocument();
   10270           2 :     if (doc) {
   10271           2 :       doc->TryCancelFrameLoaderInitialization(this);
   10272             :     }
   10273             :   }
   10274             : 
   10275             :   // Before going any further vet loads initiated by external programs.
   10276           6 :   if (aLoadType == LOAD_NORMAL_EXTERNAL) {
   10277             :     // Disallow external chrome: loads targetted at content windows
   10278           0 :     bool isChrome = false;
   10279           0 :     if (NS_SUCCEEDED(aURI->SchemeIs("chrome", &isChrome)) && isChrome) {
   10280           0 :       NS_WARNING("blocked external chrome: url -- use '--chrome' option");
   10281           0 :       return NS_ERROR_FAILURE;
   10282             :     }
   10283             : 
   10284             :     // clear the decks to prevent context bleed-through (bug 298255)
   10285           0 :     rv = CreateAboutBlankContentViewer(nullptr, nullptr);
   10286           0 :     if (NS_FAILED(rv)) {
   10287           0 :       return NS_ERROR_FAILURE;
   10288             :     }
   10289             : 
   10290             :     // reset loadType so we don't have to add lots of tests for
   10291             :     // LOAD_NORMAL_EXTERNAL after this point
   10292           0 :     aLoadType = LOAD_NORMAL;
   10293             :   }
   10294             : 
   10295           6 :   mAllowKeywordFixup =
   10296           6 :     (aFlags & INTERNAL_LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP) != 0;
   10297           6 :   mURIResultedInDocument = false;  // reset the clock...
   10298             : 
   10299           6 :   if (aLoadType == LOAD_NORMAL ||
   10300           0 :       aLoadType == LOAD_STOP_CONTENT ||
   10301           0 :       LOAD_TYPE_HAS_FLAGS(aLoadType, LOAD_FLAGS_REPLACE_HISTORY) ||
   10302           0 :       aLoadType == LOAD_HISTORY ||
   10303             :       aLoadType == LOAD_LINK) {
   10304          12 :     nsCOMPtr<nsIURI> currentURI = mCurrentURI;
   10305             : 
   10306          12 :     nsAutoCString curHash, newHash;
   10307           6 :     bool curURIHasRef = false, newURIHasRef = false;
   10308             : 
   10309           6 :     nsresult rvURINew = aURI->GetRef(newHash);
   10310           6 :     if (NS_SUCCEEDED(rvURINew)) {
   10311           6 :       rvURINew = aURI->GetHasRef(&newURIHasRef);
   10312             :     }
   10313             : 
   10314           6 :     bool sameExceptHashes = false;
   10315           6 :     if (currentURI && NS_SUCCEEDED(rvURINew)) {
   10316           5 :       nsresult rvURIOld = currentURI->GetRef(curHash);
   10317           5 :       if (NS_SUCCEEDED(rvURIOld)) {
   10318           5 :         rvURIOld = currentURI->GetHasRef(&curURIHasRef);
   10319             :       }
   10320           5 :       if (NS_SUCCEEDED(rvURIOld)) {
   10321           5 :         if (NS_FAILED(currentURI->EqualsExceptRef(aURI, &sameExceptHashes))) {
   10322           0 :           sameExceptHashes = false;
   10323             :         }
   10324             :       }
   10325             :     }
   10326             : 
   10327           9 :     if (!sameExceptHashes && sURIFixup && currentURI &&
   10328           3 :         NS_SUCCEEDED(rvURINew)) {
   10329             :       // Maybe aURI came from the exposable form of currentURI?
   10330           6 :       nsCOMPtr<nsIURI> currentExposableURI;
   10331           6 :       rv = sURIFixup->CreateExposableURI(currentURI,
   10332           6 :                                          getter_AddRefs(currentExposableURI));
   10333           3 :       NS_ENSURE_SUCCESS(rv, rv);
   10334           3 :       nsresult rvURIOld = currentExposableURI->GetRef(curHash);
   10335           3 :       if (NS_SUCCEEDED(rvURIOld)) {
   10336           3 :         rvURIOld = currentExposableURI->GetHasRef(&curURIHasRef);
   10337             :       }
   10338           3 :       if (NS_SUCCEEDED(rvURIOld)) {
   10339           3 :         if (NS_FAILED(currentExposableURI->EqualsExceptRef(aURI, &sameExceptHashes))) {
   10340           0 :           sameExceptHashes = false;
   10341             :         }
   10342             :       }
   10343             :     }
   10344             : 
   10345           6 :     bool historyNavBetweenSameDoc = false;
   10346           6 :     if (mOSHE && aSHEntry) {
   10347             :       // We're doing a history load.
   10348             : 
   10349           0 :       mOSHE->SharesDocumentWith(aSHEntry, &historyNavBetweenSameDoc);
   10350             : 
   10351             : #ifdef DEBUG
   10352           0 :       if (historyNavBetweenSameDoc) {
   10353           0 :         nsCOMPtr<nsIInputStream> currentPostData;
   10354           0 :         mOSHE->GetPostData(getter_AddRefs(currentPostData));
   10355           0 :         NS_ASSERTION(currentPostData == aPostData,
   10356             :                      "Different POST data for entries for the same page?");
   10357             :       }
   10358             : #endif
   10359             :     }
   10360             : 
   10361             :     // A short-circuited load happens when we navigate between two SHEntries
   10362             :     // for the same document.  We do a short-circuited load under two
   10363             :     // circumstances.  Either
   10364             :     //
   10365             :     //  a) we're navigating between two different SHEntries which share a
   10366             :     //     document, or
   10367             :     //
   10368             :     //  b) we're navigating to a new shentry whose URI differs from the
   10369             :     //     current URI only in its hash, the new hash is non-empty, and
   10370             :     //     we're not doing a POST.
   10371             :     //
   10372             :     // The restriction tha the SHEntries in (a) must be different ensures
   10373             :     // that history.go(0) and the like trigger full refreshes, rather than
   10374             :     // short-circuited loads.
   10375             :     bool doShortCircuitedLoad =
   10376           6 :       (historyNavBetweenSameDoc && mOSHE != aSHEntry) ||
   10377           6 :       (!aSHEntry && !aPostData &&
   10378           8 :        sameExceptHashes && newURIHasRef);
   10379             : 
   10380           6 :     if (doShortCircuitedLoad) {
   10381             :       // Save the position of the scrollers.
   10382           0 :       nscoord cx = 0, cy = 0;
   10383           0 :       GetCurScrollPos(ScrollOrientation_X, &cx);
   10384           0 :       GetCurScrollPos(ScrollOrientation_Y, &cy);
   10385             : 
   10386             :       // Reset mLoadType to its original value once we exit this block,
   10387             :       // because this short-circuited load might have started after a
   10388             :       // normal, network load, and we don't want to clobber its load type.
   10389             :       // See bug 737307.
   10390           0 :       AutoRestore<uint32_t> loadTypeResetter(mLoadType);
   10391             : 
   10392             :       // If a non-short-circuit load (i.e., a network load) is pending,
   10393             :       // make this a replacement load, so that we don't add a SHEntry here
   10394             :       // and the network load goes into the SHEntry it expects to.
   10395           0 :       if (JustStartedNetworkLoad() && (aLoadType & LOAD_CMD_NORMAL)) {
   10396           0 :         mLoadType = LOAD_NORMAL_REPLACE;
   10397             :       } else {
   10398           0 :         mLoadType = aLoadType;
   10399             :       }
   10400             : 
   10401           0 :       mURIResultedInDocument = true;
   10402             : 
   10403           0 :       nsCOMPtr<nsISHEntry> oldLSHE = mLSHE;
   10404             : 
   10405             :       /* we need to assign mLSHE to aSHEntry right here, so that on History
   10406             :        * loads, SetCurrentURI() called from OnNewURI() will send proper
   10407             :        * onLocationChange() notifications to the browser to update
   10408             :        * back/forward buttons.
   10409             :        */
   10410           0 :       SetHistoryEntry(&mLSHE, aSHEntry);
   10411             : 
   10412             :       // Set the doc's URI according to the new history entry's URI.
   10413           0 :       nsCOMPtr<nsIDocument> doc = GetDocument();
   10414           0 :       NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE);
   10415           0 :       doc->SetDocumentURI(aURI);
   10416             : 
   10417             :       /* This is a anchor traversal with in the same page.
   10418             :        * call OnNewURI() so that, this traversal will be
   10419             :        * recorded in session and global history.
   10420             :        */
   10421           0 :       nsCOMPtr<nsIPrincipal> newURITriggeringPrincipal, newURIPrincipalToInherit;
   10422           0 :       if (mOSHE) {
   10423           0 :         mOSHE->GetTriggeringPrincipal(getter_AddRefs(newURITriggeringPrincipal));
   10424           0 :         mOSHE->GetPrincipalToInherit(getter_AddRefs(newURIPrincipalToInherit));
   10425             :       } else {
   10426           0 :         newURITriggeringPrincipal = aTriggeringPrincipal;
   10427           0 :         newURIPrincipalToInherit = doc->NodePrincipal();
   10428             :       }
   10429             :       // Pass true for aCloneSHChildren, since we're not
   10430             :       // changing documents here, so all of our subframes are
   10431             :       // still relevant to the new session history entry.
   10432             :       //
   10433             :       // It also makes OnNewURI(...) set LOCATION_CHANGE_SAME_DOCUMENT
   10434             :       // flag on firing onLocationChange(...).
   10435             :       // Anyway, aCloneSHChildren param is simply reflecting
   10436             :       // doShortCircuitedLoad in this scope.
   10437           0 :       OnNewURI(aURI, nullptr, newURITriggeringPrincipal, newURIPrincipalToInherit,
   10438           0 :                mLoadType, true, true, true);
   10439             : 
   10440           0 :       nsCOMPtr<nsIInputStream> postData;
   10441           0 :       nsCOMPtr<nsISupports> cacheKey;
   10442             : 
   10443           0 :       bool scrollRestorationIsManual = false;
   10444           0 :       if (mOSHE) {
   10445             :         /* save current position of scroller(s) (bug 59774) */
   10446           0 :         mOSHE->SetScrollPosition(cx, cy);
   10447           0 :         mOSHE->GetScrollRestorationIsManual(&scrollRestorationIsManual);
   10448             :         // Get the postdata and page ident from the current page, if
   10449             :         // the new load is being done via normal means.  Note that
   10450             :         // "normal means" can be checked for just by checking for
   10451             :         // LOAD_CMD_NORMAL, given the loadType and allowScroll check
   10452             :         // above -- it filters out some LOAD_CMD_NORMAL cases that we
   10453             :         // wouldn't want here.
   10454           0 :         if (aLoadType & LOAD_CMD_NORMAL) {
   10455           0 :           mOSHE->GetPostData(getter_AddRefs(postData));
   10456           0 :           mOSHE->GetCacheKey(getter_AddRefs(cacheKey));
   10457             : 
   10458             :           // Link our new SHEntry to the old SHEntry's back/forward
   10459             :           // cache data, since the two SHEntries correspond to the
   10460             :           // same document.
   10461           0 :           if (mLSHE) {
   10462           0 :             if (!aSHEntry) {
   10463             :               // If we're not doing a history load, scroll restoration
   10464             :               // should be inherited from the previous session history entry.
   10465           0 :               mLSHE->SetScrollRestorationIsManual(scrollRestorationIsManual);
   10466             :             }
   10467           0 :             mLSHE->AdoptBFCacheEntry(mOSHE);
   10468             :           }
   10469             :         }
   10470             :       }
   10471             : 
   10472             :       // If we're doing a history load, use its scroll restoration state.
   10473           0 :       if (aSHEntry) {
   10474           0 :         aSHEntry->GetScrollRestorationIsManual(&scrollRestorationIsManual);
   10475             :       }
   10476             : 
   10477             :       /* Assign mOSHE to mLSHE. This will either be a new entry created
   10478             :        * by OnNewURI() for normal loads or aSHEntry for history loads.
   10479             :        */
   10480           0 :       if (mLSHE) {
   10481           0 :         SetHistoryEntry(&mOSHE, mLSHE);
   10482             :         // Save the postData obtained from the previous page
   10483             :         // in to the session history entry created for the
   10484             :         // anchor page, so that any history load of the anchor
   10485             :         // page will restore the appropriate postData.
   10486           0 :         if (postData) {
   10487           0 :           mOSHE->SetPostData(postData);
   10488             :         }
   10489             : 
   10490             :         // Make sure we won't just repost without hitting the
   10491             :         // cache first
   10492           0 :         if (cacheKey) {
   10493           0 :           mOSHE->SetCacheKey(cacheKey);
   10494             :         }
   10495             :       }
   10496             : 
   10497             :       /* Restore the original LSHE if we were loading something
   10498             :        * while short-circuited load was initiated.
   10499             :        */
   10500           0 :       SetHistoryEntry(&mLSHE, oldLSHE);
   10501             :       /* Set the title for the SH entry for this target url. so that
   10502             :        * SH menus in go/back/forward buttons won't be empty for this.
   10503             :        */
   10504           0 :       if (mSessionHistory) {
   10505           0 :         int32_t index = -1;
   10506           0 :         mSessionHistory->GetIndex(&index);
   10507           0 :         nsCOMPtr<nsISHEntry> shEntry;
   10508           0 :         mSessionHistory->GetEntryAtIndex(index, false, getter_AddRefs(shEntry));
   10509           0 :         NS_ENSURE_TRUE(shEntry, NS_ERROR_FAILURE);
   10510           0 :         shEntry->SetTitle(mTitle);
   10511             :       }
   10512             : 
   10513             :       /* Set the title for the Global History entry for this anchor url.
   10514             :        */
   10515           0 :       UpdateGlobalHistoryTitle(aURI);
   10516             : 
   10517           0 :       SetDocCurrentStateObj(mOSHE);
   10518             : 
   10519             :       // Inform the favicon service that the favicon for oldURI also
   10520             :       // applies to aURI.
   10521           0 :       CopyFavicon(currentURI, aURI, doc->NodePrincipal(), UsePrivateBrowsing());
   10522             : 
   10523           0 :       RefPtr<nsGlobalWindow> scriptGlobal = mScriptGlobal;
   10524             :       RefPtr<nsGlobalWindow> win = scriptGlobal ?
   10525           0 :         scriptGlobal->GetCurrentInnerWindowInternal() : nullptr;
   10526             : 
   10527             :       // ScrollToAnchor doesn't necessarily cause us to scroll the window;
   10528             :       // the function decides whether a scroll is appropriate based on the
   10529             :       // arguments it receives.  But even if we don't end up scrolling,
   10530             :       // ScrollToAnchor performs other important tasks, such as informing
   10531             :       // the presShell that we have a new hash.  See bug 680257.
   10532           0 :       rv = ScrollToAnchor(curURIHasRef, newURIHasRef, newHash, aLoadType);
   10533           0 :       NS_ENSURE_SUCCESS(rv, rv);
   10534             : 
   10535             :       /* restore previous position of scroller(s), if we're moving
   10536             :        * back in history (bug 59774)
   10537             :        */
   10538           0 :       nscoord bx = 0;
   10539           0 :       nscoord by = 0;
   10540           0 :       bool needsScrollPosUpdate = false;
   10541           0 :       if (mOSHE && (aLoadType == LOAD_HISTORY ||
   10542           0 :                     aLoadType == LOAD_RELOAD_NORMAL) &&
   10543           0 :           !scrollRestorationIsManual) {
   10544           0 :         needsScrollPosUpdate = true;
   10545           0 :         mOSHE->GetScrollPosition(&bx, &by);
   10546             :       }
   10547             : 
   10548             :       // Dispatch the popstate and hashchange events, as appropriate.
   10549             :       //
   10550             :       // The event dispatch below can cause us to re-enter script and
   10551             :       // destroy the docshell, nulling out mScriptGlobal. Hold a stack
   10552             :       // reference to avoid null derefs. See bug 914521.
   10553           0 :       if (win) {
   10554             :         // Fire a hashchange event URIs differ, and only in their hashes.
   10555           0 :         bool doHashchange = sameExceptHashes &&
   10556           0 :                             (curURIHasRef != newURIHasRef || !curHash.Equals(newHash));
   10557             : 
   10558           0 :         if (historyNavBetweenSameDoc || doHashchange) {
   10559           0 :           win->DispatchSyncPopState();
   10560             :         }
   10561             : 
   10562           0 :         if (needsScrollPosUpdate && win->AsInner()->HasActiveDocument()) {
   10563           0 :           SetCurScrollPosEx(bx, by);
   10564             :         }
   10565             : 
   10566           0 :         if (doHashchange) {
   10567             :           // Note that currentURI hasn't changed because it's on the
   10568             :           // stack, so we can just use it directly as the old URI.
   10569           0 :           win->DispatchAsyncHashchange(currentURI, aURI);
   10570             :         }
   10571             :       }
   10572             : 
   10573           0 :       return NS_OK;
   10574             :     }
   10575             :   }
   10576             : 
   10577             :   // mContentViewer->PermitUnload can destroy |this| docShell, which
   10578             :   // causes the next call of CanSavePresentation to crash.
   10579             :   // Hold onto |this| until we return, to prevent a crash from happening.
   10580             :   // (bug#331040)
   10581          12 :   nsCOMPtr<nsIDocShell> kungFuDeathGrip(this);
   10582             : 
   10583             :   // Don't init timing for javascript:, since it generally doesn't
   10584             :   // actually start a load or anything.  If it does, we'll init
   10585             :   // timing then, from OnStateChange.
   10586             : 
   10587             :   // XXXbz mTiming should know what channel it's for, so we don't
   10588             :   // need this hackery.
   10589           6 :   bool toBeReset = false;
   10590           6 :   if (!isJavaScript) {
   10591           6 :     toBeReset = MaybeInitTiming();
   10592             :   }
   10593           6 :   bool timeBeforeUnload = aFileName.IsVoid();
   10594           6 :   if (mTiming && timeBeforeUnload) {
   10595           6 :     mTiming->NotifyBeforeUnload();
   10596             :   }
   10597             :   // Check if the page doesn't want to be unloaded. The javascript:
   10598             :   // protocol handler deals with this for javascript: URLs.
   10599           6 :   if (!isJavaScript && aFileName.IsVoid() && mContentViewer) {
   10600             :     bool okToUnload;
   10601           5 :     rv = mContentViewer->PermitUnload(&okToUnload);
   10602             : 
   10603           5 :     if (NS_SUCCEEDED(rv) && !okToUnload) {
   10604             :       // The user chose not to unload the page, interrupt the
   10605             :       // load.
   10606           0 :       MaybeResetInitTiming(toBeReset);
   10607           0 :       return NS_OK;
   10608             :     }
   10609             :   }
   10610             : 
   10611           6 :   if (mTiming && timeBeforeUnload) {
   10612           6 :     mTiming->NotifyUnloadAccepted(mCurrentURI);
   10613             :   }
   10614             : 
   10615             :   // Check if the webbrowser chrome wants the load to proceed; this can be
   10616             :   // used to cancel attempts to load URIs in the wrong process.
   10617          12 :   nsCOMPtr<nsIWebBrowserChrome3> browserChrome3 = do_GetInterface(mTreeOwner);
   10618           6 :   if (browserChrome3) {
   10619             :     bool shouldLoad;
   10620           4 :     rv = browserChrome3->ShouldLoadURI(this, aURI, aReferrer, !!aPostData,
   10621           2 :                                        aTriggeringPrincipal, &shouldLoad);
   10622           2 :     if (NS_SUCCEEDED(rv) && !shouldLoad) {
   10623           0 :       return NS_OK;
   10624             :     }
   10625             :   }
   10626             : 
   10627           6 :   if (browserChrome3 && aCheckForPrerender) {
   10628             :     nsCOMPtr<nsIRunnable> ev =
   10629             :       new InternalLoadEvent(this, aURI, aOriginalURI, aResultPrincipalURI,
   10630             :                             aLoadReplace, aReferrer, aReferrerPolicy,
   10631             :                             aTriggeringPrincipal, principalToInherit,
   10632             :                             aFlags, aTypeHint, aPostData, aHeadersData,
   10633             :                             aLoadType, aSHEntry, aFirstParty, aSrcdoc,
   10634           0 :                             aSourceDocShell, aBaseURI, false);
   10635             :     // We don't need any success handler since in that case
   10636             :     // OnPartialSHistoryDeactive would be called, and it would ensure
   10637             :     // docshell loads about:blank.
   10638           0 :     bool shouldSwitch = false;
   10639           0 :     rv = browserChrome3->ShouldSwitchToPrerenderedDocument(
   10640           0 :       aURI, mCurrentURI, nullptr, ev, &shouldSwitch);
   10641           0 :     if (NS_SUCCEEDED(rv) && shouldSwitch) {
   10642           0 :       return NS_OK;
   10643             :     }
   10644             :   }
   10645             : 
   10646             :   // Whenever a top-level browsing context is navigated, the user agent MUST
   10647             :   // lock the orientation of the document to the document's default
   10648             :   // orientation. We don't explicitly check for a top-level browsing context
   10649             :   // here because orientation is only set on top-level browsing contexts.
   10650           6 :   if (OrientationLock() != eScreenOrientation_None) {
   10651             : #ifdef DEBUG
   10652           0 :     nsCOMPtr<nsIDocShellTreeItem> parent;
   10653           0 :     GetSameTypeParent(getter_AddRefs(parent));
   10654           0 :     MOZ_ASSERT(!parent);
   10655             : #endif
   10656           0 :     SetOrientationLock(eScreenOrientation_None);
   10657           0 :     if (mIsActive) {
   10658           0 :       ScreenOrientation::UpdateActiveOrientationLock(eScreenOrientation_None);
   10659             :     }
   10660             :   }
   10661             : 
   10662             :   // Check for saving the presentation here, before calling Stop().
   10663             :   // This is necessary so that we can catch any pending requests.
   10664             :   // Since the new request has not been created yet, we pass null for the
   10665             :   // new request parameter.
   10666             :   // Also pass nullptr for the document, since it doesn't affect the return
   10667             :   // value for our purposes here.
   10668           6 :   bool savePresentation = CanSavePresentation(aLoadType, nullptr, nullptr);
   10669             : 
   10670             :   // Don't stop current network activity for javascript: URL's since
   10671             :   // they might not result in any data, and thus nothing should be
   10672             :   // stopped in those cases. In the case where they do result in
   10673             :   // data, the javascript: URL channel takes care of stopping
   10674             :   // current network activity.
   10675           6 :   if (!isJavaScript && aFileName.IsVoid()) {
   10676             :     // Stop any current network activity.
   10677             :     // Also stop content if this is a zombie doc. otherwise
   10678             :     // the onload will be delayed by other loads initiated in the
   10679             :     // background by the first document that
   10680             :     // didn't fully load before the next load was initiated.
   10681             :     // If not a zombie, don't stop content until data
   10682             :     // starts arriving from the new URI...
   10683             : 
   10684          12 :     nsCOMPtr<nsIContentViewer> zombieViewer;
   10685           6 :     if (mContentViewer) {
   10686           5 :       mContentViewer->GetPreviousViewer(getter_AddRefs(zombieViewer));
   10687             :     }
   10688             : 
   10689          12 :     if (zombieViewer ||
   10690          12 :         LOAD_TYPE_HAS_FLAGS(aLoadType, LOAD_FLAGS_STOP_CONTENT)) {
   10691           0 :       rv = Stop(nsIWebNavigation::STOP_ALL);
   10692             :     } else {
   10693           6 :       rv = Stop(nsIWebNavigation::STOP_NETWORK);
   10694             :     }
   10695             : 
   10696           6 :     if (NS_FAILED(rv)) {
   10697           0 :       return rv;
   10698             :     }
   10699             :   }
   10700             : 
   10701           6 :   mLoadType = aLoadType;
   10702             : 
   10703             :   // mLSHE should be assigned to aSHEntry, only after Stop() has
   10704             :   // been called. But when loading an error page, do not clear the
   10705             :   // mLSHE for the real page.
   10706           6 :   if (mLoadType != LOAD_ERROR_PAGE) {
   10707           6 :     SetHistoryEntry(&mLSHE, aSHEntry);
   10708             :   }
   10709             : 
   10710           6 :   mSavingOldViewer = savePresentation;
   10711             : 
   10712             :   // If we have a saved content viewer in history, restore and show it now.
   10713           6 :   if (aSHEntry && (mLoadType & LOAD_CMD_HISTORY)) {
   10714             :     // Make sure our history ID points to the same ID as
   10715             :     // SHEntry's docshell ID.
   10716           0 :     mHistoryID = aSHEntry->DocshellID();
   10717             : 
   10718             :     // It's possible that the previous viewer of mContentViewer is the
   10719             :     // viewer that will end up in aSHEntry when it gets closed.  If that's
   10720             :     // the case, we need to go ahead and force it into its shentry so we
   10721             :     // can restore it.
   10722           0 :     if (mContentViewer) {
   10723           0 :       nsCOMPtr<nsIContentViewer> prevViewer;
   10724           0 :       mContentViewer->GetPreviousViewer(getter_AddRefs(prevViewer));
   10725           0 :       if (prevViewer) {
   10726             : #ifdef DEBUG
   10727           0 :         nsCOMPtr<nsIContentViewer> prevPrevViewer;
   10728           0 :         prevViewer->GetPreviousViewer(getter_AddRefs(prevPrevViewer));
   10729           0 :         NS_ASSERTION(!prevPrevViewer, "Should never have viewer chain here");
   10730             : #endif
   10731           0 :         nsCOMPtr<nsISHEntry> viewerEntry;
   10732           0 :         prevViewer->GetHistoryEntry(getter_AddRefs(viewerEntry));
   10733           0 :         if (viewerEntry == aSHEntry) {
   10734             :           // Make sure this viewer ends up in the right place
   10735           0 :           mContentViewer->SetPreviousViewer(nullptr);
   10736           0 :           prevViewer->Destroy();
   10737             :         }
   10738             :       }
   10739             :     }
   10740           0 :     nsCOMPtr<nsISHEntry> oldEntry = mOSHE;
   10741             :     bool restoring;
   10742           0 :     rv = RestorePresentation(aSHEntry, &restoring);
   10743           0 :     if (restoring) {
   10744           0 :       return rv;
   10745             :     }
   10746             : 
   10747             :     // We failed to restore the presentation, so clean up.
   10748             :     // Both the old and new history entries could potentially be in
   10749             :     // an inconsistent state.
   10750           0 :     if (NS_FAILED(rv)) {
   10751           0 :       if (oldEntry) {
   10752           0 :         oldEntry->SyncPresentationState();
   10753             :       }
   10754             : 
   10755           0 :       aSHEntry->SyncPresentationState();
   10756             :     }
   10757             :   }
   10758             : 
   10759          12 :   nsAutoString srcdoc;
   10760           6 :   if (aFlags & INTERNAL_LOAD_FLAGS_IS_SRCDOC) {
   10761           0 :     srcdoc = aSrcdoc;
   10762             :   } else {
   10763           6 :     srcdoc = NullString();
   10764             :   }
   10765             : 
   10766           9 :   bool isTopLevelDoc = mItemType == typeContent &&
   10767           0 :                        (isTargetTopLevelDocShell ||
   10768           6 :                         GetIsMozBrowser());
   10769             : 
   10770          12 :   OriginAttributes attrs = GetOriginAttributes();
   10771           6 :   attrs.SetFirstPartyDomain(isTopLevelDoc, aURI);
   10772             : 
   10773             :   net::PredictorLearn(aURI, nullptr,
   10774           6 :                       nsINetworkPredictor::LEARN_LOAD_TOPLEVEL, attrs);
   10775             :   net::PredictorPredict(aURI, nullptr,
   10776           6 :                         nsINetworkPredictor::PREDICT_LOAD, attrs, nullptr);
   10777             : 
   10778          12 :   nsCOMPtr<nsIRequest> req;
   10779          30 :   rv = DoURILoad(aURI, aOriginalURI, aResultPrincipalURI, aLoadReplace, aReferrer,
   10780           6 :                  !(aFlags & INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER),
   10781             :                  aReferrerPolicy,
   10782             :                  aTriggeringPrincipal, principalToInherit, aTypeHint,
   10783             :                  aFileName, aPostData, aHeadersData,
   10784          12 :                  aFirstParty, aDocShell, getter_AddRefs(req),
   10785           6 :                  (aFlags & INTERNAL_LOAD_FLAGS_FIRST_LOAD) != 0,
   10786           6 :                  (aFlags & INTERNAL_LOAD_FLAGS_BYPASS_CLASSIFIER) != 0,
   10787           6 :                  (aFlags & INTERNAL_LOAD_FLAGS_FORCE_ALLOW_COOKIES) != 0,
   10788             :                  srcdoc, aBaseURI, contentType);
   10789           6 :   if (req && aRequest) {
   10790           0 :     NS_ADDREF(*aRequest = req);
   10791             :   }
   10792             : 
   10793           6 :   if (NS_FAILED(rv)) {
   10794           0 :     nsCOMPtr<nsIChannel> chan(do_QueryInterface(req));
   10795           0 :     if (DisplayLoadError(rv, aURI, nullptr, chan) &&
   10796           0 :         (aFlags & LOAD_FLAGS_ERROR_LOAD_CHANGES_RV) != 0) {
   10797           0 :       return NS_ERROR_LOAD_SHOWED_ERRORPAGE;
   10798             :     }
   10799             :   }
   10800             : 
   10801           6 :   return rv;
   10802             : }
   10803             : 
   10804             : nsIPrincipal*
   10805           2 : nsDocShell::GetInheritedPrincipal(bool aConsiderCurrentDocument)
   10806             : {
   10807           4 :   nsCOMPtr<nsIDocument> document;
   10808           2 :   bool inheritedFromCurrent = false;
   10809             : 
   10810           2 :   if (aConsiderCurrentDocument && mContentViewer) {
   10811           0 :     document = mContentViewer->GetDocument();
   10812           0 :     inheritedFromCurrent = true;
   10813             :   }
   10814             : 
   10815           2 :   if (!document) {
   10816           4 :     nsCOMPtr<nsIDocShellTreeItem> parentItem;
   10817           2 :     GetSameTypeParent(getter_AddRefs(parentItem));
   10818           2 :     if (parentItem) {
   10819           0 :       document = parentItem->GetDocument();
   10820             :     }
   10821             :   }
   10822             : 
   10823           2 :   if (!document) {
   10824           2 :     if (!aConsiderCurrentDocument) {
   10825           2 :       return nullptr;
   10826             :     }
   10827             : 
   10828             :     // Make sure we end up with _something_ as the principal no matter
   10829             :     // what.If this fails, we'll just get a null docViewer and bail.
   10830           0 :     EnsureContentViewer();
   10831           0 :     if (!mContentViewer) {
   10832           0 :       return nullptr;
   10833             :     }
   10834           0 :     document = mContentViewer->GetDocument();
   10835             :   }
   10836             : 
   10837             :   //-- Get the document's principal
   10838           0 :   if (document) {
   10839           0 :     nsIPrincipal* docPrincipal = document->NodePrincipal();
   10840             : 
   10841             :     // Don't allow loads in typeContent docShells to inherit the system
   10842             :     // principal from existing documents.
   10843           0 :     if (inheritedFromCurrent &&
   10844           0 :         mItemType == typeContent &&
   10845           0 :         nsContentUtils::IsSystemPrincipal(docPrincipal)) {
   10846           0 :       return nullptr;
   10847             :     }
   10848             : 
   10849           0 :     return docPrincipal;
   10850             :   }
   10851             : 
   10852           0 :   return nullptr;
   10853             : }
   10854             : 
   10855             : nsresult
   10856           6 : nsDocShell::DoURILoad(nsIURI* aURI,
   10857             :                       nsIURI* aOriginalURI,
   10858             :                       Maybe<nsCOMPtr<nsIURI>> const& aResultPrincipalURI,
   10859             :                       bool aLoadReplace,
   10860             :                       nsIURI* aReferrerURI,
   10861             :                       bool aSendReferrer,
   10862             :                       uint32_t aReferrerPolicy,
   10863             :                       nsIPrincipal* aTriggeringPrincipal,
   10864             :                       nsIPrincipal* aPrincipalToInherit,
   10865             :                       const char* aTypeHint,
   10866             :                       const nsAString& aFileName,
   10867             :                       nsIInputStream* aPostData,
   10868             :                       nsIInputStream* aHeadersData,
   10869             :                       bool aFirstParty,
   10870             :                       nsIDocShell** aDocShell,
   10871             :                       nsIRequest** aRequest,
   10872             :                       bool aIsNewWindowTarget,
   10873             :                       bool aBypassClassifier,
   10874             :                       bool aForceAllowCookies,
   10875             :                       const nsAString& aSrcdoc,
   10876             :                       nsIURI* aBaseURI,
   10877             :                       nsContentPolicyType aContentPolicyType)
   10878             : {
   10879             :   // Double-check that we're still around to load this URI.
   10880           6 :   if (mIsBeingDestroyed) {
   10881             :     // Return NS_OK despite not doing anything to avoid throwing exceptions from
   10882             :     // nsLocation::SetHref if the unload handler of the existing page tears us
   10883             :     // down.
   10884           0 :     return NS_OK;
   10885             :   }
   10886             : 
   10887             :   nsresult rv;
   10888          12 :   nsCOMPtr<nsIURILoader> uriLoader = do_GetService(NS_URI_LOADER_CONTRACTID, &rv);
   10889           6 :   if (NS_FAILED(rv)) {
   10890           0 :     return rv;
   10891             :   }
   10892             : 
   10893           6 :   if (IsFrame()) {
   10894             : 
   10895           1 :     MOZ_ASSERT(aContentPolicyType == nsIContentPolicy::TYPE_INTERNAL_IFRAME ||
   10896             :                aContentPolicyType == nsIContentPolicy::TYPE_INTERNAL_FRAME,
   10897             :                "DoURILoad thinks this is a frame and InternalLoad does not");
   10898             : 
   10899             :     // Only allow view-source scheme in top-level docshells. view-source is
   10900             :     // the only scheme to which this applies at the moment due to potential
   10901             :     // timing attacks to read data from cross-origin iframes. If this widens
   10902             :     // we should add a protocol flag for whether the scheme is allowed in
   10903             :     // frames and use something like nsNetUtil::NS_URIChainHasFlags.
   10904           2 :     nsCOMPtr<nsIURI> tempURI = aURI;
   10905           2 :     nsCOMPtr<nsINestedURI> nestedURI = do_QueryInterface(tempURI);
   10906           3 :     while (nestedURI) {
   10907             :       // view-source should always be an nsINestedURI, loop and check the
   10908             :       // scheme on this and all inner URIs that are also nested URIs.
   10909           1 :       bool isViewSource = false;
   10910           1 :       rv = tempURI->SchemeIs("view-source", &isViewSource);
   10911           1 :       if (NS_FAILED(rv) || isViewSource) {
   10912           0 :         return NS_ERROR_UNKNOWN_PROTOCOL;
   10913             :       }
   10914           1 :       nestedURI->GetInnerURI(getter_AddRefs(tempURI));
   10915           1 :       nestedURI = do_QueryInterface(tempURI);
   10916             :     }
   10917             :   } else {
   10918           5 :     MOZ_ASSERT(aContentPolicyType == nsIContentPolicy::TYPE_DOCUMENT,
   10919             :     "DoURILoad thinks this is a document and InternalLoad does not");
   10920             :   }
   10921             : 
   10922             :   // open a channel for the url
   10923          12 :   nsCOMPtr<nsIChannel> channel;
   10924             : 
   10925           6 :   bool isSrcdoc = !aSrcdoc.IsVoid();
   10926             : 
   10927             :   // There are two cases we care about:
   10928             :   // * Top-level load: In this case, loadingNode is null, but loadingWindow
   10929             :   //   is our mScriptGlobal. We pass null for loadingPrincipal in this case.
   10930             :   // * Subframe load: loadingWindow is null, but loadingNode is the frame
   10931             :   //   element for the load. loadingPrincipal is the NodePrincipal of the frame
   10932             :   //   element.
   10933          12 :   nsCOMPtr<nsINode> loadingNode;
   10934          12 :   nsCOMPtr<nsPIDOMWindowOuter> loadingWindow;
   10935          12 :   nsCOMPtr<nsIPrincipal> loadingPrincipal;
   10936             : 
   10937           6 :   if (aContentPolicyType == nsIContentPolicy::TYPE_DOCUMENT) {
   10938           5 :     loadingNode = nullptr;
   10939           5 :     loadingPrincipal = nullptr;
   10940           5 :     loadingWindow = mScriptGlobal->AsOuter();
   10941             :   } else {
   10942           1 :     loadingWindow = nullptr;
   10943           1 :     loadingNode = mScriptGlobal->AsOuter()->GetFrameElementInternal();
   10944           1 :     if (loadingNode) {
   10945             :       // If we have a loading node, then use that as our loadingPrincipal.
   10946           1 :       loadingPrincipal = loadingNode->NodePrincipal();
   10947             :     } else {
   10948             :       // If this isn't a top-level load and mScriptGlobal's frame element is
   10949             :       // null, then the element got removed from the DOM while we were trying
   10950             :       // to load this resource. This docshell is scheduled for destruction
   10951             :       // already, so bail out here.
   10952           0 :       return NS_OK;
   10953             :     }
   10954             :   }
   10955             : 
   10956             :   // Getting the right triggeringPrincipal needs to be updated and is only
   10957             :   // ready for use once bug 1182569 landed. Until then, we cannot rely on
   10958             :   // the triggeringPrincipal for TYPE_DOCUMENT loads.
   10959           6 :   MOZ_ASSERT(aTriggeringPrincipal, "Need a valid triggeringPrincipal");
   10960             : 
   10961           6 :   bool isSandBoxed = mSandboxFlags & SANDBOXED_ORIGIN;
   10962             :   // only inherit if we have a aPrincipalToInherit
   10963           6 :   bool inherit = false;
   10964             : 
   10965           6 :   if (aPrincipalToInherit) {
   10966             :     bool isData;
   10967           4 :     bool isURIUniqueOrigin = nsIOService::IsDataURIUniqueOpaqueOrigin() &&
   10968           4 :                              NS_SUCCEEDED(aURI->SchemeIs("data", &isData)) &&
   10969           4 :                              isData;
   10970             :     // If aURI is data: URI and is treated as a unique opaque origin, we don't
   10971             :     // want to inherit principal.
   10972           8 :     inherit = nsContentUtils::ChannelShouldInheritPrincipal(
   10973             :       aPrincipalToInherit,
   10974             :       aURI,
   10975             :       true, // aInheritForAboutBlank
   10976           4 :       isSrcdoc) && !isURIUniqueOrigin ;
   10977             :   }
   10978             : 
   10979           6 :   nsLoadFlags loadFlags = mDefaultLoadFlags;
   10980             :   nsSecurityFlags securityFlags =
   10981           6 :     nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL;
   10982             : 
   10983           6 :   if (aFirstParty) {
   10984             :     // tag first party URL loads
   10985           4 :     loadFlags |= nsIChannel::LOAD_INITIAL_DOCUMENT_URI;
   10986             :   }
   10987             : 
   10988           6 :   if (mLoadType == LOAD_ERROR_PAGE) {
   10989             :     // Error pages are LOAD_BACKGROUND
   10990           0 :     loadFlags |= nsIChannel::LOAD_BACKGROUND;
   10991           0 :     securityFlags |= nsILoadInfo::SEC_LOAD_ERROR_PAGE;
   10992             :   }
   10993             : 
   10994           6 :   if (inherit) {
   10995           2 :     securityFlags |= nsILoadInfo::SEC_FORCE_INHERIT_PRINCIPAL;
   10996             :   }
   10997           6 :   if (isSandBoxed) {
   10998           0 :     securityFlags |= nsILoadInfo::SEC_SANDBOXED;
   10999             :   }
   11000             : 
   11001             :   nsCOMPtr<nsILoadInfo> loadInfo =
   11002             :     (aContentPolicyType == nsIContentPolicy::TYPE_DOCUMENT) ?
   11003             :       new LoadInfo(loadingWindow, aTriggeringPrincipal,
   11004          10 :                    securityFlags) :
   11005             :       new LoadInfo(loadingPrincipal, aTriggeringPrincipal, loadingNode,
   11006          18 :                    securityFlags, aContentPolicyType);
   11007             : 
   11008           6 :   if (aContentPolicyType == nsIContentPolicy::TYPE_DOCUMENT) {
   11009             :     enum TopLevelDataState {
   11010             :       DATA_NAVIGATED = 0,
   11011             :       DATA_TYPED = 1,
   11012             :       NO_DATA = 2,
   11013             :     };
   11014           5 :     bool isDataURI = (NS_SUCCEEDED(aURI->SchemeIs("data", &isDataURI)) && isDataURI);
   11015           5 :     if (isDataURI) {
   11016             :       // In all cases where the toplevel document is navigated to a data: URI
   11017             :       // the triggeringPrincipal is a CodeBasePrincipal. In all other cases
   11018             :       // e.g. typing a data: URL into the URL-Bar or also clicking a bookmark
   11019             :       // uses a SystemPrincipal as the triggeringPrincipal.
   11020           0 :       if (aTriggeringPrincipal->GetIsCodebasePrincipal()) {
   11021           0 :         Telemetry::Accumulate(Telemetry::DOCUMENT_DATA_URI_LOADS, DATA_NAVIGATED);
   11022             :       } else {
   11023           0 :         Telemetry::Accumulate(Telemetry::DOCUMENT_DATA_URI_LOADS, DATA_TYPED);
   11024             :       }
   11025             :     } else {
   11026           5 :       Telemetry::Accumulate(Telemetry::DOCUMENT_DATA_URI_LOADS, NO_DATA);
   11027             :     }
   11028             :   }
   11029             : 
   11030           6 :   if (aPrincipalToInherit) {
   11031           4 :     loadInfo->SetPrincipalToInherit(aPrincipalToInherit);
   11032             :   }
   11033             : 
   11034             :   // We have to do this in case our OriginAttributes are different from the
   11035             :   // OriginAttributes of the parent document. Or in case there isn't a
   11036             :   // parent document.
   11037           9 :   bool isTopLevelDoc = mItemType == typeContent &&
   11038           0 :                        (aContentPolicyType == nsIContentPolicy::TYPE_DOCUMENT ||
   11039           6 :                         GetIsMozBrowser());
   11040             : 
   11041          12 :   OriginAttributes attrs;
   11042             : 
   11043             :   // If inherit is true, which means loadInfo will have SEC_FORCE_INHERIT_PRINCIPAL
   11044             :   // set, so later when we create principal of the document from
   11045             :   // nsScriptSecurityManager::GetChannelResultPrincipal, we will use
   11046             :   // principalToInherit of the loadInfo as the document principal.
   11047             :   // Therefore we use the origin attributes from aPrincipalToInherit.
   11048             :   //
   11049             :   // Otherwise we just use the origin attributes from docshell.
   11050           6 :   if (inherit) {
   11051           2 :     MOZ_ASSERT(aPrincipalToInherit, "We should have aPrincipalToInherit here.");
   11052           2 :     attrs = aPrincipalToInherit->OriginAttributesRef();
   11053             :     // If firstPartyIsolation is not enabled, then PrincipalToInherit should
   11054             :     // have the same origin attributes with docshell.
   11055           2 :     MOZ_ASSERT_IF(!OriginAttributes::IsFirstPartyEnabled(), attrs == GetOriginAttributes());
   11056             :   } else {
   11057           4 :     attrs = GetOriginAttributes();
   11058           4 :     attrs.SetFirstPartyDomain(isTopLevelDoc, aURI);
   11059             :   }
   11060             : 
   11061           6 :   rv = loadInfo->SetOriginAttributes(attrs);
   11062           6 :   if (NS_WARN_IF(NS_FAILED(rv))) {
   11063           0 :     return rv;
   11064             :   }
   11065             : 
   11066           6 :   if (!isSrcdoc) {
   11067           6 :     rv = NS_NewChannelInternal(getter_AddRefs(channel),
   11068             :                                aURI,
   11069             :                                loadInfo,
   11070             :                                nullptr,   // loadGroup
   11071             :                                static_cast<nsIInterfaceRequestor*>(this),
   11072             :                                loadFlags);
   11073             : 
   11074           6 :     if (NS_FAILED(rv)) {
   11075           0 :       if (rv == NS_ERROR_UNKNOWN_PROTOCOL) {
   11076             :         // This is a uri with a protocol scheme we don't know how
   11077             :         // to handle.  Embedders might still be interested in
   11078             :         // handling the load, though, so we fire a notification
   11079             :         // before throwing the load away.
   11080           0 :         bool abort = false;
   11081           0 :         nsresult rv2 = mContentListener->OnStartURIOpen(aURI, &abort);
   11082           0 :         if (NS_SUCCEEDED(rv2) && abort) {
   11083             :           // Hey, they're handling the load for us!  How convenient!
   11084           0 :           return NS_OK;
   11085             :         }
   11086             :       }
   11087           0 :       return rv;
   11088             :     }
   11089             : 
   11090           6 :     if (aBaseURI) {
   11091           0 :         nsCOMPtr<nsIViewSourceChannel> vsc = do_QueryInterface(channel);
   11092           0 :         if (vsc) {
   11093           0 :             rv = vsc->SetBaseURI(aBaseURI);
   11094           0 :             MOZ_ASSERT(NS_SUCCEEDED(rv));
   11095             :         }
   11096             :     }
   11097             :   } else {
   11098           0 :     nsAutoCString scheme;
   11099           0 :     rv = aURI->GetScheme(scheme);
   11100           0 :     NS_ENSURE_SUCCESS(rv, rv);
   11101             :     bool isViewSource;
   11102           0 :     aURI->SchemeIs("view-source", &isViewSource);
   11103             : 
   11104           0 :     if (isViewSource) {
   11105           0 :       nsViewSourceHandler* vsh = nsViewSourceHandler::GetInstance();
   11106           0 :       NS_ENSURE_TRUE(vsh, NS_ERROR_FAILURE);
   11107             : 
   11108           0 :       rv = vsh->NewSrcdocChannel(aURI, aBaseURI, aSrcdoc,
   11109           0 :                                  loadInfo, getter_AddRefs(channel));
   11110             :     } else {
   11111           0 :       rv = NS_NewInputStreamChannelInternal(getter_AddRefs(channel),
   11112             :                                             aURI,
   11113             :                                             aSrcdoc,
   11114           0 :                                             NS_LITERAL_CSTRING("text/html"),
   11115             :                                             loadInfo,
   11116           0 :                                             true);
   11117           0 :       NS_ENSURE_SUCCESS(rv, rv);
   11118           0 :       nsCOMPtr<nsIInputStreamChannel> isc = do_QueryInterface(channel);
   11119           0 :       MOZ_ASSERT(isc);
   11120           0 :       isc->SetBaseURI(aBaseURI);
   11121             :     }
   11122             :   }
   11123             : 
   11124             :   // Navigational requests that are same origin need to be upgraded in case
   11125             :   // upgrade-insecure-requests is present. Please note that in that case
   11126             :   // the triggeringPrincipal is holding the CSP that potentially
   11127             :   // holds upgrade-insecure-requests.
   11128          12 :   nsCOMPtr<nsIContentSecurityPolicy> csp;
   11129           6 :   aTriggeringPrincipal->GetCsp(getter_AddRefs(csp));
   11130           6 :   if (csp) {
   11131           0 :     bool upgradeInsecureRequests = false;
   11132           0 :     csp->GetUpgradeInsecureRequests(&upgradeInsecureRequests);
   11133           0 :     if (upgradeInsecureRequests) {
   11134             :       // only upgrade if the navigation is same origin
   11135           0 :       nsCOMPtr<nsIPrincipal> resultPrincipal;
   11136           0 :       rv = nsContentUtils::GetSecurityManager()->
   11137           0 :              GetChannelResultPrincipal(channel,
   11138           0 :                                        getter_AddRefs(resultPrincipal));
   11139           0 :       NS_ENSURE_SUCCESS(rv, rv);
   11140           0 :       if (resultPrincipal->Equals(aTriggeringPrincipal)) {
   11141           0 :         static_cast<mozilla::LoadInfo*>(loadInfo.get())->SetUpgradeInsecureRequests();
   11142             :       }
   11143             :     }
   11144             :   }
   11145             : 
   11146             : 
   11147             :   nsCOMPtr<nsIApplicationCacheChannel> appCacheChannel =
   11148          12 :     do_QueryInterface(channel);
   11149           6 :   if (appCacheChannel) {
   11150             :     // Any document load should not inherit application cache.
   11151           1 :     appCacheChannel->SetInheritApplicationCache(false);
   11152             : 
   11153             :     // Loads with the correct permissions should check for a matching
   11154             :     // application cache.
   11155           1 :     if (GeckoProcessType_Default != XRE_GetProcessType()) {
   11156             :       // Permission will be checked in the parent process
   11157           1 :       appCacheChannel->SetChooseApplicationCache(true);
   11158             :     } else {
   11159             :       nsCOMPtr<nsIScriptSecurityManager> secMan =
   11160           0 :         do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID);
   11161             : 
   11162           0 :       if (secMan) {
   11163           0 :         nsCOMPtr<nsIPrincipal> principal;
   11164           0 :         secMan->GetDocShellCodebasePrincipal(aURI, this,
   11165           0 :                                              getter_AddRefs(principal));
   11166           0 :         appCacheChannel->SetChooseApplicationCache(
   11167           0 :           NS_ShouldCheckAppCache(principal));
   11168             :       }
   11169             :     }
   11170             :   }
   11171             : 
   11172             :   // Make sure to give the caller a channel if we managed to create one
   11173             :   // This is important for correct error page/session history interaction
   11174           6 :   if (aRequest) {
   11175           6 :     NS_ADDREF(*aRequest = channel);
   11176             :   }
   11177             : 
   11178           6 :   if (aOriginalURI) {
   11179           0 :     channel->SetOriginalURI(aOriginalURI);
   11180             :     // The LOAD_REPLACE flag and its handling here will be removed as part
   11181             :     // of bug 1319110.  For now preserve its restoration here to not break
   11182             :     // any code expecting it being set specially on redirected channels.
   11183             :     // If the flag has originally been set to change result of
   11184             :     // NS_GetFinalChannelURI it won't have any effect and also won't cause
   11185             :     // any harm.
   11186           0 :     if (aLoadReplace) {
   11187             :       uint32_t loadFlags;
   11188           0 :       channel->GetLoadFlags(&loadFlags);
   11189           0 :       NS_ENSURE_SUCCESS(rv, rv);
   11190           0 :       channel->SetLoadFlags(loadFlags | nsIChannel::LOAD_REPLACE);
   11191             :     }
   11192             :   } else {
   11193           6 :     channel->SetOriginalURI(aURI);
   11194             :   }
   11195             : 
   11196           6 :   if (aResultPrincipalURI) {
   11197             :     // Unconditionally override, we want the replay to be equal to what has
   11198             :     // been captured.
   11199           0 :     loadInfo->SetResultPrincipalURI(aResultPrincipalURI.ref());
   11200             :   }
   11201             : 
   11202           6 :   if (aTypeHint && *aTypeHint) {
   11203           0 :     channel->SetContentType(nsDependentCString(aTypeHint));
   11204           0 :     mContentTypeHint = aTypeHint;
   11205             :   } else {
   11206           6 :     mContentTypeHint.Truncate();
   11207             :   }
   11208             : 
   11209           6 :   if (!aFileName.IsVoid()) {
   11210           0 :     rv = channel->SetContentDisposition(nsIChannel::DISPOSITION_ATTACHMENT);
   11211           0 :     NS_ENSURE_SUCCESS(rv, rv);
   11212           0 :     if (!aFileName.IsEmpty()) {
   11213           0 :       rv = channel->SetContentDispositionFilename(aFileName);
   11214           0 :       NS_ENSURE_SUCCESS(rv, rv);
   11215             :     }
   11216             :   }
   11217             : 
   11218          12 :   if (mLoadType == LOAD_NORMAL_ALLOW_MIXED_CONTENT ||
   11219           6 :       mLoadType == LOAD_RELOAD_ALLOW_MIXED_CONTENT) {
   11220           0 :     rv = SetMixedContentChannel(channel);
   11221           0 :     NS_ENSURE_SUCCESS(rv, rv);
   11222           6 :   } else if (mMixedContentChannel) {
   11223             :     /*
   11224             :      * If the user "Disables Protection on This Page", we call
   11225             :      * SetMixedContentChannel for the first time, otherwise
   11226             :      * mMixedContentChannel is still null.
   11227             :      * Later, if the new channel passes a same orign check, we remember the
   11228             :      * users decision by calling SetMixedContentChannel using the new channel.
   11229             :      * This way, the user does not have to click the disable protection button
   11230             :      * over and over for browsing the same site.
   11231             :      */
   11232           0 :     rv = nsContentUtils::CheckSameOrigin(mMixedContentChannel, channel);
   11233           0 :     if (NS_FAILED(rv) || NS_FAILED(SetMixedContentChannel(channel))) {
   11234           0 :       SetMixedContentChannel(nullptr);
   11235             :     }
   11236             :   }
   11237             : 
   11238             :   // hack
   11239          12 :   nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel));
   11240             :   nsCOMPtr<nsIHttpChannelInternal> httpChannelInternal(
   11241          12 :     do_QueryInterface(channel));
   11242           6 :   if (httpChannelInternal) {
   11243           1 :     if (aForceAllowCookies) {
   11244           0 :       rv = httpChannelInternal->SetThirdPartyFlags(
   11245           0 :         nsIHttpChannelInternal::THIRD_PARTY_FORCE_ALLOW);
   11246           0 :       MOZ_ASSERT(NS_SUCCEEDED(rv));
   11247             :     }
   11248           1 :     if (aFirstParty) {
   11249           1 :       rv = httpChannelInternal->SetDocumentURI(aURI);
   11250           1 :       MOZ_ASSERT(NS_SUCCEEDED(rv));
   11251             :     } else {
   11252           0 :       rv = httpChannelInternal->SetDocumentURI(aReferrerURI);
   11253           0 :       MOZ_ASSERT(NS_SUCCEEDED(rv));
   11254             :     }
   11255           2 :     rv = httpChannelInternal->SetRedirectMode(
   11256           1 :       nsIHttpChannelInternal::REDIRECT_MODE_MANUAL);
   11257           1 :     MOZ_ASSERT(NS_SUCCEEDED(rv));
   11258             :   }
   11259             : 
   11260          12 :   nsCOMPtr<nsIWritablePropertyBag2> props(do_QueryInterface(channel));
   11261           6 :   if (props) {
   11262             :     // save true referrer for those who need it (e.g. xpinstall whitelisting)
   11263             :     // Currently only http and ftp channels support this.
   11264          24 :     props->SetPropertyAsInterface(NS_LITERAL_STRING("docshell.internalReferrer"),
   11265          18 :                                   aReferrerURI);
   11266             :   }
   11267             : 
   11268          12 :   nsCOMPtr<nsICacheInfoChannel> cacheChannel(do_QueryInterface(channel));
   11269             :   /* Get the cache Key from SH */
   11270          12 :   nsCOMPtr<nsISupports> cacheKey;
   11271           6 :   if (cacheChannel) {
   11272           1 :     if (mLSHE) {
   11273           0 :       mLSHE->GetCacheKey(getter_AddRefs(cacheKey));
   11274           1 :     } else if (mOSHE) {  // for reload cases
   11275           0 :       mOSHE->GetCacheKey(getter_AddRefs(cacheKey));
   11276             :     }
   11277             :   }
   11278             : 
   11279             :   // figure out if we need to set the post data stream on the channel...
   11280           6 :   if (aPostData) {
   11281           0 :     nsCOMPtr<nsIFormPOSTActionChannel> postChannel(do_QueryInterface(channel));
   11282           0 :     if (postChannel) {
   11283             :       // XXX it's a bit of a hack to rewind the postdata stream here but
   11284             :       // it has to be done in case the post data is being reused multiple
   11285             :       // times.
   11286             :       nsCOMPtr<nsISeekableStream> postDataSeekable =
   11287           0 :         do_QueryInterface(aPostData);
   11288           0 :       if (postDataSeekable) {
   11289           0 :         rv = postDataSeekable->Seek(nsISeekableStream::NS_SEEK_SET, 0);
   11290           0 :         NS_ENSURE_SUCCESS(rv, rv);
   11291             :       }
   11292             : 
   11293             :       // we really need to have a content type associated with this stream!!
   11294           0 :       postChannel->SetUploadStream(aPostData, EmptyCString(), -1);
   11295             :     }
   11296             : 
   11297             :     /* If there is a valid postdata *and* it is a History Load,
   11298             :      * set up the cache key on the channel, to retrieve the
   11299             :      * data *only* from the cache. If it is a normal reload, the
   11300             :      * cache is free to go to the server for updated postdata.
   11301             :      */
   11302           0 :     if (cacheChannel && cacheKey) {
   11303           0 :       if (mLoadType == LOAD_HISTORY ||
   11304           0 :           mLoadType == LOAD_RELOAD_CHARSET_CHANGE) {
   11305           0 :         cacheChannel->SetCacheKey(cacheKey);
   11306             :         uint32_t loadFlags;
   11307           0 :         if (NS_SUCCEEDED(channel->GetLoadFlags(&loadFlags))) {
   11308           0 :           channel->SetLoadFlags(
   11309           0 :             loadFlags | nsICachingChannel::LOAD_ONLY_FROM_CACHE);
   11310           0 :         }
   11311           0 :       } else if (mLoadType == LOAD_RELOAD_NORMAL) {
   11312           0 :         cacheChannel->SetCacheKey(cacheKey);
   11313             :       }
   11314             :     }
   11315             :   } else {
   11316             :     /* If there is no postdata, set the cache key on the channel, and
   11317             :      * do not set the LOAD_ONLY_FROM_CACHE flag, so that the channel
   11318             :      * will be free to get it from net if it is not found in cache.
   11319             :      * New cache may use it creatively on CGI pages with GET
   11320             :      * method and even on those that say "no-cache"
   11321             :      */
   11322          12 :     if (mLoadType == LOAD_HISTORY ||
   11323          12 :         mLoadType == LOAD_RELOAD_NORMAL ||
   11324           6 :         mLoadType == LOAD_RELOAD_CHARSET_CHANGE) {
   11325           0 :       if (cacheChannel && cacheKey) {
   11326           0 :         cacheChannel->SetCacheKey(cacheKey);
   11327             :       }
   11328             :     }
   11329             :   }
   11330             : 
   11331           6 :   if (httpChannel) {
   11332           1 :     if (aHeadersData) {
   11333           0 :       rv = AddHeadersToChannel(aHeadersData, httpChannel);
   11334             :     }
   11335             :     // Set the referrer explicitly
   11336           1 :     if (aReferrerURI && aSendReferrer) {
   11337             :       // Referrer is currenly only set for link clicks here.
   11338           0 :       rv = httpChannel->SetReferrerWithPolicy(aReferrerURI, aReferrerPolicy);
   11339           0 :       MOZ_ASSERT(NS_SUCCEEDED(rv));
   11340             :     }
   11341             :   }
   11342             : 
   11343          12 :   nsCOMPtr<nsIScriptChannel> scriptChannel = do_QueryInterface(channel);
   11344           6 :   if (scriptChannel) {
   11345             :     // Allow execution against our context if the principals match
   11346           0 :     scriptChannel->SetExecutionPolicy(nsIScriptChannel::EXECUTE_NORMAL);
   11347             :   }
   11348             : 
   11349           6 :   if (aIsNewWindowTarget) {
   11350           2 :     nsCOMPtr<nsIWritablePropertyBag2> props = do_QueryInterface(channel);
   11351           1 :     if (props) {
   11352           4 :       props->SetPropertyAsBool(NS_LITERAL_STRING("docshell.newWindowTarget"),
   11353           3 :                                true);
   11354             :     }
   11355             :   }
   11356             : 
   11357          12 :   nsCOMPtr<nsITimedChannel> timedChannel(do_QueryInterface(channel));
   11358           6 :   if (timedChannel) {
   11359           1 :     timedChannel->SetTimingEnabled(true);
   11360             : 
   11361           2 :     nsCOMPtr<nsPIDOMWindowOuter> win = GetWindow();
   11362           1 :     if (IsFrame() && win) {
   11363           0 :       nsCOMPtr<Element> frameElement = win->GetFrameElementInternal();
   11364           0 :       if (frameElement) {
   11365           0 :         timedChannel->SetInitiatorType(frameElement->LocalName());
   11366             :       }
   11367             :     }
   11368             :   }
   11369             : 
   11370             :   // Mark the http channel as UrgentStart for top level document loading
   11371             :   // in active tab.
   11372           6 :   if (mIsActive || (mLoadType & (LOAD_CMD_NORMAL | LOAD_CMD_HISTORY))) {
   11373           6 :     if (httpChannel && isTopLevelDoc) {
   11374           2 :       nsCOMPtr<nsIClassOfService> cos(do_QueryInterface(channel));
   11375           1 :       if (cos) {
   11376           1 :         cos->AddClassFlags(nsIClassOfService::UrgentStart);
   11377             :       }
   11378             :     }
   11379             :   }
   11380             : 
   11381           6 :   rv = DoChannelLoad(channel, uriLoader, aBypassClassifier);
   11382             : 
   11383             :   //
   11384             :   // If the channel load failed, we failed and nsIWebProgress just ain't
   11385             :   // gonna happen.
   11386             :   //
   11387           6 :   if (NS_SUCCEEDED(rv)) {
   11388           6 :     if (aDocShell) {
   11389           0 :       *aDocShell = this;
   11390           0 :       NS_ADDREF(*aDocShell);
   11391             :     }
   11392             :   }
   11393             : 
   11394           6 :   return rv;
   11395             : }
   11396             : 
   11397             : static nsresult
   11398           0 : AppendSegmentToString(nsIInputStream* aIn,
   11399             :                       void* aClosure,
   11400             :                       const char* aFromRawSegment,
   11401             :                       uint32_t aToOffset,
   11402             :                       uint32_t aCount,
   11403             :                       uint32_t* aWriteCount)
   11404             : {
   11405             :   // aFromSegment now contains aCount bytes of data.
   11406             : 
   11407           0 :   nsAutoCString* buf = static_cast<nsAutoCString*>(aClosure);
   11408           0 :   buf->Append(aFromRawSegment, aCount);
   11409             : 
   11410             :   // Indicate that we have consumed all of aFromSegment
   11411           0 :   *aWriteCount = aCount;
   11412           0 :   return NS_OK;
   11413             : }
   11414             : 
   11415             : nsresult
   11416           0 : nsDocShell::AddHeadersToChannel(nsIInputStream* aHeadersData,
   11417             :                                 nsIChannel* aGenericChannel)
   11418             : {
   11419           0 :   nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aGenericChannel);
   11420           0 :   NS_ENSURE_STATE(httpChannel);
   11421             : 
   11422             :   uint32_t numRead;
   11423           0 :   nsAutoCString headersString;
   11424             :   nsresult rv = aHeadersData->ReadSegments(AppendSegmentToString,
   11425             :                                            &headersString,
   11426             :                                            UINT32_MAX,
   11427           0 :                                            &numRead);
   11428           0 :   NS_ENSURE_SUCCESS(rv, rv);
   11429             : 
   11430             :   // used during the manipulation of the String from the InputStream
   11431           0 :   nsAutoCString headerName;
   11432           0 :   nsAutoCString headerValue;
   11433             :   int32_t crlf;
   11434             :   int32_t colon;
   11435             : 
   11436             :   //
   11437             :   // Iterate over the headersString: for each "\r\n" delimited chunk,
   11438             :   // add the value as a header to the nsIHttpChannel
   11439             :   //
   11440             : 
   11441             :   static const char kWhitespace[] = "\b\t\r\n ";
   11442             :   while (true) {
   11443           0 :     crlf = headersString.Find("\r\n");
   11444           0 :     if (crlf == kNotFound) {
   11445           0 :       return NS_OK;
   11446             :     }
   11447             : 
   11448           0 :     const nsACString& oneHeader = StringHead(headersString, crlf);
   11449             : 
   11450           0 :     colon = oneHeader.FindChar(':');
   11451           0 :     if (colon == kNotFound) {
   11452           0 :       return NS_ERROR_UNEXPECTED;
   11453             :     }
   11454             : 
   11455           0 :     headerName = StringHead(oneHeader, colon);
   11456           0 :     headerValue = Substring(oneHeader, colon + 1);
   11457             : 
   11458           0 :     headerName.Trim(kWhitespace);
   11459           0 :     headerValue.Trim(kWhitespace);
   11460             : 
   11461           0 :     headersString.Cut(0, crlf + 2);
   11462             : 
   11463             :     //
   11464             :     // FINALLY: we can set the header!
   11465             :     //
   11466             : 
   11467           0 :     rv = httpChannel->SetRequestHeader(headerName, headerValue, true);
   11468           0 :     NS_ENSURE_SUCCESS(rv, rv);
   11469           0 :   }
   11470             : 
   11471             :   NS_NOTREACHED("oops");
   11472             :   return NS_ERROR_UNEXPECTED;
   11473             : }
   11474             : 
   11475             : nsresult
   11476           6 : nsDocShell::DoChannelLoad(nsIChannel* aChannel,
   11477             :                           nsIURILoader* aURILoader,
   11478             :                           bool aBypassClassifier)
   11479             : {
   11480             :   nsresult rv;
   11481             :   // Mark the channel as being a document URI and allow content sniffing...
   11482           6 :   nsLoadFlags loadFlags = 0;
   11483           6 :   (void)aChannel->GetLoadFlags(&loadFlags);
   11484           6 :   loadFlags |= nsIChannel::LOAD_DOCUMENT_URI |
   11485           6 :                nsIChannel::LOAD_CALL_CONTENT_SNIFFERS;
   11486             : 
   11487             :   // Load attributes depend on load type...
   11488           6 :   switch (mLoadType) {
   11489             :     case LOAD_HISTORY: {
   11490             :       // Only send VALIDATE_NEVER if mLSHE's URI was never changed via
   11491             :       // push/replaceState (bug 669671).
   11492           0 :       bool uriModified = false;
   11493           0 :       if (mLSHE) {
   11494           0 :         mLSHE->GetURIWasModified(&uriModified);
   11495             :       }
   11496             : 
   11497           0 :       if (!uriModified) {
   11498           0 :         loadFlags |= nsIRequest::VALIDATE_NEVER;
   11499             :       }
   11500           0 :       break;
   11501             :     }
   11502             : 
   11503             :     case LOAD_RELOAD_CHARSET_CHANGE: {
   11504             :       // Use SetAllowStaleCacheContent (not LOAD_FROM_CACHE flag) since we only want
   11505             :       // to force cache load for this channel, not the whole loadGroup.
   11506           0 :       nsCOMPtr<nsICacheInfoChannel> cachingChannel = do_QueryInterface(aChannel);
   11507           0 :       if (cachingChannel) {
   11508           0 :         cachingChannel->SetAllowStaleCacheContent(true);
   11509             :       }
   11510           0 :       break;
   11511             :     }
   11512             : 
   11513             :     case LOAD_RELOAD_NORMAL:
   11514             :     case LOAD_REFRESH:
   11515           0 :       loadFlags |= nsIRequest::VALIDATE_ALWAYS;
   11516           0 :       break;
   11517             : 
   11518             :     case LOAD_NORMAL_BYPASS_CACHE:
   11519             :     case LOAD_NORMAL_BYPASS_PROXY:
   11520             :     case LOAD_NORMAL_BYPASS_PROXY_AND_CACHE:
   11521             :     case LOAD_NORMAL_ALLOW_MIXED_CONTENT:
   11522             :     case LOAD_RELOAD_BYPASS_CACHE:
   11523             :     case LOAD_RELOAD_BYPASS_PROXY:
   11524             :     case LOAD_RELOAD_BYPASS_PROXY_AND_CACHE:
   11525             :     case LOAD_RELOAD_ALLOW_MIXED_CONTENT:
   11526             :     case LOAD_REPLACE_BYPASS_CACHE:
   11527           0 :       loadFlags |= nsIRequest::LOAD_BYPASS_CACHE |
   11528           0 :                    nsIRequest::LOAD_FRESH_CONNECTION;
   11529           0 :       break;
   11530             : 
   11531             :     case LOAD_NORMAL:
   11532             :     case LOAD_LINK:
   11533             :       // Set cache checking flags
   11534           6 :       switch (Preferences::GetInt("browser.cache.check_doc_frequency", -1)) {
   11535             :         case 0:
   11536           0 :           loadFlags |= nsIRequest::VALIDATE_ONCE_PER_SESSION;
   11537           0 :           break;
   11538             :         case 1:
   11539           0 :           loadFlags |= nsIRequest::VALIDATE_ALWAYS;
   11540           0 :           break;
   11541             :         case 2:
   11542           0 :           loadFlags |= nsIRequest::VALIDATE_NEVER;
   11543           0 :           break;
   11544             :       }
   11545           6 :       break;
   11546             :   }
   11547             : 
   11548           6 :   if (!aBypassClassifier) {
   11549           6 :     loadFlags |= nsIChannel::LOAD_CLASSIFY_URI;
   11550             :   }
   11551             : 
   11552             :   // If the user pressed shift-reload, then do not allow ServiceWorker
   11553             :   // interception to occur. See step 12.1 of the SW HandleFetch algorithm.
   11554           6 :   if (IsForceReloadType(mLoadType)) {
   11555           0 :     loadFlags |= nsIChannel::LOAD_BYPASS_SERVICE_WORKER;
   11556             :   }
   11557             : 
   11558           6 :   (void)aChannel->SetLoadFlags(loadFlags);
   11559             : 
   11560           6 :   uint32_t openFlags = 0;
   11561           6 :   if (mLoadType == LOAD_LINK) {
   11562           0 :     openFlags |= nsIURILoader::IS_CONTENT_PREFERRED;
   11563             :   }
   11564           6 :   if (!mAllowContentRetargeting) {
   11565           0 :     openFlags |= nsIURILoader::DONT_RETARGET;
   11566             :   }
   11567           6 :   rv = aURILoader->OpenURI(aChannel, openFlags, this);
   11568           6 :   NS_ENSURE_SUCCESS(rv, rv);
   11569             : 
   11570           6 :   return NS_OK;
   11571             : }
   11572             : 
   11573             : nsresult
   11574           0 : nsDocShell::ScrollToAnchor(bool aCurHasRef, bool aNewHasRef,
   11575             :                            nsACString& aNewHash, uint32_t aLoadType)
   11576             : {
   11577           0 :   if (!mCurrentURI) {
   11578           0 :     return NS_OK;
   11579             :   }
   11580             : 
   11581           0 :   nsCOMPtr<nsIPresShell> shell = GetPresShell();
   11582           0 :   if (!shell) {
   11583             :     // If we failed to get the shell, or if there is no shell,
   11584             :     // nothing left to do here.
   11585           0 :     return NS_OK;
   11586             :   }
   11587             : 
   11588           0 :   nsIScrollableFrame* rootScroll = shell->GetRootScrollFrameAsScrollable();
   11589           0 :   if (rootScroll) {
   11590           0 :     rootScroll->ClearDidHistoryRestore();
   11591             :   }
   11592             : 
   11593             :   // If we have no new anchor, we do not want to scroll, unless there is a
   11594             :   // current anchor and we are doing a history load.  So return if we have no
   11595             :   // new anchor, and there is no current anchor or the load is not a history
   11596             :   // load.
   11597           0 :   if ((!aCurHasRef || aLoadType != LOAD_HISTORY) && !aNewHasRef) {
   11598           0 :     return NS_OK;
   11599             :   }
   11600             : 
   11601             :   // Both the new and current URIs refer to the same page. We can now
   11602             :   // browse to the hash stored in the new URI.
   11603             : 
   11604           0 :   if (!aNewHash.IsEmpty()) {
   11605             :     // anchor is there, but if it's a load from history,
   11606             :     // we don't have any anchor jumping to do
   11607           0 :     bool scroll = aLoadType != LOAD_HISTORY &&
   11608           0 :                   aLoadType != LOAD_RELOAD_NORMAL;
   11609             : 
   11610           0 :     char* str = ToNewCString(aNewHash);
   11611           0 :     if (!str) {
   11612           0 :       return NS_ERROR_OUT_OF_MEMORY;
   11613             :     }
   11614             : 
   11615             :     // nsUnescape modifies the string that is passed into it.
   11616           0 :     nsUnescape(str);
   11617             : 
   11618             :     // We assume that the bytes are in UTF-8, as it says in the
   11619             :     // spec:
   11620             :     // http://www.w3.org/TR/html4/appendix/notes.html#h-B.2.1
   11621             : 
   11622             :     // We try the UTF-8 string first, and then try the document's
   11623             :     // charset (see below).  If the string is not UTF-8,
   11624             :     // conversion will fail and give us an empty Unicode string.
   11625             :     // In that case, we should just fall through to using the
   11626             :     // page's charset.
   11627           0 :     nsresult rv = NS_ERROR_FAILURE;
   11628           0 :     NS_ConvertUTF8toUTF16 uStr(str);
   11629           0 :     if (!uStr.IsEmpty()) {
   11630           0 :       rv = shell->GoToAnchor(NS_ConvertUTF8toUTF16(str), scroll,
   11631           0 :                              nsIPresShell::SCROLL_SMOOTH_AUTO);
   11632             :     }
   11633           0 :     free(str);
   11634             : 
   11635             :     // Above will fail if the anchor name is not UTF-8.  Need to
   11636             :     // convert from document charset to unicode.
   11637           0 :     if (NS_FAILED(rv)) {
   11638             :       // Get a document charset
   11639           0 :       NS_ENSURE_TRUE(mContentViewer, NS_ERROR_FAILURE);
   11640           0 :       nsIDocument* doc = mContentViewer->GetDocument();
   11641           0 :       NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE);
   11642           0 :       nsAutoCString charset;
   11643           0 :       doc->GetDocumentCharacterSet()->Name(charset);
   11644             : 
   11645             :       nsCOMPtr<nsITextToSubURI> textToSubURI =
   11646           0 :         do_GetService(NS_ITEXTTOSUBURI_CONTRACTID, &rv);
   11647           0 :       NS_ENSURE_SUCCESS(rv, rv);
   11648             : 
   11649             :       // Unescape and convert to unicode
   11650           0 :       nsAutoString uStr;
   11651             : 
   11652           0 :       rv = textToSubURI->UnEscapeAndConvert(charset, aNewHash, uStr);
   11653           0 :       NS_ENSURE_SUCCESS(rv, rv);
   11654             : 
   11655             :       // Ignore return value of GoToAnchor, since it will return an error
   11656             :       // if there is no such anchor in the document, which is actually a
   11657             :       // success condition for us (we want to update the session history
   11658             :       // with the new URI no matter whether we actually scrolled
   11659             :       // somewhere).
   11660             :       //
   11661             :       // When aNewHash contains "%00", unescaped string may be empty.
   11662             :       // And GoToAnchor asserts if we ask it to scroll to an empty ref.
   11663           0 :       shell->GoToAnchor(uStr, scroll && !uStr.IsEmpty(),
   11664           0 :                         nsIPresShell::SCROLL_SMOOTH_AUTO);
   11665             :     }
   11666             :   } else {
   11667             :     // Tell the shell it's at an anchor, without scrolling.
   11668           0 :     shell->GoToAnchor(EmptyString(), false);
   11669             : 
   11670             :     // An empty anchor was found, but if it's a load from history,
   11671             :     // we don't have to jump to the top of the page. Scrollbar
   11672             :     // position will be restored by the caller, based on positions
   11673             :     // stored in session history.
   11674           0 :     if (aLoadType == LOAD_HISTORY || aLoadType == LOAD_RELOAD_NORMAL) {
   11675           0 :       return NS_OK;
   11676             :     }
   11677             :     // An empty anchor. Scroll to the top of the page.  Ignore the
   11678             :     // return value; failure to scroll here (e.g. if there is no
   11679             :     // root scrollframe) is not grounds for canceling the load!
   11680           0 :     SetCurScrollPosEx(0, 0);
   11681             :   }
   11682             : 
   11683           0 :   return NS_OK;
   11684             : }
   11685             : 
   11686             : void
   11687           4 : nsDocShell::SetupReferrerFromChannel(nsIChannel* aChannel)
   11688             : {
   11689           8 :   nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aChannel));
   11690           4 :   if (httpChannel) {
   11691           2 :     nsCOMPtr<nsIURI> referrer;
   11692           1 :     nsresult rv = httpChannel->GetReferrer(getter_AddRefs(referrer));
   11693           1 :     if (NS_SUCCEEDED(rv)) {
   11694           1 :       SetReferrerURI(referrer);
   11695             :     }
   11696             :     uint32_t referrerPolicy;
   11697           1 :     rv = httpChannel->GetReferrerPolicy(&referrerPolicy);
   11698           1 :     if (NS_SUCCEEDED(rv)) {
   11699           1 :       SetReferrerPolicy(referrerPolicy);
   11700             :     }
   11701             :   }
   11702           4 : }
   11703             : 
   11704             : bool
   11705           4 : nsDocShell::OnNewURI(nsIURI* aURI, nsIChannel* aChannel,
   11706             :                      nsIPrincipal* aTriggeringPrincipal,
   11707             :                      nsIPrincipal* aPrincipalToInherit,
   11708             :                      uint32_t aLoadType, bool aFireOnLocationChange,
   11709             :                      bool aAddToGlobalHistory, bool aCloneSHChildren)
   11710             : {
   11711           4 :   NS_PRECONDITION(aURI, "uri is null");
   11712           4 :   NS_PRECONDITION(!aChannel || !aTriggeringPrincipal, "Shouldn't have both set");
   11713             : 
   11714           4 :   MOZ_ASSERT(!aPrincipalToInherit || (aPrincipalToInherit && aTriggeringPrincipal));
   11715             : 
   11716             : #if defined(DEBUG)
   11717           4 :   if (MOZ_LOG_TEST(gDocShellLog, LogLevel::Debug)) {
   11718           0 :     nsAutoCString chanName;
   11719           0 :     if (aChannel) {
   11720           0 :       aChannel->GetName(chanName);
   11721             :     } else {
   11722           0 :       chanName.AssignLiteral("<no channel>");
   11723             :     }
   11724             : 
   11725           0 :     MOZ_LOG(gDocShellLog, LogLevel::Debug,
   11726             :             ("nsDocShell[%p]::OnNewURI(\"%s\", [%s], 0x%x)\n",
   11727             :              this, aURI->GetSpecOrDefault().get(), chanName.get(), aLoadType));
   11728             :   }
   11729             : #endif
   11730             : 
   11731           4 :   bool equalUri = false;
   11732             : 
   11733             :   // Get the post data and the HTTP response code from the channel.
   11734           4 :   uint32_t responseStatus = 0;
   11735           8 :   nsCOMPtr<nsIInputStream> inputStream;
   11736           4 :   if (aChannel) {
   11737           8 :     nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aChannel));
   11738             : 
   11739             :     // Check if the HTTPChannel is hiding under a multiPartChannel
   11740           4 :     if (!httpChannel) {
   11741           3 :       GetHttpChannel(aChannel, getter_AddRefs(httpChannel));
   11742             :     }
   11743             : 
   11744           4 :     if (httpChannel) {
   11745           2 :       nsCOMPtr<nsIUploadChannel> uploadChannel(do_QueryInterface(httpChannel));
   11746           1 :       if (uploadChannel) {
   11747           1 :         uploadChannel->GetUploadStream(getter_AddRefs(inputStream));
   11748             :       }
   11749             : 
   11750             :       // If the response status indicates an error, unlink this session
   11751             :       // history entry from any entries sharing its document.
   11752           1 :       nsresult rv = httpChannel->GetResponseStatus(&responseStatus);
   11753           1 :       if (mLSHE && NS_SUCCEEDED(rv) && responseStatus >= 400) {
   11754           0 :         mLSHE->AbandonBFCacheEntry();
   11755             :       }
   11756             :     }
   11757             :   }
   11758             : 
   11759             :   // Determine if this type of load should update history.
   11760           8 :   bool updateGHistory = !(aLoadType == LOAD_BYPASS_HISTORY ||
   11761             :                           aLoadType == LOAD_ERROR_PAGE ||
   11762           8 :                           aLoadType & LOAD_CMD_HISTORY);
   11763             : 
   11764             :   // We don't update session history on reload unless we're loading
   11765             :   // an iframe in shift-reload case.
   11766          12 :   bool updateSHistory = updateGHistory &&
   11767           4 :                         (!(aLoadType & LOAD_CMD_RELOAD) ||
   11768           4 :                          (IsForceReloadType(aLoadType) && IsFrame()));
   11769             : 
   11770             :   // Create SH Entry (mLSHE) only if there is a SessionHistory object in the
   11771             :   // current frame or in the root docshell.
   11772           8 :   nsCOMPtr<nsISHistory> rootSH = mSessionHistory;
   11773           4 :   if (!rootSH) {
   11774             :     // Get the handle to SH from the root docshell
   11775           3 :     GetRootSessionHistory(getter_AddRefs(rootSH));
   11776           3 :     if (!rootSH) {
   11777           3 :       updateSHistory = false;
   11778           3 :       updateGHistory = false; // XXX Why global history too?
   11779             :     }
   11780             :   }
   11781             : 
   11782             :   // Check if the url to be loaded is the same as the one already loaded.
   11783           4 :   if (mCurrentURI) {
   11784           3 :     aURI->Equals(mCurrentURI, &equalUri);
   11785             :   }
   11786             : 
   11787             : #ifdef DEBUG
   11788           4 :   bool shAvailable = (rootSH != nullptr);
   11789             : 
   11790             :   // XXX This log message is almost useless because |updateSHistory|
   11791             :   //     and |updateGHistory| are not correct at this point.
   11792             : 
   11793           4 :   MOZ_LOG(gDocShellLog, LogLevel::Debug,
   11794             :          ("  shAvailable=%i updateSHistory=%i updateGHistory=%i"
   11795             :           " equalURI=%i\n",
   11796             :           shAvailable, updateSHistory, updateGHistory, equalUri));
   11797             : 
   11798           4 :   if (shAvailable && mCurrentURI && !mOSHE && aLoadType != LOAD_ERROR_PAGE) {
   11799             :     // XXX mCurrentURI can be changed from any caller regardless what actual
   11800             :     // loaded document is, so testing mCurrentURI isn't really a reliable way.
   11801             :     // Session restore is one example which changes current URI in order to
   11802             :     // show address before loading. See bug 1301399.
   11803           1 :     NS_ASSERTION(NS_IsAboutBlank(mCurrentURI),
   11804             :                  "no SHEntry for a non-transient viewer?");
   11805             :   }
   11806             : #endif
   11807             : 
   11808             :   /* If the url to be loaded is the same as the one already there,
   11809             :    * and the original loadType is LOAD_NORMAL, LOAD_LINK, or
   11810             :    * LOAD_STOP_CONTENT, set loadType to LOAD_NORMAL_REPLACE so that
   11811             :    * AddToSessionHistory() won't mess with the current SHEntry and
   11812             :    * if this page has any frame children, it also will be handled
   11813             :    * properly. see bug 83684
   11814             :    *
   11815             :    * NB: If mOSHE is null but we have a current URI, then it means
   11816             :    * that we must be at the transient about:blank content viewer
   11817             :    * (asserted above) and we should let the normal load continue,
   11818             :    * since there's nothing to replace.
   11819             :    *
   11820             :    * XXX Hopefully changing the loadType at this time will not hurt
   11821             :    *  anywhere. The other way to take care of sequentially repeating
   11822             :    *  frameset pages is to add new methods to nsIDocShellTreeItem.
   11823             :    * Hopefully I don't have to do that.
   11824             :    */
   11825           4 :   if (equalUri &&
   11826           0 :       mOSHE &&
   11827           0 :       (mLoadType == LOAD_NORMAL ||
   11828           0 :        mLoadType == LOAD_LINK ||
   11829           4 :        mLoadType == LOAD_STOP_CONTENT) &&
   11830           0 :       !inputStream) {
   11831           0 :     mLoadType = LOAD_NORMAL_REPLACE;
   11832             :   }
   11833             : 
   11834             :   // If this is a refresh to the currently loaded url, we don't
   11835             :   // have to update session or global history.
   11836           4 :   if (mLoadType == LOAD_REFRESH && !inputStream && equalUri) {
   11837           0 :     SetHistoryEntry(&mLSHE, mOSHE);
   11838             :   }
   11839             : 
   11840             :   /* If the user pressed shift-reload, cache will create a new cache key
   11841             :    * for the page. Save the new cacheKey in Session History.
   11842             :    * see bug 90098
   11843             :    */
   11844           4 :   if (aChannel && IsForceReloadType(aLoadType)) {
   11845           0 :     MOZ_ASSERT(!updateSHistory || IsFrame(),
   11846             :                "We shouldn't be updating session history for forced"
   11847             :                " reloads unless we're in a newly created iframe!");
   11848             : 
   11849           0 :     nsCOMPtr<nsICacheInfoChannel> cacheChannel(do_QueryInterface(aChannel));
   11850           0 :     nsCOMPtr<nsISupports> cacheKey;
   11851             :     // Get the Cache Key and store it in SH.
   11852           0 :     if (cacheChannel) {
   11853           0 :       cacheChannel->GetCacheKey(getter_AddRefs(cacheKey));
   11854             :     }
   11855             :     // If we already have a loading history entry, store the new cache key
   11856             :     // in it.  Otherwise, since we're doing a reload and won't be updating
   11857             :     // our history entry, store the cache key in our current history entry.
   11858           0 :     if (mLSHE) {
   11859           0 :       mLSHE->SetCacheKey(cacheKey);
   11860           0 :     } else if (mOSHE) {
   11861           0 :       mOSHE->SetCacheKey(cacheKey);
   11862             :     }
   11863             :   }
   11864             : 
   11865             :   // Clear subframe history on refresh or reload.
   11866             :   // XXX: history.go(0) won't go this path as aLoadType is LOAD_HISTORY in this
   11867             :   // case. One should re-validate after bug 1331865 fixed.
   11868           4 :   if (aLoadType == LOAD_REFRESH || (aLoadType & LOAD_CMD_RELOAD)) {
   11869           0 :     ClearFrameHistory(mLSHE);
   11870           0 :     ClearFrameHistory(mOSHE);
   11871             :   }
   11872             : 
   11873           4 :   if (updateSHistory) {
   11874             :     // Update session history if necessary...
   11875           1 :     if (!mLSHE && (mItemType == typeContent) && mURIResultedInDocument) {
   11876             :       /* This is  a fresh page getting loaded for the first time
   11877             :        *.Create a Entry for it and add it to SH, if this is the
   11878             :        * rootDocShell
   11879             :        */
   11880           1 :       (void)AddToSessionHistory(aURI, aChannel, aTriggeringPrincipal,
   11881             :                                 aPrincipalToInherit, aCloneSHChildren,
   11882           2 :                                 getter_AddRefs(mLSHE));
   11883             :     }
   11884           3 :   } else if (mSessionHistory && mLSHE && mURIResultedInDocument) {
   11885             :     // Even if we don't add anything to SHistory, ensure the current index
   11886             :     // points to the same SHEntry as our mLSHE.
   11887           0 :     int32_t index = 0;
   11888           0 :     mSessionHistory->GetRequestedIndex(&index);
   11889           0 :     if (index == -1) {
   11890           0 :       mSessionHistory->GetIndex(&index);
   11891             :     }
   11892           0 :     nsCOMPtr<nsISHEntry> currentSH;
   11893           0 :     mSessionHistory->GetEntryAtIndex(index, false, getter_AddRefs(currentSH));
   11894           0 :     if (currentSH != mLSHE) {
   11895             :       nsCOMPtr<nsISHistoryInternal> shPrivate =
   11896           0 :         do_QueryInterface(mSessionHistory);
   11897           0 :       shPrivate->ReplaceEntry(index, mLSHE);
   11898             :     }
   11899             :   }
   11900             : 
   11901             :   // If this is a POST request, we do not want to include this in global
   11902             :   // history.
   11903           4 :   if (updateGHistory && aAddToGlobalHistory && !ChannelIsPost(aChannel)) {
   11904           2 :     nsCOMPtr<nsIURI> previousURI;
   11905           1 :     uint32_t previousFlags = 0;
   11906             : 
   11907           1 :     if (aLoadType & LOAD_CMD_RELOAD) {
   11908             :       // On a reload request, we don't set redirecting flags.
   11909           0 :       previousURI = aURI;
   11910             :     } else {
   11911           1 :       ExtractLastVisit(aChannel, getter_AddRefs(previousURI), &previousFlags);
   11912             :     }
   11913             : 
   11914             :     // Note: We don't use |referrer| when our global history is
   11915             :     //       based on IHistory.
   11916           2 :     nsCOMPtr<nsIURI> referrer;
   11917             :     // Treat referrer as null if there is an error getting it.
   11918           1 :     (void)NS_GetReferrerFromChannel(aChannel, getter_AddRefs(referrer));
   11919             : 
   11920           1 :     AddURIVisit(aURI, referrer, previousURI, previousFlags, responseStatus);
   11921             :   }
   11922             : 
   11923             :   // If this was a history load or a refresh, or it was a history load but
   11924             :   // later changed to LOAD_NORMAL_REPLACE due to redirection, update the index
   11925             :   // in session history.
   11926           5 :   if (rootSH &&
   11927           2 :        ((mLoadType & (LOAD_CMD_HISTORY | LOAD_CMD_RELOAD)) ||
   11928           5 :          mLoadType == LOAD_NORMAL_REPLACE)) {
   11929           0 :     nsCOMPtr<nsISHistoryInternal> shInternal(do_QueryInterface(rootSH));
   11930           0 :     if (shInternal) {
   11931           0 :       rootSH->GetIndex(&mPreviousTransIndex);
   11932           0 :       shInternal->UpdateIndex();
   11933           0 :       rootSH->GetIndex(&mLoadedTransIndex);
   11934             : #ifdef DEBUG_PAGE_CACHE
   11935             :       printf("Previous index: %d, Loaded index: %d\n\n",
   11936             :              mPreviousTransIndex, mLoadedTransIndex);
   11937             : #endif
   11938             :     }
   11939             :   }
   11940             : 
   11941             :   // aCloneSHChildren exactly means "we are not loading a new document".
   11942             :   uint32_t locationFlags =
   11943           4 :     aCloneSHChildren ? uint32_t(LOCATION_CHANGE_SAME_DOCUMENT) : 0;
   11944             : 
   11945           4 :   bool onLocationChangeNeeded = SetCurrentURI(aURI, aChannel,
   11946             :                                               aFireOnLocationChange,
   11947           4 :                                               locationFlags);
   11948             :   // Make sure to store the referrer from the channel, if any
   11949           4 :   SetupReferrerFromChannel(aChannel);
   11950           8 :   return onLocationChangeNeeded;
   11951             : }
   11952             : 
   11953             : bool
   11954           4 : nsDocShell::OnLoadingSite(nsIChannel* aChannel, bool aFireOnLocationChange,
   11955             :                           bool aAddToGlobalHistory)
   11956             : {
   11957           8 :   nsCOMPtr<nsIURI> uri;
   11958             :   // If this a redirect, use the final url (uri)
   11959             :   // else use the original url
   11960             :   //
   11961             :   // Note that this should match what documents do (see nsDocument::Reset).
   11962           4 :   NS_GetFinalChannelURI(aChannel, getter_AddRefs(uri));
   11963           4 :   NS_ENSURE_TRUE(uri, false);
   11964             : 
   11965             :   // Pass false for aCloneSHChildren, since we're loading a new page here.
   11966           4 :   return OnNewURI(uri, aChannel, nullptr, nullptr, mLoadType, aFireOnLocationChange,
   11967           4 :                   aAddToGlobalHistory, false);
   11968             : }
   11969             : 
   11970             : void
   11971           1 : nsDocShell::SetReferrerURI(nsIURI* aURI)
   11972             : {
   11973           1 :   mReferrerURI = aURI;  // This assigment addrefs
   11974           1 : }
   11975             : 
   11976             : void
   11977           1 : nsDocShell::SetReferrerPolicy(uint32_t aReferrerPolicy)
   11978             : {
   11979           1 :   mReferrerPolicy = aReferrerPolicy;
   11980           1 : }
   11981             : 
   11982             : //*****************************************************************************
   11983             : // nsDocShell: Session History
   11984             : //*****************************************************************************
   11985             : 
   11986             : NS_IMETHODIMP
   11987           0 : nsDocShell::AddState(JS::Handle<JS::Value> aData, const nsAString& aTitle,
   11988             :                      const nsAString& aURL, bool aReplace, JSContext* aCx)
   11989             : {
   11990             :   // Implements History.pushState and History.replaceState
   11991             : 
   11992             :   // Here's what we do, roughly in the order specified by HTML5:
   11993             :   // 1. Serialize aData using structured clone.
   11994             :   // 2. If the third argument is present,
   11995             :   //     a. Resolve the url, relative to the first script's base URL
   11996             :   //     b. If (a) fails, raise a SECURITY_ERR
   11997             :   //     c. Compare the resulting absolute URL to the document's address.  If
   11998             :   //        any part of the URLs difer other than the <path>, <query>, and
   11999             :   //        <fragment> components, raise a SECURITY_ERR and abort.
   12000             :   // 3. If !aReplace:
   12001             :   //     Remove from the session history all entries after the current entry,
   12002             :   //     as we would after a regular navigation, and save the current
   12003             :   //     entry's scroll position (bug 590573).
   12004             :   // 4. As apropriate, either add a state object entry to the session history
   12005             :   //    after the current entry with the following properties, or modify the
   12006             :   //    current session history entry to set
   12007             :   //      a. cloned data as the state object,
   12008             :   //      b. if the third argument was present, the absolute URL found in
   12009             :   //         step 2
   12010             :   //    Also clear the new history entry's POST data (see bug 580069).
   12011             :   // 5. If aReplace is false (i.e. we're doing a pushState instead of a
   12012             :   //    replaceState), notify bfcache that we've navigated to a new page.
   12013             :   // 6. If the third argument is present, set the document's current address
   12014             :   //    to the absolute URL found in step 2.
   12015             :   //
   12016             :   // It's important that this function not run arbitrary scripts after step 1
   12017             :   // and before completing step 5.  For example, if a script called
   12018             :   // history.back() before we completed step 5, bfcache might destroy an
   12019             :   // active content viewer.  Since EvictOutOfRangeContentViewers at the end of
   12020             :   // step 5 might run script, we can't just put a script blocker around the
   12021             :   // critical section.
   12022             :   //
   12023             :   // Note that we completely ignore the aTitle parameter.
   12024             : 
   12025             :   nsresult rv;
   12026             : 
   12027             :   // Don't clobber the load type of an existing network load.
   12028           0 :   AutoRestore<uint32_t> loadTypeResetter(mLoadType);
   12029             : 
   12030             :   // pushState effectively becomes replaceState when we've started a network
   12031             :   // load but haven't adopted its document yet.  This mirrors what we do with
   12032             :   // changes to the hash at this stage of the game.
   12033           0 :   if (JustStartedNetworkLoad()) {
   12034           0 :     aReplace = true;
   12035             :   }
   12036             : 
   12037           0 :   nsCOMPtr<nsIDocument> document = GetDocument();
   12038           0 :   NS_ENSURE_TRUE(document, NS_ERROR_FAILURE);
   12039             : 
   12040             :   // Step 1: Serialize aData using structured clone.
   12041           0 :   nsCOMPtr<nsIStructuredCloneContainer> scContainer;
   12042             : 
   12043             :   // scContainer->Init might cause arbitrary JS to run, and this code might
   12044             :   // navigate the page we're on, potentially to a different origin! (bug
   12045             :   // 634834)  To protect against this, we abort if our principal changes due
   12046             :   // to the InitFromJSVal() call.
   12047             :   {
   12048           0 :     nsCOMPtr<nsIDocument> origDocument = GetDocument();
   12049           0 :     if (!origDocument) {
   12050           0 :       return NS_ERROR_DOM_SECURITY_ERR;
   12051             :     }
   12052           0 :     nsCOMPtr<nsIPrincipal> origPrincipal = origDocument->NodePrincipal();
   12053             : 
   12054           0 :     scContainer = new nsStructuredCloneContainer();
   12055           0 :     rv = scContainer->InitFromJSVal(aData, aCx);
   12056           0 :     NS_ENSURE_SUCCESS(rv, rv);
   12057             : 
   12058           0 :     nsCOMPtr<nsIDocument> newDocument = GetDocument();
   12059           0 :     if (!newDocument) {
   12060           0 :       return NS_ERROR_DOM_SECURITY_ERR;
   12061             :     }
   12062           0 :     nsCOMPtr<nsIPrincipal> newPrincipal = newDocument->NodePrincipal();
   12063             : 
   12064           0 :     bool principalsEqual = false;
   12065           0 :     origPrincipal->Equals(newPrincipal, &principalsEqual);
   12066           0 :     NS_ENSURE_TRUE(principalsEqual, NS_ERROR_DOM_SECURITY_ERR);
   12067             :   }
   12068             : 
   12069             :   // Check that the state object isn't too long.
   12070             :   // Default max length: 640k bytes.
   12071             :   int32_t maxStateObjSize =
   12072           0 :     Preferences::GetInt("browser.history.maxStateObjectSize", 0xA0000);
   12073           0 :   if (maxStateObjSize < 0) {
   12074           0 :     maxStateObjSize = 0;
   12075             :   }
   12076             : 
   12077             :   uint64_t scSize;
   12078           0 :   rv = scContainer->GetSerializedNBytes(&scSize);
   12079           0 :   NS_ENSURE_SUCCESS(rv, rv);
   12080             : 
   12081           0 :   NS_ENSURE_TRUE(scSize <= (uint32_t)maxStateObjSize, NS_ERROR_ILLEGAL_VALUE);
   12082             : 
   12083             :   // Step 2: Resolve aURL
   12084           0 :   bool equalURIs = true;
   12085           0 :   nsCOMPtr<nsIURI> currentURI;
   12086           0 :   if (sURIFixup && mCurrentURI) {
   12087           0 :     rv = sURIFixup->CreateExposableURI(mCurrentURI, getter_AddRefs(currentURI));
   12088           0 :     NS_ENSURE_SUCCESS(rv, rv);
   12089             :   } else {
   12090           0 :     currentURI = mCurrentURI;
   12091             :   }
   12092           0 :   nsCOMPtr<nsIURI> oldURI = currentURI;
   12093           0 :   nsCOMPtr<nsIURI> newURI;
   12094           0 :   if (aURL.Length() == 0) {
   12095           0 :     newURI = currentURI;
   12096             :   } else {
   12097             :     // 2a: Resolve aURL relative to mURI
   12098             : 
   12099           0 :     nsIURI* docBaseURI = document->GetDocBaseURI();
   12100           0 :     if (!docBaseURI) {
   12101           0 :       return NS_ERROR_FAILURE;
   12102             :     }
   12103             : 
   12104           0 :     nsAutoCString spec;
   12105           0 :     docBaseURI->GetSpec(spec);
   12106             : 
   12107           0 :     nsAutoCString charset;
   12108           0 :     rv = docBaseURI->GetOriginCharset(charset);
   12109           0 :     NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
   12110             : 
   12111           0 :     rv = NS_NewURI(getter_AddRefs(newURI), aURL, charset.get(), docBaseURI);
   12112             : 
   12113             :     // 2b: If 2a fails, raise a SECURITY_ERR
   12114           0 :     if (NS_FAILED(rv)) {
   12115           0 :       return NS_ERROR_DOM_SECURITY_ERR;
   12116             :     }
   12117             : 
   12118             :     // 2c: Same-origin check.
   12119           0 :     if (!nsContentUtils::URIIsLocalFile(newURI)) {
   12120             :       // In addition to checking that the security manager says that
   12121             :       // the new URI has the same origin as our current URI, we also
   12122             :       // check that the two URIs have the same userpass. (The
   12123             :       // security manager says that |http://foo.com| and
   12124             :       // |http://me@foo.com| have the same origin.)  currentURI
   12125             :       // won't contain the password part of the userpass, so this
   12126             :       // means that it's never valid to specify a password in a
   12127             :       // pushState or replaceState URI.
   12128             : 
   12129             :       nsCOMPtr<nsIScriptSecurityManager> secMan =
   12130           0 :         do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID);
   12131           0 :       NS_ENSURE_TRUE(secMan, NS_ERROR_FAILURE);
   12132             : 
   12133             :       // It's very important that we check that newURI is of the same
   12134             :       // origin as currentURI, not docBaseURI, because a page can
   12135             :       // set docBaseURI arbitrarily to any domain.
   12136           0 :       nsAutoCString currentUserPass, newUserPass;
   12137           0 :       NS_ENSURE_SUCCESS(currentURI->GetUserPass(currentUserPass),
   12138             :                         NS_ERROR_FAILURE);
   12139           0 :       NS_ENSURE_SUCCESS(newURI->GetUserPass(newUserPass), NS_ERROR_FAILURE);
   12140           0 :       if (NS_FAILED(secMan->CheckSameOriginURI(currentURI, newURI, true)) ||
   12141           0 :           !currentUserPass.Equals(newUserPass)) {
   12142           0 :         return NS_ERROR_DOM_SECURITY_ERR;
   12143             :       }
   12144             :     } else {
   12145             :       // It's a file:// URI
   12146             :       nsCOMPtr<nsIScriptObjectPrincipal> docScriptObj =
   12147           0 :         do_QueryInterface(document);
   12148             : 
   12149           0 :       if (!docScriptObj) {
   12150           0 :         return NS_ERROR_DOM_SECURITY_ERR;
   12151             :       }
   12152             : 
   12153           0 :       nsCOMPtr<nsIPrincipal> principal = docScriptObj->GetPrincipal();
   12154             : 
   12155           0 :       if (!principal ||
   12156           0 :           NS_FAILED(principal->CheckMayLoad(newURI, true, false))) {
   12157           0 :         return NS_ERROR_DOM_SECURITY_ERR;
   12158             :       }
   12159             :     }
   12160             : 
   12161           0 :     if (currentURI) {
   12162           0 :       currentURI->Equals(newURI, &equalURIs);
   12163             :     } else {
   12164           0 :       equalURIs = false;
   12165             :     }
   12166             : 
   12167             :   } // end of same-origin check
   12168             : 
   12169             :   // Step 3: Create a new entry in the session history. This will erase
   12170             :   // all SHEntries after the new entry and make this entry the current
   12171             :   // one.  This operation may modify mOSHE, which we need later, so we
   12172             :   // keep a reference here.
   12173           0 :   NS_ENSURE_TRUE(mOSHE, NS_ERROR_FAILURE);
   12174           0 :   nsCOMPtr<nsISHEntry> oldOSHE = mOSHE;
   12175             : 
   12176           0 :   mLoadType = LOAD_PUSHSTATE;
   12177             : 
   12178           0 :   nsCOMPtr<nsISHEntry> newSHEntry;
   12179           0 :   if (!aReplace) {
   12180             :     // Save the current scroll position (bug 590573).
   12181           0 :     nscoord cx = 0, cy = 0;
   12182           0 :     GetCurScrollPos(ScrollOrientation_X, &cx);
   12183           0 :     GetCurScrollPos(ScrollOrientation_Y, &cy);
   12184           0 :     mOSHE->SetScrollPosition(cx, cy);
   12185             : 
   12186           0 :     bool scrollRestorationIsManual = false;
   12187           0 :     mOSHE->GetScrollRestorationIsManual(&scrollRestorationIsManual);
   12188             : 
   12189             :     // Since we're not changing which page we have loaded, pass
   12190             :     // true for aCloneChildren.
   12191           0 :     rv = AddToSessionHistory(newURI, nullptr,
   12192           0 :                              document->NodePrincipal(), // triggeringPrincipal
   12193             :                              nullptr, true,
   12194           0 :                              getter_AddRefs(newSHEntry));
   12195           0 :     NS_ENSURE_SUCCESS(rv, rv);
   12196             : 
   12197           0 :     NS_ENSURE_TRUE(newSHEntry, NS_ERROR_FAILURE);
   12198             : 
   12199             :     // Session history entries created by pushState inherit scroll restoration
   12200             :     // mode from the current entry.
   12201           0 :     newSHEntry->SetScrollRestorationIsManual(scrollRestorationIsManual);
   12202             : 
   12203             :     // Link the new SHEntry to the old SHEntry's BFCache entry, since the
   12204             :     // two entries correspond to the same document.
   12205           0 :     NS_ENSURE_SUCCESS(newSHEntry->AdoptBFCacheEntry(oldOSHE), NS_ERROR_FAILURE);
   12206             : 
   12207             :     // Set the new SHEntry's title (bug 655273).
   12208           0 :     nsString title;
   12209           0 :     mOSHE->GetTitle(getter_Copies(title));
   12210           0 :     newSHEntry->SetTitle(title);
   12211             : 
   12212             :     // AddToSessionHistory may not modify mOSHE.  In case it doesn't,
   12213             :     // we'll just set mOSHE here.
   12214           0 :     mOSHE = newSHEntry;
   12215             : 
   12216             :   } else {
   12217           0 :     newSHEntry = mOSHE;
   12218           0 :     newSHEntry->SetURI(newURI);
   12219           0 :     newSHEntry->SetOriginalURI(newURI);
   12220           0 :     newSHEntry->SetLoadReplace(false);
   12221             :   }
   12222             : 
   12223             :   // Step 4: Modify new/original session history entry and clear its POST
   12224             :   // data, if there is any.
   12225           0 :   newSHEntry->SetStateData(scContainer);
   12226           0 :   newSHEntry->SetPostData(nullptr);
   12227             : 
   12228             :   // If this push/replaceState changed the document's current URI and the new
   12229             :   // URI differs from the old URI in more than the hash, or if the old
   12230             :   // SHEntry's URI was modified in this way by a push/replaceState call
   12231             :   // set URIWasModified to true for the current SHEntry (bug 669671).
   12232           0 :   bool sameExceptHashes = true, oldURIWasModified = false;
   12233           0 :   newURI->EqualsExceptRef(currentURI, &sameExceptHashes);
   12234           0 :   oldOSHE->GetURIWasModified(&oldURIWasModified);
   12235           0 :   newSHEntry->SetURIWasModified(!sameExceptHashes || oldURIWasModified);
   12236             : 
   12237             :   // Step 5: If aReplace is false, indicating that we're doing a pushState
   12238             :   // rather than a replaceState, notify bfcache that we've added a page to
   12239             :   // the history so it can evict content viewers if appropriate. Otherwise
   12240             :   // call ReplaceEntry so that we notify nsIHistoryListeners that an entry
   12241             :   // was replaced.
   12242           0 :   nsCOMPtr<nsISHistory> rootSH;
   12243           0 :   GetRootSessionHistory(getter_AddRefs(rootSH));
   12244           0 :   NS_ENSURE_TRUE(rootSH, NS_ERROR_UNEXPECTED);
   12245             : 
   12246           0 :   nsCOMPtr<nsISHistoryInternal> internalSH = do_QueryInterface(rootSH);
   12247           0 :   NS_ENSURE_TRUE(internalSH, NS_ERROR_UNEXPECTED);
   12248             : 
   12249           0 :   if (!aReplace) {
   12250           0 :     int32_t curIndex = -1;
   12251           0 :     rv = rootSH->GetIndex(&curIndex);
   12252           0 :     if (NS_SUCCEEDED(rv) && curIndex > -1) {
   12253           0 :       internalSH->EvictOutOfRangeContentViewers(curIndex);
   12254             :     }
   12255             :   } else {
   12256           0 :     nsCOMPtr<nsISHEntry> rootSHEntry = GetRootSHEntry(newSHEntry);
   12257             : 
   12258           0 :     int32_t index = -1;
   12259           0 :     rv = rootSH->GetIndexOfEntry(rootSHEntry, &index);
   12260           0 :     if (NS_SUCCEEDED(rv) && index > -1) {
   12261           0 :       internalSH->ReplaceEntry(index, rootSHEntry);
   12262             :     }
   12263             :   }
   12264             : 
   12265             :   // Step 6: If the document's URI changed, update document's URI and update
   12266             :   // global history.
   12267             :   //
   12268             :   // We need to call FireOnLocationChange so that the browser's address bar
   12269             :   // gets updated and the back button is enabled, but we only need to
   12270             :   // explicitly call FireOnLocationChange if we're not calling SetCurrentURI,
   12271             :   // since SetCurrentURI will call FireOnLocationChange for us.
   12272             :   //
   12273             :   // Both SetCurrentURI(...) and FireDummyOnLocationChange() pass
   12274             :   // nullptr for aRequest param to FireOnLocationChange(...). Such an update
   12275             :   // notification is allowed only when we know docshell is not loading a new
   12276             :   // document and it requires LOCATION_CHANGE_SAME_DOCUMENT flag. Otherwise,
   12277             :   // FireOnLocationChange(...) breaks security UI.
   12278           0 :   if (!equalURIs) {
   12279           0 :     document->SetDocumentURI(newURI);
   12280             :     // We can't trust SetCurrentURI to do always fire locationchange events
   12281             :     // when we expect it to, so we hack around that by doing it ourselves...
   12282           0 :     SetCurrentURI(newURI, nullptr, false, LOCATION_CHANGE_SAME_DOCUMENT);
   12283           0 :     if (mLoadType != LOAD_ERROR_PAGE) {
   12284           0 :       FireDummyOnLocationChange();
   12285             :     }
   12286             : 
   12287           0 :     AddURIVisit(newURI, oldURI, oldURI, 0);
   12288             : 
   12289             :     // AddURIVisit doesn't set the title for the new URI in global history,
   12290             :     // so do that here.
   12291           0 :     UpdateGlobalHistoryTitle(newURI);
   12292             : 
   12293             :     // Inform the favicon service that our old favicon applies to this new
   12294             :     // URI.
   12295           0 :     CopyFavicon(oldURI, newURI, document->NodePrincipal(), UsePrivateBrowsing());
   12296             :   } else {
   12297           0 :     FireDummyOnLocationChange();
   12298             :   }
   12299           0 :   document->SetStateObject(scContainer);
   12300             : 
   12301           0 :   return NS_OK;
   12302             : }
   12303             : 
   12304             : NS_IMETHODIMP
   12305           0 : nsDocShell::GetCurrentScrollRestorationIsManual(bool* aIsManual)
   12306             : {
   12307           0 :   *aIsManual = false;
   12308           0 :   if (mOSHE) {
   12309           0 :     mOSHE->GetScrollRestorationIsManual(aIsManual);
   12310             :   }
   12311             : 
   12312           0 :   return NS_OK;
   12313             : }
   12314             : 
   12315             : NS_IMETHODIMP
   12316           0 : nsDocShell::SetCurrentScrollRestorationIsManual(bool aIsManual)
   12317             : {
   12318           0 :   if (mOSHE) {
   12319           0 :     mOSHE->SetScrollRestorationIsManual(aIsManual);
   12320             :   }
   12321             : 
   12322           0 :   return NS_OK;
   12323             : }
   12324             : 
   12325             : bool
   12326           1 : nsDocShell::ShouldAddToSessionHistory(nsIURI* aURI)
   12327             : {
   12328             :   // I believe none of the about: urls should go in the history. But then
   12329             :   // that could just be me... If the intent is only deny about:blank then we
   12330             :   // should just do a spec compare, rather than two gets of the scheme and
   12331             :   // then the path.  -Gagan
   12332             :   nsresult rv;
   12333           2 :   nsAutoCString buf;
   12334             : 
   12335           1 :   rv = aURI->GetScheme(buf);
   12336           1 :   if (NS_FAILED(rv)) {
   12337           0 :     return false;
   12338             :   }
   12339             : 
   12340           1 :   if (buf.EqualsLiteral("about")) {
   12341           0 :     rv = aURI->GetPath(buf);
   12342           0 :     if (NS_FAILED(rv)) {
   12343           0 :       return false;
   12344             :     }
   12345             : 
   12346           0 :     if (buf.EqualsLiteral("blank") || buf.EqualsLiteral("newtab")) {
   12347           0 :       return false;
   12348             :     }
   12349             :   }
   12350             : 
   12351           1 :   return true;
   12352             : }
   12353             : 
   12354             : nsresult
   12355           1 : nsDocShell::AddToSessionHistory(nsIURI* aURI, nsIChannel* aChannel,
   12356             :                                 nsIPrincipal* aTriggeringPrincipal,
   12357             :                                 nsIPrincipal* aPrincipalToInherit,
   12358             :                                 bool aCloneChildren,
   12359             :                                 nsISHEntry** aNewEntry)
   12360             : {
   12361           1 :   NS_PRECONDITION(aURI, "uri is null");
   12362           1 :   NS_PRECONDITION(!aChannel || !aTriggeringPrincipal, "Shouldn't have both set");
   12363             : 
   12364             : #if defined(DEBUG)
   12365           1 :   if (MOZ_LOG_TEST(gDocShellLog, LogLevel::Debug)) {
   12366           0 :     nsAutoCString chanName;
   12367           0 :     if (aChannel) {
   12368           0 :       aChannel->GetName(chanName);
   12369             :     } else {
   12370           0 :       chanName.AssignLiteral("<no channel>");
   12371             :     }
   12372             : 
   12373           0 :     MOZ_LOG(gDocShellLog, LogLevel::Debug,
   12374             :             ("nsDocShell[%p]::AddToSessionHistory(\"%s\", [%s])\n",
   12375             :              this, aURI->GetSpecOrDefault().get(), chanName.get()));
   12376             :   }
   12377             : #endif
   12378             : 
   12379           1 :   nsresult rv = NS_OK;
   12380           2 :   nsCOMPtr<nsISHEntry> entry;
   12381             :   bool shouldPersist;
   12382             : 
   12383           1 :   shouldPersist = ShouldAddToSessionHistory(aURI);
   12384             : 
   12385             :   // Get a handle to the root docshell
   12386           2 :   nsCOMPtr<nsIDocShellTreeItem> root;
   12387           1 :   GetSameTypeRootTreeItem(getter_AddRefs(root));
   12388             :   /*
   12389             :    * If this is a LOAD_FLAGS_REPLACE_HISTORY in a subframe, we use
   12390             :    * the existing SH entry in the page and replace the url and
   12391             :    * other vitalities.
   12392             :    */
   12393           1 :   if (LOAD_TYPE_HAS_FLAGS(mLoadType, LOAD_FLAGS_REPLACE_HISTORY) &&
   12394           0 :       root != static_cast<nsIDocShellTreeItem*>(this)) {
   12395             :     // This is a subframe
   12396           0 :     entry = mOSHE;
   12397           0 :     nsCOMPtr<nsISHContainer> shContainer(do_QueryInterface(entry));
   12398           0 :     if (shContainer) {
   12399           0 :       int32_t childCount = 0;
   12400           0 :       shContainer->GetChildCount(&childCount);
   12401             :       // Remove all children of this entry
   12402           0 :       for (int32_t i = childCount - 1; i >= 0; i--) {
   12403           0 :         nsCOMPtr<nsISHEntry> child;
   12404           0 :         shContainer->GetChildAt(i, getter_AddRefs(child));
   12405           0 :         shContainer->RemoveChild(child);
   12406             :       }
   12407           0 :       entry->AbandonBFCacheEntry();
   12408             :     }
   12409             :   }
   12410             : 
   12411             :   // Create a new entry if necessary.
   12412           1 :   if (!entry) {
   12413           1 :     entry = do_CreateInstance(NS_SHENTRY_CONTRACTID);
   12414             : 
   12415           1 :     if (!entry) {
   12416           0 :       return NS_ERROR_OUT_OF_MEMORY;
   12417             :     }
   12418             :   }
   12419             : 
   12420             :   // Get the post data & referrer
   12421           2 :   nsCOMPtr<nsIInputStream> inputStream;
   12422           2 :   nsCOMPtr<nsIURI> originalURI;
   12423           2 :   nsCOMPtr<nsIURI> resultPrincipalURI;
   12424           1 :   bool loadReplace = false;
   12425           2 :   nsCOMPtr<nsIURI> referrerURI;
   12426           1 :   uint32_t referrerPolicy = mozilla::net::RP_Unset;
   12427           2 :   nsCOMPtr<nsISupports> cacheKey;
   12428           2 :   nsCOMPtr<nsIPrincipal> triggeringPrincipal = aTriggeringPrincipal;
   12429           2 :   nsCOMPtr<nsIPrincipal> principalToInherit = aPrincipalToInherit;
   12430           1 :   bool expired = false;
   12431           1 :   bool discardLayoutState = false;
   12432           2 :   nsCOMPtr<nsICacheInfoChannel> cacheChannel;
   12433           1 :   if (aChannel) {
   12434           1 :     cacheChannel = do_QueryInterface(aChannel);
   12435             : 
   12436             :     /* If there is a caching channel, get the Cache Key and store it
   12437             :      * in SH.
   12438             :      */
   12439           1 :     if (cacheChannel) {
   12440           1 :       cacheChannel->GetCacheKey(getter_AddRefs(cacheKey));
   12441             :     }
   12442           2 :     nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aChannel));
   12443             : 
   12444             :     // Check if the httpChannel is hiding under a multipartChannel
   12445           1 :     if (!httpChannel) {
   12446           0 :       GetHttpChannel(aChannel, getter_AddRefs(httpChannel));
   12447             :     }
   12448           1 :     if (httpChannel) {
   12449           2 :       nsCOMPtr<nsIUploadChannel> uploadChannel(do_QueryInterface(httpChannel));
   12450           1 :       if (uploadChannel) {
   12451           1 :         uploadChannel->GetUploadStream(getter_AddRefs(inputStream));
   12452             :       }
   12453           1 :       httpChannel->GetOriginalURI(getter_AddRefs(originalURI));
   12454             :       uint32_t loadFlags;
   12455           1 :       aChannel->GetLoadFlags(&loadFlags);
   12456           1 :       loadReplace = loadFlags & nsIChannel::LOAD_REPLACE;
   12457           1 :       rv = httpChannel->GetReferrer(getter_AddRefs(referrerURI));
   12458           1 :       MOZ_ASSERT(NS_SUCCEEDED(rv));
   12459           1 :       rv = httpChannel->GetReferrerPolicy(&referrerPolicy);
   12460           1 :       MOZ_ASSERT(NS_SUCCEEDED(rv));
   12461             : 
   12462           1 :       discardLayoutState = ShouldDiscardLayoutState(httpChannel);
   12463             :     }
   12464             : 
   12465           2 :     nsCOMPtr<nsILoadInfo> loadInfo = aChannel->GetLoadInfo();
   12466           1 :     if (loadInfo) {
   12467           1 :       if (!triggeringPrincipal) {
   12468           1 :         triggeringPrincipal = loadInfo->TriggeringPrincipal();
   12469             :       }
   12470             : 
   12471           1 :       loadInfo->GetResultPrincipalURI(getter_AddRefs(resultPrincipalURI));
   12472             : 
   12473             :       // For now keep storing just the principal in the SHEntry.
   12474           1 :       if (!principalToInherit) {
   12475           1 :         if (loadInfo->GetLoadingSandboxed()) {
   12476           0 :           if (loadInfo->LoadingPrincipal()) {
   12477           0 :             principalToInherit = NullPrincipal::CreateWithInheritedAttributes(
   12478           0 :             loadInfo->LoadingPrincipal());
   12479             :           } else {
   12480             :             // get the OriginAttributes
   12481           0 :             OriginAttributes attrs;
   12482           0 :             loadInfo->GetOriginAttributes(&attrs);
   12483           0 :             principalToInherit = NullPrincipal::Create(attrs);
   12484             :           }
   12485             :         } else {
   12486           1 :           principalToInherit = loadInfo->PrincipalToInherit();
   12487             :         }
   12488             :       }
   12489             :     }
   12490             :   }
   12491             : 
   12492             :   // Title is set in nsDocShell::SetTitle()
   12493           3 :   entry->Create(aURI,                // uri
   12494           1 :                 EmptyString(),       // Title
   12495             :                 inputStream,         // Post data stream
   12496             :                 nullptr,             // LayoutHistory state
   12497             :                 cacheKey,            // CacheKey
   12498             :                 mContentTypeHint,    // Content-type
   12499             :                 triggeringPrincipal, // Channel or provided principal
   12500             :                 principalToInherit,
   12501             :                 mHistoryID,
   12502           2 :                 mDynamicallyCreated);
   12503             : 
   12504           1 :   entry->SetOriginalURI(originalURI);
   12505           1 :   entry->SetResultPrincipalURI(resultPrincipalURI);
   12506           1 :   entry->SetLoadReplace(loadReplace);
   12507           1 :   entry->SetReferrerURI(referrerURI);
   12508           1 :   entry->SetReferrerPolicy(referrerPolicy);
   12509           2 :   nsCOMPtr<nsIInputStreamChannel> inStrmChan = do_QueryInterface(aChannel);
   12510           1 :   if (inStrmChan) {
   12511             :     bool isSrcdocChannel;
   12512           0 :     inStrmChan->GetIsSrcdocChannel(&isSrcdocChannel);
   12513           0 :     if (isSrcdocChannel) {
   12514           0 :       nsAutoString srcdoc;
   12515           0 :       inStrmChan->GetSrcdocData(srcdoc);
   12516           0 :       entry->SetSrcdocData(srcdoc);
   12517           0 :       nsCOMPtr<nsIURI> baseURI;
   12518           0 :       inStrmChan->GetBaseURI(getter_AddRefs(baseURI));
   12519           0 :       entry->SetBaseURI(baseURI);
   12520             :     }
   12521             :   }
   12522             :   /* If cache got a 'no-store', ask SH not to store
   12523             :    * HistoryLayoutState. By default, SH will set this
   12524             :    * flag to true and save HistoryLayoutState.
   12525             :    */
   12526           1 :   if (discardLayoutState) {
   12527           0 :     entry->SetSaveLayoutStateFlag(false);
   12528             :   }
   12529           1 :   if (cacheChannel) {
   12530             :     // Check if the page has expired from cache
   12531           1 :     uint32_t expTime = 0;
   12532           1 :     cacheChannel->GetCacheTokenExpirationTime(&expTime);
   12533           1 :     uint32_t now = PRTimeToSeconds(PR_Now());
   12534           1 :     if (expTime <= now) {
   12535           0 :       expired = true;
   12536             :     }
   12537             :   }
   12538           1 :   if (expired) {
   12539           0 :     entry->SetExpirationStatus(true);
   12540             :   }
   12541             : 
   12542           1 :   if (root == static_cast<nsIDocShellTreeItem*>(this) && mSessionHistory) {
   12543             :     // If we need to clone our children onto the new session
   12544             :     // history entry, do so now.
   12545           1 :     if (aCloneChildren && mOSHE) {
   12546             :       uint32_t cloneID;
   12547           0 :       mOSHE->GetID(&cloneID);
   12548           0 :       nsCOMPtr<nsISHEntry> newEntry;
   12549           0 :       CloneAndReplace(mOSHE, this, cloneID, entry, true,
   12550           0 :                       getter_AddRefs(newEntry));
   12551           0 :       NS_ASSERTION(entry == newEntry,
   12552             :                    "The new session history should be in the new entry");
   12553             :     }
   12554             : 
   12555             :     // This is the root docshell
   12556           1 :     bool addToSHistory = !LOAD_TYPE_HAS_FLAGS(mLoadType, LOAD_FLAGS_REPLACE_HISTORY);
   12557           1 :     if (!addToSHistory) {
   12558             :       // Replace current entry in session history; If the requested index is
   12559             :       // valid, it indicates the loading was triggered by a history load, and
   12560             :       // we should replace the entry at requested index instead.
   12561           0 :       int32_t index = 0;
   12562           0 :       mSessionHistory->GetRequestedIndex(&index);
   12563           0 :       if (index == -1) {
   12564           0 :         mSessionHistory->GetIndex(&index);
   12565             :       }
   12566             :       nsCOMPtr<nsISHistoryInternal> shPrivate =
   12567           0 :         do_QueryInterface(mSessionHistory);
   12568             :       // Replace the current entry with the new entry
   12569           0 :       if (index >= 0) {
   12570           0 :         if (shPrivate) {
   12571           0 :           rv = shPrivate->ReplaceEntry(index, entry);
   12572             :         }
   12573             :       } else {
   12574             :         // If we're trying to replace an inexistant shistory entry, append.
   12575           0 :         addToSHistory = true;
   12576             :       }
   12577             :     }
   12578             : 
   12579           1 :     if (addToSHistory) {
   12580             :       // Add to session history
   12581             :       nsCOMPtr<nsISHistoryInternal> shPrivate =
   12582           2 :         do_QueryInterface(mSessionHistory);
   12583           1 :       NS_ENSURE_TRUE(shPrivate, NS_ERROR_FAILURE);
   12584           1 :       mSessionHistory->GetIndex(&mPreviousTransIndex);
   12585           1 :       rv = shPrivate->AddEntry(entry, shouldPersist);
   12586           1 :       mSessionHistory->GetIndex(&mLoadedTransIndex);
   12587             : #ifdef DEBUG_PAGE_CACHE
   12588             :       printf("Previous index: %d, Loaded index: %d\n\n",
   12589             :              mPreviousTransIndex, mLoadedTransIndex);
   12590             : #endif
   12591             :     }
   12592             :   } else {
   12593             :     // This is a subframe.
   12594           0 :     if (!mOSHE || !LOAD_TYPE_HAS_FLAGS(mLoadType, LOAD_FLAGS_REPLACE_HISTORY)) {
   12595           0 :       rv = AddChildSHEntryToParent(entry, mChildOffset, aCloneChildren);
   12596             :     }
   12597             :   }
   12598             : 
   12599             :   // Return the new SH entry...
   12600           1 :   if (aNewEntry) {
   12601           1 :     *aNewEntry = nullptr;
   12602           1 :     if (NS_SUCCEEDED(rv)) {
   12603           1 :       entry.forget(aNewEntry);
   12604             :     }
   12605             :   }
   12606             : 
   12607           1 :   return rv;
   12608             : }
   12609             : 
   12610             : nsresult
   12611           0 : nsDocShell::LoadHistoryEntry(nsISHEntry* aEntry, uint32_t aLoadType)
   12612             : {
   12613           0 :   if (!IsNavigationAllowed()) {
   12614           0 :     return NS_OK;
   12615             :   }
   12616             : 
   12617           0 :   nsCOMPtr<nsIURI> uri;
   12618           0 :   nsCOMPtr<nsIURI> originalURI;
   12619           0 :   nsCOMPtr<nsIURI> resultPrincipalURI;
   12620           0 :   bool loadReplace = false;
   12621           0 :   nsCOMPtr<nsIInputStream> postData;
   12622           0 :   nsCOMPtr<nsIURI> referrerURI;
   12623             :   uint32_t referrerPolicy;
   12624           0 :   nsAutoCString contentType;
   12625           0 :   nsCOMPtr<nsIPrincipal> triggeringPrincipal;
   12626           0 :   nsCOMPtr<nsIPrincipal> principalToInherit;
   12627             : 
   12628           0 :   NS_ENSURE_TRUE(aEntry, NS_ERROR_FAILURE);
   12629             : 
   12630           0 :   NS_ENSURE_SUCCESS(aEntry->GetURI(getter_AddRefs(uri)), NS_ERROR_FAILURE);
   12631           0 :   NS_ENSURE_SUCCESS(aEntry->GetOriginalURI(getter_AddRefs(originalURI)),
   12632             :                     NS_ERROR_FAILURE);
   12633           0 :   NS_ENSURE_SUCCESS(aEntry->GetResultPrincipalURI(getter_AddRefs(resultPrincipalURI)),
   12634             :                     NS_ERROR_FAILURE);
   12635           0 :   NS_ENSURE_SUCCESS(aEntry->GetLoadReplace(&loadReplace),
   12636             :                     NS_ERROR_FAILURE);
   12637           0 :   NS_ENSURE_SUCCESS(aEntry->GetReferrerURI(getter_AddRefs(referrerURI)),
   12638             :                     NS_ERROR_FAILURE);
   12639           0 :   NS_ENSURE_SUCCESS(aEntry->GetReferrerPolicy(&referrerPolicy),
   12640             :                     NS_ERROR_FAILURE);
   12641           0 :   NS_ENSURE_SUCCESS(aEntry->GetPostData(getter_AddRefs(postData)),
   12642             :                     NS_ERROR_FAILURE);
   12643           0 :   NS_ENSURE_SUCCESS(aEntry->GetContentType(contentType), NS_ERROR_FAILURE);
   12644           0 :   NS_ENSURE_SUCCESS(aEntry->GetTriggeringPrincipal(getter_AddRefs(triggeringPrincipal)),
   12645             :                     NS_ERROR_FAILURE);
   12646           0 :   NS_ENSURE_SUCCESS(aEntry->GetPrincipalToInherit(getter_AddRefs(principalToInherit)),
   12647             :                     NS_ERROR_FAILURE);
   12648             : 
   12649             :   // Calling CreateAboutBlankContentViewer can set mOSHE to null, and if
   12650             :   // that's the only thing holding a ref to aEntry that will cause aEntry to
   12651             :   // die while we're loading it.  So hold a strong ref to aEntry here, just
   12652             :   // in case.
   12653           0 :   nsCOMPtr<nsISHEntry> kungFuDeathGrip(aEntry);
   12654             :   bool isJS;
   12655           0 :   nsresult rv = uri->SchemeIs("javascript", &isJS);
   12656           0 :   if (NS_FAILED(rv) || isJS) {
   12657             :     // We're loading a URL that will execute script from inside asyncOpen.
   12658             :     // Replace the current document with about:blank now to prevent
   12659             :     // anything from the current document from leaking into any JavaScript
   12660             :     // code in the URL.
   12661             :     // Don't cache the presentation if we're going to just reload the
   12662             :     // current entry. Caching would lead to trying to save the different
   12663             :     // content viewers in the same nsISHEntry object.
   12664           0 :     rv = CreateAboutBlankContentViewer(principalToInherit, nullptr,
   12665           0 :                                        aEntry != mOSHE);
   12666             : 
   12667           0 :     if (NS_FAILED(rv)) {
   12668             :       // The creation of the intermittent about:blank content
   12669             :       // viewer failed for some reason (potentially because the
   12670             :       // user prevented it). Interrupt the history load.
   12671           0 :       return NS_OK;
   12672             :     }
   12673             : 
   12674           0 :     if (!triggeringPrincipal) {
   12675             :       // Ensure that we have a triggeringPrincipal.  Otherwise javascript:
   12676             :       // URIs will pick it up from the about:blank page we just loaded,
   12677             :       // and we don't really want even that in this case.
   12678           0 :       triggeringPrincipal = NullPrincipal::CreateWithInheritedAttributes(this);
   12679             :     }
   12680             :   }
   12681             : 
   12682             :   /* If there is a valid postdata *and* the user pressed
   12683             :    * reload or shift-reload, take user's permission before we
   12684             :    * repost the data to the server.
   12685             :    */
   12686           0 :   if ((aLoadType & LOAD_CMD_RELOAD) && postData) {
   12687             :     bool repost;
   12688           0 :     rv = ConfirmRepost(&repost);
   12689           0 :     if (NS_FAILED(rv)) {
   12690           0 :       return rv;
   12691             :     }
   12692             : 
   12693             :     // If the user pressed cancel in the dialog, return.  We're done here.
   12694           0 :     if (!repost) {
   12695           0 :       return NS_BINDING_ABORTED;
   12696             :     }
   12697             :   }
   12698             : 
   12699             :   // Do not inherit principal from document (security-critical!);
   12700           0 :   uint32_t flags = INTERNAL_LOAD_FLAGS_NONE;
   12701             : 
   12702           0 :   nsAutoString srcdoc;
   12703             :   bool isSrcdoc;
   12704           0 :   nsCOMPtr<nsIURI> baseURI;
   12705           0 :   aEntry->GetIsSrcdocEntry(&isSrcdoc);
   12706           0 :   if (isSrcdoc) {
   12707           0 :     aEntry->GetSrcdocData(srcdoc);
   12708           0 :     aEntry->GetBaseURI(getter_AddRefs(baseURI));
   12709           0 :     flags |= INTERNAL_LOAD_FLAGS_IS_SRCDOC;
   12710             :   } else {
   12711           0 :     srcdoc = NullString();
   12712             :   }
   12713             : 
   12714           0 :   if (!triggeringPrincipal) {
   12715           0 :     triggeringPrincipal = nsContentUtils::GetSystemPrincipal();
   12716             :   }
   12717             : 
   12718             :   // Passing nullptr as aSourceDocShell gives the same behaviour as before
   12719             :   // aSourceDocShell was introduced. According to spec we should be passing
   12720             :   // the source browsing context that was used when the history entry was
   12721             :   // first created. bug 947716 has been created to address this issue.
   12722           0 :   Maybe<nsCOMPtr<nsIURI>> emplacedResultPrincipalURI;
   12723           0 :   emplacedResultPrincipalURI.emplace(Move(resultPrincipalURI));
   12724           0 :   rv = InternalLoad(uri,
   12725             :                     originalURI,
   12726             :                     emplacedResultPrincipalURI,
   12727             :                     loadReplace,
   12728             :                     referrerURI,
   12729             :                     referrerPolicy,
   12730             :                     triggeringPrincipal,
   12731             :                     principalToInherit,
   12732             :                     flags,
   12733           0 :                     EmptyString(),      // No window target
   12734             :                     contentType.get(),  // Type hint
   12735           0 :                     NullString(),       // No forced file download
   12736             :                     postData,           // Post data stream
   12737             :                     nullptr,            // No headers stream
   12738             :                     aLoadType,          // Load type
   12739             :                     aEntry,             // SHEntry
   12740             :                     true,
   12741             :                     srcdoc,
   12742             :                     nullptr,            // Source docshell, see comment above
   12743             :                     baseURI,
   12744             :                     false,
   12745             :                     nullptr,            // No nsIDocShell
   12746           0 :                     nullptr);           // No nsIRequest
   12747           0 :   return rv;
   12748             : }
   12749             : 
   12750             : NS_IMETHODIMP
   12751           0 : nsDocShell::GetShouldSaveLayoutState(bool* aShould)
   12752             : {
   12753           0 :   *aShould = false;
   12754           0 :   if (mOSHE) {
   12755             :     // Don't capture historystate and save it in history
   12756             :     // if the page asked not to do so.
   12757           0 :     mOSHE->GetSaveLayoutStateFlag(aShould);
   12758             :   }
   12759             : 
   12760           0 :   return NS_OK;
   12761             : }
   12762             : 
   12763             : nsresult
   12764           9 : nsDocShell::PersistLayoutHistoryState()
   12765             : {
   12766           9 :   nsresult rv = NS_OK;
   12767             : 
   12768           9 :   if (mOSHE) {
   12769           0 :     bool scrollRestorationIsManual = false;
   12770           0 :     mOSHE->GetScrollRestorationIsManual(&scrollRestorationIsManual);
   12771             : 
   12772           0 :     nsCOMPtr<nsIPresShell> shell = GetPresShell();
   12773           0 :     nsCOMPtr<nsILayoutHistoryState> layoutState;
   12774           0 :     if (shell) {
   12775           0 :       rv = shell->CaptureHistoryState(getter_AddRefs(layoutState));
   12776           0 :     } else if (scrollRestorationIsManual) {
   12777             :       // Even if we don't have layout anymore, we may want to reset the current
   12778             :       // scroll state in layout history.
   12779           0 :       GetLayoutHistoryState(getter_AddRefs(layoutState));
   12780             :     }
   12781             : 
   12782           0 :     if (scrollRestorationIsManual && layoutState) {
   12783           0 :       layoutState->ResetScrollState();
   12784             :     }
   12785             :   }
   12786             : 
   12787           9 :   return rv;
   12788             : }
   12789             : 
   12790             : /* static */ nsresult
   12791           0 : nsDocShell::WalkHistoryEntries(nsISHEntry* aRootEntry,
   12792             :                                nsDocShell* aRootShell,
   12793             :                                WalkHistoryEntriesFunc aCallback,
   12794             :                                void* aData)
   12795             : {
   12796           0 :   NS_ENSURE_TRUE(aRootEntry, NS_ERROR_FAILURE);
   12797             : 
   12798           0 :   nsCOMPtr<nsISHContainer> container(do_QueryInterface(aRootEntry));
   12799           0 :   if (!container) {
   12800           0 :     return NS_ERROR_FAILURE;
   12801             :   }
   12802             : 
   12803             :   int32_t childCount;
   12804           0 :   container->GetChildCount(&childCount);
   12805           0 :   for (int32_t i = 0; i < childCount; i++) {
   12806           0 :     nsCOMPtr<nsISHEntry> childEntry;
   12807           0 :     container->GetChildAt(i, getter_AddRefs(childEntry));
   12808           0 :     if (!childEntry) {
   12809             :       // childEntry can be null for valid reasons, for example if the
   12810             :       // docshell at index i never loaded anything useful.
   12811             :       // Remember to clone also nulls in the child array (bug 464064).
   12812           0 :       aCallback(nullptr, nullptr, i, aData);
   12813           0 :       continue;
   12814             :     }
   12815             : 
   12816           0 :     nsDocShell* childShell = nullptr;
   12817           0 :     if (aRootShell) {
   12818             :       // Walk the children of aRootShell and see if one of them
   12819             :       // has srcChild as a SHEntry.
   12820             :       nsTObserverArray<nsDocLoader*>::ForwardIterator iter(
   12821           0 :         aRootShell->mChildList);
   12822           0 :       while (iter.HasMore()) {
   12823           0 :         nsDocShell* child = static_cast<nsDocShell*>(iter.GetNext());
   12824             : 
   12825           0 :         if (child->HasHistoryEntry(childEntry)) {
   12826           0 :           childShell = child;
   12827           0 :           break;
   12828             :         }
   12829             :       }
   12830             :     }
   12831           0 :     nsresult rv = aCallback(childEntry, childShell, i, aData);
   12832           0 :     NS_ENSURE_SUCCESS(rv, rv);
   12833             :   }
   12834             : 
   12835           0 :   return NS_OK;
   12836             : }
   12837             : 
   12838             : // callback data for WalkHistoryEntries
   12839           0 : struct MOZ_STACK_CLASS CloneAndReplaceData
   12840             : {
   12841           0 :   CloneAndReplaceData(uint32_t aCloneID, nsISHEntry* aReplaceEntry,
   12842             :                       bool aCloneChildren, nsISHEntry* aDestTreeParent)
   12843           0 :     : cloneID(aCloneID)
   12844             :     , cloneChildren(aCloneChildren)
   12845             :     , replaceEntry(aReplaceEntry)
   12846           0 :     , destTreeParent(aDestTreeParent)
   12847             :   {
   12848           0 :   }
   12849             : 
   12850             :   uint32_t cloneID;
   12851             :   bool cloneChildren;
   12852             :   nsISHEntry* replaceEntry;
   12853             :   nsISHEntry* destTreeParent;
   12854             :   nsCOMPtr<nsISHEntry> resultEntry;
   12855             : };
   12856             : 
   12857             : /* static */ nsresult
   12858           0 : nsDocShell::CloneAndReplaceChild(nsISHEntry* aEntry, nsDocShell* aShell,
   12859             :                                  int32_t aEntryIndex, void* aData)
   12860             : {
   12861           0 :   nsCOMPtr<nsISHEntry> dest;
   12862             : 
   12863           0 :   CloneAndReplaceData* data = static_cast<CloneAndReplaceData*>(aData);
   12864           0 :   uint32_t cloneID = data->cloneID;
   12865           0 :   nsISHEntry* replaceEntry = data->replaceEntry;
   12866             : 
   12867           0 :   nsCOMPtr<nsISHContainer> container = do_QueryInterface(data->destTreeParent);
   12868           0 :   if (!aEntry) {
   12869           0 :     if (container) {
   12870           0 :       container->AddChild(nullptr, aEntryIndex);
   12871             :     }
   12872           0 :     return NS_OK;
   12873             :   }
   12874             : 
   12875             :   uint32_t srcID;
   12876           0 :   aEntry->GetID(&srcID);
   12877             : 
   12878           0 :   nsresult rv = NS_OK;
   12879           0 :   if (srcID == cloneID) {
   12880             :     // Replace the entry
   12881           0 :     dest = replaceEntry;
   12882             :   } else {
   12883             :     // Clone the SHEntry...
   12884           0 :     rv = aEntry->Clone(getter_AddRefs(dest));
   12885           0 :     NS_ENSURE_SUCCESS(rv, rv);
   12886             :   }
   12887           0 :   dest->SetIsSubFrame(true);
   12888             : 
   12889           0 :   if (srcID != cloneID || data->cloneChildren) {
   12890             :     // Walk the children
   12891             :     CloneAndReplaceData childData(cloneID, replaceEntry,
   12892           0 :                                   data->cloneChildren, dest);
   12893             :     rv = WalkHistoryEntries(aEntry, aShell,
   12894           0 :                             CloneAndReplaceChild, &childData);
   12895           0 :     NS_ENSURE_SUCCESS(rv, rv);
   12896             :   }
   12897             : 
   12898           0 :   if (srcID != cloneID && aShell) {
   12899           0 :     aShell->SwapHistoryEntries(aEntry, dest);
   12900             :   }
   12901             : 
   12902           0 :   if (container) {
   12903           0 :     container->AddChild(dest, aEntryIndex);
   12904             :   }
   12905             : 
   12906           0 :   data->resultEntry = dest;
   12907           0 :   return rv;
   12908             : }
   12909             : 
   12910             : /* static */ nsresult
   12911           0 : nsDocShell::CloneAndReplace(nsISHEntry* aSrcEntry,
   12912             :                             nsDocShell* aSrcShell,
   12913             :                             uint32_t aCloneID,
   12914             :                             nsISHEntry* aReplaceEntry,
   12915             :                             bool aCloneChildren,
   12916             :                             nsISHEntry** aResultEntry)
   12917             : {
   12918           0 :   NS_ENSURE_ARG_POINTER(aResultEntry);
   12919           0 :   NS_ENSURE_TRUE(aReplaceEntry, NS_ERROR_FAILURE);
   12920             : 
   12921           0 :   CloneAndReplaceData data(aCloneID, aReplaceEntry, aCloneChildren, nullptr);
   12922           0 :   nsresult rv = CloneAndReplaceChild(aSrcEntry, aSrcShell, 0, &data);
   12923             : 
   12924           0 :   data.resultEntry.swap(*aResultEntry);
   12925           0 :   return rv;
   12926             : }
   12927             : 
   12928             : void
   12929           0 : nsDocShell::SwapHistoryEntries(nsISHEntry* aOldEntry, nsISHEntry* aNewEntry)
   12930             : {
   12931           0 :   if (aOldEntry == mOSHE) {
   12932           0 :     mOSHE = aNewEntry;
   12933             :   }
   12934             : 
   12935           0 :   if (aOldEntry == mLSHE) {
   12936           0 :     mLSHE = aNewEntry;
   12937             :   }
   12938           0 : }
   12939             : 
   12940             : struct SwapEntriesData
   12941             : {
   12942             :   nsDocShell* ignoreShell;     // constant; the shell to ignore
   12943             :   nsISHEntry* destTreeRoot;    // constant; the root of the dest tree
   12944             :   nsISHEntry* destTreeParent;  // constant; the node under destTreeRoot
   12945             :                                // whose children will correspond to aEntry
   12946             : };
   12947             : 
   12948             : nsresult
   12949           0 : nsDocShell::SetChildHistoryEntry(nsISHEntry* aEntry, nsDocShell* aShell,
   12950             :                                  int32_t aEntryIndex, void* aData)
   12951             : {
   12952           0 :   SwapEntriesData* data = static_cast<SwapEntriesData*>(aData);
   12953           0 :   nsDocShell* ignoreShell = data->ignoreShell;
   12954             : 
   12955           0 :   if (!aShell || aShell == ignoreShell) {
   12956           0 :     return NS_OK;
   12957             :   }
   12958             : 
   12959           0 :   nsISHEntry* destTreeRoot = data->destTreeRoot;
   12960             : 
   12961           0 :   nsCOMPtr<nsISHEntry> destEntry;
   12962           0 :   nsCOMPtr<nsISHContainer> container = do_QueryInterface(data->destTreeParent);
   12963             : 
   12964           0 :   if (container) {
   12965             :     // aEntry is a clone of some child of destTreeParent, but since the
   12966             :     // trees aren't necessarily in sync, we'll have to locate it.
   12967             :     // Note that we could set aShell's entry to null if we don't find a
   12968             :     // corresponding entry under destTreeParent.
   12969             : 
   12970             :     uint32_t targetID, id;
   12971           0 :     aEntry->GetID(&targetID);
   12972             : 
   12973             :     // First look at the given index, since this is the common case.
   12974           0 :     nsCOMPtr<nsISHEntry> entry;
   12975           0 :     container->GetChildAt(aEntryIndex, getter_AddRefs(entry));
   12976           0 :     if (entry && NS_SUCCEEDED(entry->GetID(&id)) && id == targetID) {
   12977           0 :       destEntry.swap(entry);
   12978             :     } else {
   12979             :       int32_t childCount;
   12980           0 :       container->GetChildCount(&childCount);
   12981           0 :       for (int32_t i = 0; i < childCount; ++i) {
   12982           0 :         container->GetChildAt(i, getter_AddRefs(entry));
   12983           0 :         if (!entry) {
   12984           0 :           continue;
   12985             :         }
   12986             : 
   12987           0 :         entry->GetID(&id);
   12988           0 :         if (id == targetID) {
   12989           0 :           destEntry.swap(entry);
   12990           0 :           break;
   12991             :         }
   12992             :       }
   12993             :     }
   12994             :   } else {
   12995           0 :     destEntry = destTreeRoot;
   12996             :   }
   12997             : 
   12998           0 :   aShell->SwapHistoryEntries(aEntry, destEntry);
   12999             : 
   13000             :   // Now handle the children of aEntry.
   13001           0 :   SwapEntriesData childData = { ignoreShell, destTreeRoot, destEntry };
   13002           0 :   return WalkHistoryEntries(aEntry, aShell, SetChildHistoryEntry, &childData);
   13003             : }
   13004             : 
   13005             : static nsISHEntry*
   13006          13 : GetRootSHEntry(nsISHEntry* aEntry)
   13007             : {
   13008          26 :   nsCOMPtr<nsISHEntry> rootEntry = aEntry;
   13009          13 :   nsISHEntry* result = nullptr;
   13010          15 :   while (rootEntry) {
   13011           1 :     result = rootEntry;
   13012           1 :     result->GetParent(getter_AddRefs(rootEntry));
   13013             :   }
   13014             : 
   13015          26 :   return result;
   13016             : }
   13017             : 
   13018             : void
   13019          12 : nsDocShell::SetHistoryEntry(nsCOMPtr<nsISHEntry>* aPtr, nsISHEntry* aEntry)
   13020             : {
   13021             :   // We need to sync up the docshell and session history trees for
   13022             :   // subframe navigation.  If the load was in a subframe, we forward up to
   13023             :   // the root docshell, which will then recursively sync up all docshells
   13024             :   // to their corresponding entries in the new session history tree.
   13025             :   // If we don't do this, then we can cache a content viewer on the wrong
   13026             :   // cloned entry, and subsequently restore it at the wrong time.
   13027             : 
   13028          12 :   nsISHEntry* newRootEntry = GetRootSHEntry(aEntry);
   13029          12 :   if (newRootEntry) {
   13030             :     // newRootEntry is now the new root entry.
   13031             :     // Find the old root entry as well.
   13032             : 
   13033             :     // Need a strong ref. on |oldRootEntry| so it isn't destroyed when
   13034             :     // SetChildHistoryEntry() does SwapHistoryEntries() (bug 304639).
   13035           2 :     nsCOMPtr<nsISHEntry> oldRootEntry = GetRootSHEntry(*aPtr);
   13036           1 :     if (oldRootEntry) {
   13037           0 :       nsCOMPtr<nsIDocShellTreeItem> rootAsItem;
   13038           0 :       GetSameTypeRootTreeItem(getter_AddRefs(rootAsItem));
   13039           0 :       nsCOMPtr<nsIDocShell> rootShell = do_QueryInterface(rootAsItem);
   13040           0 :       if (rootShell) { // if we're the root just set it, nothing to swap
   13041           0 :         SwapEntriesData data = { this, newRootEntry };
   13042           0 :         nsIDocShell* rootIDocShell = static_cast<nsIDocShell*>(rootShell);
   13043           0 :         nsDocShell* rootDocShell = static_cast<nsDocShell*>(rootIDocShell);
   13044             : 
   13045             : #ifdef DEBUG
   13046             :         nsresult rv =
   13047             : #endif
   13048           0 :         SetChildHistoryEntry(oldRootEntry, rootDocShell, 0, &data);
   13049           0 :         NS_ASSERTION(NS_SUCCEEDED(rv), "SetChildHistoryEntry failed");
   13050             :       }
   13051             :     }
   13052             :   }
   13053             : 
   13054          12 :   *aPtr = aEntry;
   13055          12 : }
   13056             : 
   13057             : nsresult
   13058           9 : nsDocShell::GetRootSessionHistory(nsISHistory** aReturn)
   13059             : {
   13060             :   nsresult rv;
   13061             : 
   13062          18 :   nsCOMPtr<nsIDocShellTreeItem> root;
   13063             :   // Get the root docshell
   13064           9 :   rv = GetSameTypeRootTreeItem(getter_AddRefs(root));
   13065             :   // QI to nsIWebNavigation
   13066          18 :   nsCOMPtr<nsIWebNavigation> rootAsWebnav(do_QueryInterface(root));
   13067           9 :   if (rootAsWebnav) {
   13068             :     // Get the handle to SH from the root docshell
   13069           9 :     rv = rootAsWebnav->GetSessionHistory(aReturn);
   13070             :   }
   13071          18 :   return rv;
   13072             : }
   13073             : 
   13074             : nsresult
   13075          10 : nsDocShell::GetHttpChannel(nsIChannel* aChannel, nsIHttpChannel** aReturn)
   13076             : {
   13077          10 :   NS_ENSURE_ARG_POINTER(aReturn);
   13078          10 :   if (!aChannel) {
   13079           0 :     return NS_ERROR_FAILURE;
   13080             :   }
   13081             : 
   13082          20 :   nsCOMPtr<nsIMultiPartChannel> multiPartChannel(do_QueryInterface(aChannel));
   13083          10 :   if (multiPartChannel) {
   13084           0 :     nsCOMPtr<nsIChannel> baseChannel;
   13085           0 :     multiPartChannel->GetBaseChannel(getter_AddRefs(baseChannel));
   13086           0 :     nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(baseChannel));
   13087           0 :     *aReturn = httpChannel;
   13088           0 :     NS_IF_ADDREF(*aReturn);
   13089             :   }
   13090          10 :   return NS_OK;
   13091             : }
   13092             : 
   13093             : bool
   13094           2 : nsDocShell::ShouldDiscardLayoutState(nsIHttpChannel* aChannel)
   13095             : {
   13096             :   // By default layout State will be saved.
   13097           2 :   if (!aChannel) {
   13098           0 :     return false;
   13099             :   }
   13100             : 
   13101             :   // figure out if SH should be saving layout state
   13102           2 :   bool noStore = false;
   13103           2 :   Unused << aChannel->IsNoStoreResponse(&noStore);
   13104           2 :   return noStore;
   13105             : }
   13106             : 
   13107             : NS_IMETHODIMP
   13108           0 : nsDocShell::GetEditor(nsIEditor** aEditor)
   13109             : {
   13110           0 :   NS_ENSURE_ARG_POINTER(aEditor);
   13111             : 
   13112           0 :   if (!mEditorData) {
   13113           0 :     *aEditor = nullptr;
   13114           0 :     return NS_OK;
   13115             :   }
   13116             : 
   13117           0 :   return mEditorData->GetEditor(aEditor);
   13118             : }
   13119             : 
   13120             : NS_IMETHODIMP
   13121           0 : nsDocShell::SetEditor(nsIEditor* aEditor)
   13122             : {
   13123           0 :   nsresult rv = EnsureEditorData();
   13124           0 :   if (NS_FAILED(rv)) {
   13125           0 :     return rv;
   13126             :   }
   13127             : 
   13128           0 :   return mEditorData->SetEditor(aEditor);
   13129             : }
   13130             : 
   13131             : NS_IMETHODIMP
   13132           6 : nsDocShell::GetEditable(bool* aEditable)
   13133             : {
   13134           6 :   NS_ENSURE_ARG_POINTER(aEditable);
   13135           6 :   *aEditable = mEditorData && mEditorData->GetEditable();
   13136           6 :   return NS_OK;
   13137             : }
   13138             : 
   13139             : NS_IMETHODIMP
   13140           0 : nsDocShell::GetHasEditingSession(bool* aHasEditingSession)
   13141             : {
   13142           0 :   NS_ENSURE_ARG_POINTER(aHasEditingSession);
   13143             : 
   13144           0 :   if (mEditorData) {
   13145           0 :     nsCOMPtr<nsIEditingSession> editingSession;
   13146           0 :     mEditorData->GetEditingSession(getter_AddRefs(editingSession));
   13147           0 :     *aHasEditingSession = (editingSession.get() != nullptr);
   13148             :   } else {
   13149           0 :     *aHasEditingSession = false;
   13150             :   }
   13151             : 
   13152           0 :   return NS_OK;
   13153             : }
   13154             : 
   13155             : NS_IMETHODIMP
   13156           0 : nsDocShell::MakeEditable(bool aInWaitForUriLoad)
   13157             : {
   13158           0 :   nsresult rv = EnsureEditorData();
   13159           0 :   if (NS_FAILED(rv)) {
   13160           0 :     return rv;
   13161             :   }
   13162             : 
   13163           0 :   return mEditorData->MakeEditable(aInWaitForUriLoad);
   13164             : }
   13165             : 
   13166             : bool
   13167           1 : nsDocShell::ChannelIsPost(nsIChannel* aChannel)
   13168             : {
   13169           2 :   nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aChannel));
   13170           1 :   if (!httpChannel) {
   13171           0 :     return false;
   13172             :   }
   13173             : 
   13174           2 :   nsAutoCString method;
   13175           1 :   Unused << httpChannel->GetRequestMethod(method);
   13176           1 :   return method.EqualsLiteral("POST");
   13177             : }
   13178             : 
   13179             : void
   13180           1 : nsDocShell::ExtractLastVisit(nsIChannel* aChannel,
   13181             :                              nsIURI** aURI,
   13182             :                              uint32_t* aChannelRedirectFlags)
   13183             : {
   13184           2 :   nsCOMPtr<nsIPropertyBag2> props(do_QueryInterface(aChannel));
   13185           1 :   if (!props) {
   13186           0 :     return;
   13187             :   }
   13188             : 
   13189           2 :   nsresult rv = props->GetPropertyAsInterface(
   13190           2 :     NS_LITERAL_STRING("docshell.previousURI"),
   13191             :     NS_GET_IID(nsIURI),
   13192           3 :     reinterpret_cast<void**>(aURI));
   13193             : 
   13194           1 :   if (NS_FAILED(rv)) {
   13195             :     // There is no last visit for this channel, so this must be the first
   13196             :     // link.  Link the visit to the referrer of this request, if any.
   13197             :     // Treat referrer as null if there is an error getting it.
   13198           1 :     (void)NS_GetReferrerFromChannel(aChannel, aURI);
   13199             :   } else {
   13200           0 :     rv = props->GetPropertyAsUint32(NS_LITERAL_STRING("docshell.previousFlags"),
   13201           0 :                                     aChannelRedirectFlags);
   13202             : 
   13203           0 :     NS_WARNING_ASSERTION(
   13204             :       NS_SUCCEEDED(rv),
   13205             :       "Could not fetch previous flags, URI will be treated like referrer");
   13206             :   }
   13207             : }
   13208             : 
   13209             : void
   13210           0 : nsDocShell::SaveLastVisit(nsIChannel* aChannel,
   13211             :                           nsIURI* aURI,
   13212             :                           uint32_t aChannelRedirectFlags)
   13213             : {
   13214           0 :   nsCOMPtr<nsIWritablePropertyBag2> props(do_QueryInterface(aChannel));
   13215           0 :   if (!props || !aURI) {
   13216           0 :     return;
   13217             :   }
   13218             : 
   13219           0 :   props->SetPropertyAsInterface(NS_LITERAL_STRING("docshell.previousURI"),
   13220           0 :                                 aURI);
   13221           0 :   props->SetPropertyAsUint32(NS_LITERAL_STRING("docshell.previousFlags"),
   13222           0 :                              aChannelRedirectFlags);
   13223             : }
   13224             : 
   13225             : void
   13226           1 : nsDocShell::AddURIVisit(nsIURI* aURI,
   13227             :                         nsIURI* aReferrerURI,
   13228             :                         nsIURI* aPreviousURI,
   13229             :                         uint32_t aChannelRedirectFlags,
   13230             :                         uint32_t aResponseStatus)
   13231             : {
   13232           1 :   MOZ_ASSERT(aURI, "Visited URI is null!");
   13233           1 :   MOZ_ASSERT(mLoadType != LOAD_ERROR_PAGE &&
   13234             :              mLoadType != LOAD_BYPASS_HISTORY,
   13235             :              "Do not add error or bypass pages to global history");
   13236             : 
   13237             :   // Only content-type docshells save URI visits.  Also don't do
   13238             :   // anything here if we're not supposed to use global history.
   13239           1 :   if (mItemType != typeContent || !mUseGlobalHistory || UsePrivateBrowsing()) {
   13240           0 :     return;
   13241             :   }
   13242             : 
   13243           2 :   nsCOMPtr<IHistory> history = services::GetHistoryService();
   13244             : 
   13245           1 :   if (mPrerenderGlobalHistory || history) {
   13246           1 :     uint32_t visitURIFlags = 0;
   13247             : 
   13248           1 :     if (!IsFrame()) {
   13249           1 :       visitURIFlags |= IHistory::TOP_LEVEL;
   13250             :     }
   13251             : 
   13252           1 :     if (aChannelRedirectFlags & nsIChannelEventSink::REDIRECT_TEMPORARY) {
   13253           0 :       visitURIFlags |= IHistory::REDIRECT_TEMPORARY;
   13254           1 :     } else if (aChannelRedirectFlags & nsIChannelEventSink::REDIRECT_PERMANENT) {
   13255           0 :       visitURIFlags |= IHistory::REDIRECT_PERMANENT;
   13256             :     } else {
   13257           1 :       MOZ_ASSERT(!aChannelRedirectFlags,
   13258             :                  "One of REDIRECT_TEMPORARY or REDIRECT_PERMANENT must be set "
   13259             :                  "if any flags in aChannelRedirectFlags is set.");
   13260             :     }
   13261             : 
   13262           1 :     if (aResponseStatus >= 300 && aResponseStatus < 400) {
   13263           0 :       visitURIFlags |= IHistory::REDIRECT_SOURCE;
   13264             :     }
   13265             :     // Errors 400-501 and 505 are considered unrecoverable, in the sense a
   13266             :     // simple retry attempt by the user is unlikely to solve them.
   13267             :     // 408 is special cased, since may actually indicate a temporary
   13268             :     // connection problem.
   13269           1 :     else if (aResponseStatus != 408 &&
   13270           0 :              ((aResponseStatus >= 400 && aResponseStatus <= 501) ||
   13271             :               aResponseStatus == 505)) {
   13272           0 :       visitURIFlags |= IHistory::UNRECOVERABLE_ERROR;
   13273             :     }
   13274             : 
   13275           1 :     if (mPrerenderGlobalHistory) {
   13276           0 :       mPrerenderGlobalHistory->VisitURI(aURI,
   13277             :                                         aPreviousURI,
   13278             :                                         aReferrerURI,
   13279           0 :                                         visitURIFlags);
   13280             :     } else {
   13281           1 :       (void)history->VisitURI(aURI, aPreviousURI, visitURIFlags);
   13282             :     }
   13283           0 :   } else if (mGlobalHistory) {
   13284             :     // Falls back to sync global history interface.
   13285           0 :     (void)mGlobalHistory->AddURI(aURI,
   13286             :                                  !!aChannelRedirectFlags,
   13287           0 :                                  !IsFrame(),
   13288           0 :                                  aReferrerURI);
   13289             :   }
   13290             : }
   13291             : 
   13292             : //*****************************************************************************
   13293             : // nsDocShell: Helper Routines
   13294             : //*****************************************************************************
   13295             : 
   13296             : NS_IMETHODIMP
   13297           0 : nsDocShell::SetLoadType(uint32_t aLoadType)
   13298             : {
   13299           0 :   mLoadType = aLoadType;
   13300           0 :   return NS_OK;
   13301             : }
   13302             : 
   13303             : NS_IMETHODIMP
   13304          14 : nsDocShell::GetLoadType(uint32_t* aLoadType)
   13305             : {
   13306          14 :   *aLoadType = mLoadType;
   13307          14 :   return NS_OK;
   13308             : }
   13309             : 
   13310             : nsresult
   13311           0 : nsDocShell::ConfirmRepost(bool* aRepost)
   13312             : {
   13313           0 :   nsCOMPtr<nsIPrompt> prompter;
   13314           0 :   CallGetInterface(this, static_cast<nsIPrompt**>(getter_AddRefs(prompter)));
   13315           0 :   if (!prompter) {
   13316           0 :     return NS_ERROR_NOT_AVAILABLE;
   13317             :   }
   13318             : 
   13319             :   nsCOMPtr<nsIStringBundleService> stringBundleService =
   13320           0 :     mozilla::services::GetStringBundleService();
   13321           0 :   if (!stringBundleService) {
   13322           0 :     return NS_ERROR_FAILURE;
   13323             :   }
   13324             : 
   13325           0 :   nsCOMPtr<nsIStringBundle> appBundle;
   13326           0 :   nsresult rv = stringBundleService->CreateBundle(kAppstringsBundleURL,
   13327           0 :                                                   getter_AddRefs(appBundle));
   13328           0 :   NS_ENSURE_SUCCESS(rv, rv);
   13329             : 
   13330           0 :   nsCOMPtr<nsIStringBundle> brandBundle;
   13331           0 :   rv = stringBundleService->CreateBundle(kBrandBundleURL,
   13332           0 :                                          getter_AddRefs(brandBundle));
   13333           0 :   NS_ENSURE_SUCCESS(rv, rv);
   13334             : 
   13335           0 :   NS_ASSERTION(prompter && brandBundle && appBundle,
   13336             :                "Unable to set up repost prompter.");
   13337             : 
   13338           0 :   nsXPIDLString brandName;
   13339           0 :   rv = brandBundle->GetStringFromName(u"brandShortName",
   13340           0 :                                       getter_Copies(brandName));
   13341             : 
   13342           0 :   nsXPIDLString msgString, button0Title;
   13343           0 :   if (NS_FAILED(rv)) { // No brand, use the generic version.
   13344           0 :     rv = appBundle->GetStringFromName(u"confirmRepostPrompt",
   13345           0 :                                       getter_Copies(msgString));
   13346             :   } else {
   13347             :     // Brand available - if the app has an override file with formatting, the
   13348             :     // app name will be included. Without an override, the prompt will look
   13349             :     // like the generic version.
   13350           0 :     const char16_t* formatStrings[] = { brandName.get() };
   13351           0 :     rv = appBundle->FormatStringFromName(u"confirmRepostPrompt",
   13352             :                                          formatStrings,
   13353           0 :                                          ArrayLength(formatStrings),
   13354           0 :                                          getter_Copies(msgString));
   13355             :   }
   13356           0 :   if (NS_FAILED(rv)) {
   13357           0 :     return rv;
   13358             :   }
   13359             : 
   13360           0 :   rv = appBundle->GetStringFromName(u"resendButton.label",
   13361           0 :                                     getter_Copies(button0Title));
   13362           0 :   if (NS_FAILED(rv)) {
   13363           0 :     return rv;
   13364             :   }
   13365             : 
   13366             :   int32_t buttonPressed;
   13367             :   // The actual value here is irrelevant, but we can't pass an invalid
   13368             :   // bool through XPConnect.
   13369           0 :   bool checkState = false;
   13370           0 :   rv = prompter->ConfirmEx(
   13371             :     nullptr, msgString.get(),
   13372             :     (nsIPrompt::BUTTON_POS_0 * nsIPrompt::BUTTON_TITLE_IS_STRING) +
   13373             :       (nsIPrompt::BUTTON_POS_1 * nsIPrompt::BUTTON_TITLE_CANCEL),
   13374           0 :     button0Title.get(), nullptr, nullptr, nullptr, &checkState, &buttonPressed);
   13375           0 :   if (NS_FAILED(rv)) {
   13376           0 :     return rv;
   13377             :   }
   13378             : 
   13379           0 :   *aRepost = (buttonPressed == 0);
   13380           0 :   return NS_OK;
   13381             : }
   13382             : 
   13383             : NS_IMETHODIMP
   13384           0 : nsDocShell::GetPromptAndStringBundle(nsIPrompt** aPrompt,
   13385             :                                      nsIStringBundle** aStringBundle)
   13386             : {
   13387           0 :   NS_ENSURE_SUCCESS(GetInterface(NS_GET_IID(nsIPrompt), (void**)aPrompt),
   13388             :                     NS_ERROR_FAILURE);
   13389             : 
   13390             :   nsCOMPtr<nsIStringBundleService> stringBundleService =
   13391           0 :     mozilla::services::GetStringBundleService();
   13392           0 :   NS_ENSURE_TRUE(stringBundleService, NS_ERROR_FAILURE);
   13393             : 
   13394           0 :   NS_ENSURE_SUCCESS(
   13395             :     stringBundleService->CreateBundle(kAppstringsBundleURL, aStringBundle),
   13396             :     NS_ERROR_FAILURE);
   13397             : 
   13398           0 :   return NS_OK;
   13399             : }
   13400             : 
   13401             : NS_IMETHODIMP
   13402           0 : nsDocShell::GetChildOffset(nsIDOMNode* aChild, nsIDOMNode* aParent,
   13403             :                            int32_t* aOffset)
   13404             : {
   13405           0 :   NS_ENSURE_ARG_POINTER(aChild || aParent);
   13406             : 
   13407           0 :   nsCOMPtr<nsIDOMNodeList> childNodes;
   13408           0 :   NS_ENSURE_SUCCESS(aParent->GetChildNodes(getter_AddRefs(childNodes)),
   13409             :                     NS_ERROR_FAILURE);
   13410           0 :   NS_ENSURE_TRUE(childNodes, NS_ERROR_FAILURE);
   13411             : 
   13412           0 :   int32_t i = 0;
   13413             : 
   13414           0 :   for (; true; i++) {
   13415           0 :     nsCOMPtr<nsIDOMNode> childNode;
   13416           0 :     NS_ENSURE_SUCCESS(childNodes->Item(i, getter_AddRefs(childNode)),
   13417             :                       NS_ERROR_FAILURE);
   13418           0 :     NS_ENSURE_TRUE(childNode, NS_ERROR_FAILURE);
   13419             : 
   13420           0 :     if (childNode.get() == aChild) {
   13421           0 :       *aOffset = i;
   13422           0 :       return NS_OK;
   13423             :     }
   13424           0 :   }
   13425             : 
   13426             :   return NS_ERROR_FAILURE;
   13427             : }
   13428             : 
   13429             : nsIScrollableFrame*
   13430           0 : nsDocShell::GetRootScrollFrame()
   13431             : {
   13432           0 :   nsCOMPtr<nsIPresShell> shell = GetPresShell();
   13433           0 :   NS_ENSURE_TRUE(shell, nullptr);
   13434             : 
   13435           0 :   return shell->GetRootScrollFrameAsScrollableExternal();
   13436             : }
   13437             : 
   13438             : NS_IMETHODIMP
   13439         325 : nsDocShell::EnsureScriptEnvironment()
   13440             : {
   13441         325 :   if (mScriptGlobal) {
   13442         319 :     return NS_OK;
   13443             :   }
   13444             : 
   13445           6 :   if (mIsBeingDestroyed) {
   13446           1 :     return NS_ERROR_NOT_AVAILABLE;
   13447             :   }
   13448             : 
   13449             : #ifdef DEBUG
   13450           5 :   NS_ASSERTION(!mInEnsureScriptEnv,
   13451             :                "Infinite loop! Calling EnsureScriptEnvironment() from "
   13452             :                "within EnsureScriptEnvironment()!");
   13453             : 
   13454             :   // Yeah, this isn't re-entrant safe, but that's ok since if we
   13455             :   // re-enter this method, we'll infinitely loop...
   13456          10 :   AutoRestore<bool> boolSetter(mInEnsureScriptEnv);
   13457           5 :   mInEnsureScriptEnv = true;
   13458             : #endif
   13459             : 
   13460          10 :   nsCOMPtr<nsIWebBrowserChrome> browserChrome(do_GetInterface(mTreeOwner));
   13461           5 :   NS_ENSURE_TRUE(browserChrome, NS_ERROR_NOT_AVAILABLE);
   13462             : 
   13463             :   uint32_t chromeFlags;
   13464           5 :   browserChrome->GetChromeFlags(&chromeFlags);
   13465             : 
   13466             :   bool isModalContentWindow =
   13467           7 :     (mItemType == typeContent) &&
   13468           7 :     (chromeFlags & nsIWebBrowserChrome::CHROME_MODAL_CONTENT_WINDOW);
   13469             :   // There can be various other content docshells associated with the
   13470             :   // top-level window, like sidebars. Make sure that we only create an
   13471             :   // nsGlobalModalWindow for the primary content shell.
   13472           5 :   if (isModalContentWindow) {
   13473           0 :     nsCOMPtr<nsIDocShellTreeItem> primaryItem;
   13474             :     nsresult rv =
   13475           0 :       mTreeOwner->GetPrimaryContentShell(getter_AddRefs(primaryItem));
   13476           0 :     NS_ENSURE_SUCCESS(rv, rv);
   13477           0 :     isModalContentWindow = (primaryItem == this);
   13478             :   }
   13479             : 
   13480             :   // If our window is modal and we're not opened as chrome, make
   13481             :   // this window a modal content window.
   13482             :   mScriptGlobal =
   13483           5 :     NS_NewScriptGlobalObject(mItemType == typeChrome, isModalContentWindow);
   13484           5 :   MOZ_ASSERT(mScriptGlobal);
   13485             : 
   13486           5 :   mScriptGlobal->SetDocShell(this);
   13487             : 
   13488             :   // Ensure the script object is set up to run script.
   13489           5 :   return mScriptGlobal->EnsureScriptEnvironment();
   13490             : }
   13491             : 
   13492             : NS_IMETHODIMP
   13493           0 : nsDocShell::EnsureEditorData()
   13494             : {
   13495           0 :   bool openDocHasDetachedEditor = mOSHE && mOSHE->HasDetachedEditor();
   13496           0 :   if (!mEditorData && !mIsBeingDestroyed && !openDocHasDetachedEditor) {
   13497             :     // We shouldn't recreate the editor data if it already exists, or
   13498             :     // we're shutting down, or we already have a detached editor data
   13499             :     // stored in the session history. We should only have one editordata
   13500             :     // per docshell.
   13501           0 :     mEditorData = new nsDocShellEditorData(this);
   13502             :   }
   13503             : 
   13504           0 :   return mEditorData ? NS_OK : NS_ERROR_NOT_AVAILABLE;
   13505             : }
   13506             : 
   13507             : nsresult
   13508           0 : nsDocShell::EnsureTransferableHookData()
   13509             : {
   13510           0 :   if (!mTransferableHookData) {
   13511           0 :     mTransferableHookData = new nsTransferableHookData();
   13512             :   }
   13513             : 
   13514           0 :   return NS_OK;
   13515             : }
   13516             : 
   13517             : NS_IMETHODIMP
   13518           0 : nsDocShell::EnsureFind()
   13519             : {
   13520             :   nsresult rv;
   13521           0 :   if (!mFind) {
   13522           0 :     mFind = do_CreateInstance("@mozilla.org/embedcomp/find;1", &rv);
   13523           0 :     if (NS_FAILED(rv)) {
   13524           0 :       return rv;
   13525             :     }
   13526             :   }
   13527             : 
   13528             :   // we promise that the nsIWebBrowserFind that we return has been set
   13529             :   // up to point to the focused, or content window, so we have to
   13530             :   // set that up each time.
   13531             : 
   13532           0 :   nsIScriptGlobalObject* scriptGO = GetScriptGlobalObject();
   13533           0 :   NS_ENSURE_TRUE(scriptGO, NS_ERROR_UNEXPECTED);
   13534             : 
   13535             :   // default to our window
   13536           0 :   nsCOMPtr<nsPIDOMWindowOuter> ourWindow = do_QueryInterface(scriptGO);
   13537           0 :   nsCOMPtr<nsPIDOMWindowOuter> windowToSearch;
   13538           0 :   nsFocusManager::GetFocusedDescendant(ourWindow, true,
   13539           0 :                                        getter_AddRefs(windowToSearch));
   13540             : 
   13541           0 :   nsCOMPtr<nsIWebBrowserFindInFrames> findInFrames = do_QueryInterface(mFind);
   13542           0 :   if (!findInFrames) {
   13543           0 :     return NS_ERROR_NO_INTERFACE;
   13544             :   }
   13545             : 
   13546           0 :   rv = findInFrames->SetRootSearchFrame(ourWindow);
   13547           0 :   if (NS_FAILED(rv)) {
   13548           0 :     return rv;
   13549             :   }
   13550           0 :   rv = findInFrames->SetCurrentSearchFrame(windowToSearch);
   13551           0 :   if (NS_FAILED(rv)) {
   13552           0 :     return rv;
   13553             :   }
   13554             : 
   13555           0 :   return NS_OK;
   13556             : }
   13557             : 
   13558             : bool
   13559          53 : nsDocShell::IsFrame()
   13560             : {
   13561         106 :   nsCOMPtr<nsIDocShellTreeItem> parent;
   13562          53 :   GetSameTypeParent(getter_AddRefs(parent));
   13563         106 :   return !!parent;
   13564             : }
   13565             : 
   13566             : NS_IMETHODIMP
   13567           2 : nsDocShell::IsBeingDestroyed(bool* aDoomed)
   13568             : {
   13569           2 :   NS_ENSURE_ARG(aDoomed);
   13570           2 :   *aDoomed = mIsBeingDestroyed;
   13571           2 :   return NS_OK;
   13572             : }
   13573             : 
   13574             : NS_IMETHODIMP
   13575           5 : nsDocShell::GetIsExecutingOnLoadHandler(bool* aResult)
   13576             : {
   13577           5 :   NS_ENSURE_ARG(aResult);
   13578           5 :   *aResult = mIsExecutingOnLoadHandler;
   13579           5 :   return NS_OK;
   13580             : }
   13581             : 
   13582             : NS_IMETHODIMP
   13583          22 : nsDocShell::GetLayoutHistoryState(nsILayoutHistoryState** aLayoutHistoryState)
   13584             : {
   13585          22 :   if (mOSHE) {
   13586           4 :     mOSHE->GetLayoutHistoryState(aLayoutHistoryState);
   13587             :   }
   13588          22 :   return NS_OK;
   13589             : }
   13590             : 
   13591             : NS_IMETHODIMP
   13592           4 : nsDocShell::SetLayoutHistoryState(nsILayoutHistoryState* aLayoutHistoryState)
   13593             : {
   13594           4 :   if (mOSHE) {
   13595           1 :     mOSHE->SetLayoutHistoryState(aLayoutHistoryState);
   13596             :   }
   13597           4 :   return NS_OK;
   13598             : }
   13599             : 
   13600           0 : nsRefreshTimer::nsRefreshTimer()
   13601           0 :   : mDelay(0), mRepeat(false), mMetaRefresh(false)
   13602             : {
   13603           0 : }
   13604             : 
   13605           0 : nsRefreshTimer::~nsRefreshTimer()
   13606             : {
   13607           0 : }
   13608             : 
   13609           0 : NS_IMPL_ADDREF(nsRefreshTimer)
   13610           0 : NS_IMPL_RELEASE(nsRefreshTimer)
   13611             : 
   13612           0 : NS_INTERFACE_MAP_BEGIN(nsRefreshTimer)
   13613           0 :   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsITimerCallback)
   13614           0 :   NS_INTERFACE_MAP_ENTRY(nsITimerCallback)
   13615           0 : NS_INTERFACE_MAP_END_THREADSAFE
   13616             : 
   13617             : NS_IMETHODIMP
   13618           0 : nsRefreshTimer::Notify(nsITimer* aTimer)
   13619             : {
   13620           0 :   NS_ASSERTION(mDocShell, "DocShell is somehow null");
   13621             : 
   13622           0 :   if (mDocShell && aTimer) {
   13623             :     // Get the delay count to determine load type
   13624           0 :     uint32_t delay = 0;
   13625           0 :     aTimer->GetDelay(&delay);
   13626           0 :     mDocShell->ForceRefreshURIFromTimer(mURI, delay, mMetaRefresh, aTimer);
   13627             :   }
   13628           0 :   return NS_OK;
   13629             : }
   13630             : 
   13631           5 : nsDocShell::InterfaceRequestorProxy::InterfaceRequestorProxy(
   13632           5 :     nsIInterfaceRequestor* aRequestor)
   13633             : {
   13634           5 :   if (aRequestor) {
   13635           5 :     mWeakPtr = do_GetWeakReference(aRequestor);
   13636             :   }
   13637           5 : }
   13638             : 
   13639           0 : nsDocShell::InterfaceRequestorProxy::~InterfaceRequestorProxy()
   13640             : {
   13641           0 :   mWeakPtr = nullptr;
   13642           0 : }
   13643             : 
   13644        3196 : NS_IMPL_ISUPPORTS(nsDocShell::InterfaceRequestorProxy, nsIInterfaceRequestor)
   13645             : 
   13646             : NS_IMETHODIMP
   13647         612 : nsDocShell::InterfaceRequestorProxy::GetInterface(const nsIID& aIID,
   13648             :                                                   void** aSink)
   13649             : {
   13650         612 :   NS_ENSURE_ARG_POINTER(aSink);
   13651        1224 :   nsCOMPtr<nsIInterfaceRequestor> ifReq = do_QueryReferent(mWeakPtr);
   13652         612 :   if (ifReq) {
   13653         612 :     return ifReq->GetInterface(aIID, aSink);
   13654             :   }
   13655           0 :   *aSink = nullptr;
   13656           0 :   return NS_NOINTERFACE;
   13657             : }
   13658             : 
   13659             : nsresult
   13660           0 : nsDocShell::SetBaseUrlForWyciwyg(nsIContentViewer* aContentViewer)
   13661             : {
   13662           0 :   if (!aContentViewer) {
   13663           0 :     return NS_ERROR_FAILURE;
   13664             :   }
   13665             : 
   13666           0 :   nsCOMPtr<nsIURI> baseURI;
   13667           0 :   nsresult rv = NS_ERROR_NOT_AVAILABLE;
   13668             : 
   13669           0 :   if (sURIFixup) {
   13670           0 :     rv = sURIFixup->CreateExposableURI(mCurrentURI, getter_AddRefs(baseURI));
   13671             :   }
   13672             : 
   13673             :   // Get the current document and set the base uri
   13674           0 :   if (baseURI) {
   13675           0 :     nsIDocument* document = aContentViewer->GetDocument();
   13676           0 :     if (document) {
   13677           0 :       document->SetBaseURI(baseURI);
   13678             :     }
   13679             :   }
   13680           0 :   return rv;
   13681             : }
   13682             : 
   13683             : //*****************************************************************************
   13684             : // nsDocShell::nsIAuthPromptProvider
   13685             : //*****************************************************************************
   13686             : 
   13687             : NS_IMETHODIMP
   13688           0 : nsDocShell::GetAuthPrompt(uint32_t aPromptReason, const nsIID& aIID,
   13689             :                           void** aResult)
   13690             : {
   13691             :   // a priority prompt request will override a false mAllowAuth setting
   13692           0 :   bool priorityPrompt = (aPromptReason == PROMPT_PROXY);
   13693             : 
   13694           0 :   if (!mAllowAuth && !priorityPrompt) {
   13695           0 :     return NS_ERROR_NOT_AVAILABLE;
   13696             :   }
   13697             : 
   13698             :   // we're either allowing auth, or it's a proxy request
   13699             :   nsresult rv;
   13700             :   nsCOMPtr<nsIPromptFactory> wwatch =
   13701           0 :     do_GetService(NS_WINDOWWATCHER_CONTRACTID, &rv);
   13702           0 :   NS_ENSURE_SUCCESS(rv, rv);
   13703             : 
   13704           0 :   rv = EnsureScriptEnvironment();
   13705           0 :   NS_ENSURE_SUCCESS(rv, rv);
   13706             : 
   13707             :   // Get the an auth prompter for our window so that the parenting
   13708             :   // of the dialogs works as it should when using tabs.
   13709             : 
   13710           0 :   return wwatch->GetPrompt(mScriptGlobal->AsOuter(), aIID,
   13711           0 :                            reinterpret_cast<void**>(aResult));
   13712             : }
   13713             : 
   13714             : //*****************************************************************************
   13715             : // nsDocShell::nsILoadContext
   13716             : //*****************************************************************************
   13717             : 
   13718             : NS_IMETHODIMP
   13719           9 : nsDocShell::GetAssociatedWindow(mozIDOMWindowProxy** aWindow)
   13720             : {
   13721           9 :   CallGetInterface(this, aWindow);
   13722           9 :   return NS_OK;
   13723             : }
   13724             : 
   13725             : NS_IMETHODIMP
   13726           0 : nsDocShell::GetTopWindow(mozIDOMWindowProxy** aWindow)
   13727             : {
   13728           0 :   nsCOMPtr<nsPIDOMWindowOuter> win = GetWindow();
   13729           0 :   if (win) {
   13730           0 :     win = win->GetTop();
   13731             :   }
   13732           0 :   win.forget(aWindow);
   13733           0 :   return NS_OK;
   13734             : }
   13735             : 
   13736             : NS_IMETHODIMP
   13737          17 : nsDocShell::GetTopFrameElement(nsIDOMElement** aElement)
   13738             : {
   13739          17 :   *aElement = nullptr;
   13740          34 :   nsCOMPtr<nsPIDOMWindowOuter> win = GetWindow();
   13741          17 :   if (!win) {
   13742           0 :     return NS_OK;
   13743             :   }
   13744             : 
   13745          34 :   nsCOMPtr<nsPIDOMWindowOuter> top = win->GetScriptableTop();
   13746          17 :   NS_ENSURE_TRUE(top, NS_ERROR_FAILURE);
   13747             : 
   13748             :   // GetFrameElementInternal, /not/ GetScriptableFrameElement -- if |top| is
   13749             :   // inside <iframe mozbrowser>, we want to return the iframe, not null.
   13750             :   // And we want to cross the content/chrome boundary.
   13751             :   nsCOMPtr<nsIDOMElement> elt =
   13752          34 :     do_QueryInterface(top->GetFrameElementInternal());
   13753          17 :   elt.forget(aElement);
   13754          17 :   return NS_OK;
   13755             : }
   13756             : 
   13757             : NS_IMETHODIMP
   13758           0 : nsDocShell::GetNestedFrameId(uint64_t* aId)
   13759             : {
   13760           0 :   *aId = 0;
   13761           0 :   return NS_OK;
   13762             : }
   13763             : 
   13764             : NS_IMETHODIMP
   13765           7 : nsDocShell::GetUseTrackingProtection(bool* aUseTrackingProtection)
   13766             : {
   13767           7 :   *aUseTrackingProtection  = false;
   13768             : 
   13769             :   static bool sTPEnabled = false;
   13770             :   static bool sTPInPBEnabled = false;
   13771             :   static bool sPrefsInit = false;
   13772             : 
   13773           7 :   if (!sPrefsInit) {
   13774           2 :     sPrefsInit = true;
   13775             :     Preferences::AddBoolVarCache(&sTPEnabled,
   13776           2 :       "privacy.trackingprotection.enabled", false);
   13777             :     Preferences::AddBoolVarCache(&sTPInPBEnabled,
   13778           2 :       "privacy.trackingprotection.pbmode.enabled", false);
   13779             :   }
   13780             : 
   13781          14 :   if (mUseTrackingProtection || sTPEnabled ||
   13782           7 :       (UsePrivateBrowsing() && sTPInPBEnabled)) {
   13783           0 :     *aUseTrackingProtection = true;
   13784           0 :     return NS_OK;
   13785             :   }
   13786             : 
   13787          14 :   RefPtr<nsDocShell> parent = GetParentDocshell();
   13788           7 :   if (parent) {
   13789           0 :     return parent->GetUseTrackingProtection(aUseTrackingProtection);
   13790             :   }
   13791             : 
   13792           7 :   return NS_OK;
   13793             : }
   13794             : 
   13795             : NS_IMETHODIMP
   13796           0 : nsDocShell::SetUseTrackingProtection(bool aUseTrackingProtection)
   13797             : {
   13798           0 :   mUseTrackingProtection = aUseTrackingProtection;
   13799           0 :   return NS_OK;
   13800             : }
   13801             : 
   13802             : NS_IMETHODIMP
   13803           3 : nsDocShell::GetIsContent(bool* aIsContent)
   13804             : {
   13805           3 :   *aIsContent = (mItemType == typeContent);
   13806           3 :   return NS_OK;
   13807             : }
   13808             : 
   13809             : bool
   13810           0 : nsDocShell::IsOKToLoadURI(nsIURI* aURI)
   13811             : {
   13812           0 :   NS_PRECONDITION(aURI, "Must have a URI!");
   13813             : 
   13814           0 :   if (!mFiredUnloadEvent) {
   13815           0 :     return true;
   13816             :   }
   13817             : 
   13818           0 :   if (!mLoadingURI) {
   13819           0 :     return false;
   13820             :   }
   13821             : 
   13822             :   nsCOMPtr<nsIScriptSecurityManager> secMan =
   13823           0 :     do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID);
   13824           0 :   return secMan &&
   13825           0 :          NS_SUCCEEDED(secMan->CheckSameOriginURI(aURI, mLoadingURI, false));
   13826             : }
   13827             : 
   13828             : //
   13829             : // Routines for selection and clipboard
   13830             : //
   13831             : nsresult
   13832           0 : nsDocShell::GetControllerForCommand(const char* aCommand,
   13833             :                                     nsIController** aResult)
   13834             : {
   13835           0 :   NS_ENSURE_ARG_POINTER(aResult);
   13836           0 :   *aResult = nullptr;
   13837             : 
   13838           0 :   NS_ENSURE_TRUE(mScriptGlobal, NS_ERROR_FAILURE);
   13839             : 
   13840           0 :   nsCOMPtr<nsPIWindowRoot> root = mScriptGlobal->GetTopWindowRoot();
   13841           0 :   NS_ENSURE_TRUE(root, NS_ERROR_FAILURE);
   13842             : 
   13843           0 :   return root->GetControllerForCommand(aCommand, aResult);
   13844             : }
   13845             : 
   13846             : NS_IMETHODIMP
   13847           0 : nsDocShell::IsCommandEnabled(const char* aCommand, bool* aResult)
   13848             : {
   13849           0 :   NS_ENSURE_ARG_POINTER(aResult);
   13850           0 :   *aResult = false;
   13851             : 
   13852           0 :   nsresult rv = NS_ERROR_FAILURE;
   13853             : 
   13854           0 :   nsCOMPtr<nsIController> controller;
   13855           0 :   rv = GetControllerForCommand(aCommand, getter_AddRefs(controller));
   13856           0 :   if (controller) {
   13857           0 :     rv = controller->IsCommandEnabled(aCommand, aResult);
   13858             :   }
   13859             : 
   13860           0 :   return rv;
   13861             : }
   13862             : 
   13863             : NS_IMETHODIMP
   13864           0 : nsDocShell::DoCommand(const char* aCommand)
   13865             : {
   13866           0 :   nsresult rv = NS_ERROR_FAILURE;
   13867             : 
   13868           0 :   nsCOMPtr<nsIController> controller;
   13869           0 :   rv = GetControllerForCommand(aCommand, getter_AddRefs(controller));
   13870           0 :   if (controller) {
   13871           0 :     rv = controller->DoCommand(aCommand);
   13872             :   }
   13873             : 
   13874           0 :   return rv;
   13875             : }
   13876             : 
   13877             : NS_IMETHODIMP
   13878           0 : nsDocShell::DoCommandWithParams(const char* aCommand, nsICommandParams* aParams)
   13879             : {
   13880           0 :   nsCOMPtr<nsIController> controller;
   13881           0 :   nsresult rv = GetControllerForCommand(aCommand, getter_AddRefs(controller));
   13882           0 :   if (NS_WARN_IF(NS_FAILED(rv))) {
   13883           0 :     return rv;
   13884             :   }
   13885             : 
   13886             :   nsCOMPtr<nsICommandController> commandController =
   13887           0 :     do_QueryInterface(controller, &rv);
   13888           0 :   if (NS_WARN_IF(NS_FAILED(rv))) {
   13889           0 :     return rv;
   13890             :   }
   13891             : 
   13892           0 :   return commandController->DoCommandWithParams(aCommand, aParams);
   13893             : }
   13894             : 
   13895             : nsresult
   13896           0 : nsDocShell::EnsureCommandHandler()
   13897             : {
   13898           0 :   if (!mCommandManager) {
   13899             :     nsCOMPtr<nsPICommandUpdater> commandUpdater =
   13900           0 :       do_CreateInstance("@mozilla.org/embedcomp/command-manager;1");
   13901           0 :     if (!commandUpdater) {
   13902           0 :       return NS_ERROR_OUT_OF_MEMORY;
   13903             :     }
   13904             : 
   13905           0 :     nsCOMPtr<nsPIDOMWindowOuter> domWindow = GetWindow();
   13906           0 :     nsresult rv = commandUpdater->Init(domWindow);
   13907           0 :     if (NS_SUCCEEDED(rv)) {
   13908           0 :       mCommandManager = do_QueryInterface(commandUpdater);
   13909             :     }
   13910             :   }
   13911             : 
   13912           0 :   return mCommandManager ? NS_OK : NS_ERROR_FAILURE;
   13913             : }
   13914             : 
   13915             : NS_IMETHODIMP
   13916           0 : nsDocShell::CanCutSelection(bool* aResult)
   13917             : {
   13918           0 :   return IsCommandEnabled("cmd_cut", aResult);
   13919             : }
   13920             : 
   13921             : NS_IMETHODIMP
   13922           0 : nsDocShell::CanCopySelection(bool* aResult)
   13923             : {
   13924           0 :   return IsCommandEnabled("cmd_copy", aResult);
   13925             : }
   13926             : 
   13927             : NS_IMETHODIMP
   13928           0 : nsDocShell::CanCopyLinkLocation(bool* aResult)
   13929             : {
   13930           0 :   return IsCommandEnabled("cmd_copyLink", aResult);
   13931             : }
   13932             : 
   13933             : NS_IMETHODIMP
   13934           0 : nsDocShell::CanCopyImageLocation(bool* aResult)
   13935             : {
   13936           0 :   return IsCommandEnabled("cmd_copyImageLocation", aResult);
   13937             : }
   13938             : 
   13939             : NS_IMETHODIMP
   13940           0 : nsDocShell::CanCopyImageContents(bool* aResult)
   13941             : {
   13942           0 :   return IsCommandEnabled("cmd_copyImageContents", aResult);
   13943             : }
   13944             : 
   13945             : NS_IMETHODIMP
   13946           0 : nsDocShell::CanPaste(bool* aResult)
   13947             : {
   13948           0 :   return IsCommandEnabled("cmd_paste", aResult);
   13949             : }
   13950             : 
   13951             : NS_IMETHODIMP
   13952           0 : nsDocShell::CutSelection(void)
   13953             : {
   13954           0 :   return DoCommand("cmd_cut");
   13955             : }
   13956             : 
   13957             : NS_IMETHODIMP
   13958           0 : nsDocShell::CopySelection(void)
   13959             : {
   13960           0 :   return DoCommand("cmd_copy");
   13961             : }
   13962             : 
   13963             : NS_IMETHODIMP
   13964           0 : nsDocShell::CopyLinkLocation(void)
   13965             : {
   13966           0 :   return DoCommand("cmd_copyLink");
   13967             : }
   13968             : 
   13969             : NS_IMETHODIMP
   13970           0 : nsDocShell::CopyImageLocation(void)
   13971             : {
   13972           0 :   return DoCommand("cmd_copyImageLocation");
   13973             : }
   13974             : 
   13975             : NS_IMETHODIMP
   13976           0 : nsDocShell::CopyImageContents(void)
   13977             : {
   13978           0 :   return DoCommand("cmd_copyImageContents");
   13979             : }
   13980             : 
   13981             : NS_IMETHODIMP
   13982           0 : nsDocShell::Paste(void)
   13983             : {
   13984           0 :   return DoCommand("cmd_paste");
   13985             : }
   13986             : 
   13987             : NS_IMETHODIMP
   13988           0 : nsDocShell::SelectAll(void)
   13989             : {
   13990           0 :   return DoCommand("cmd_selectAll");
   13991             : }
   13992             : 
   13993             : //
   13994             : // SelectNone
   13995             : //
   13996             : // Collapses the current selection, insertion point ends up at beginning
   13997             : // of previous selection.
   13998             : //
   13999             : NS_IMETHODIMP
   14000           0 : nsDocShell::SelectNone(void)
   14001             : {
   14002           0 :   return DoCommand("cmd_selectNone");
   14003             : }
   14004             : 
   14005             : // link handling
   14006             : 
   14007           0 : class OnLinkClickEvent : public Runnable
   14008             : {
   14009             : public:
   14010             :   OnLinkClickEvent(nsDocShell* aHandler, nsIContent* aContent,
   14011             :                    nsIURI* aURI,
   14012             :                    const char16_t* aTargetSpec,
   14013             :                    const nsAString& aFileName,
   14014             :                    nsIInputStream* aPostDataStream,
   14015             :                    nsIInputStream* aHeadersDataStream,
   14016             :                    bool aNoOpenerImplied,
   14017             :                    bool aIsTrusted,
   14018             :                    nsIPrincipal* aTriggeringPrincipal);
   14019             : 
   14020           0 :   NS_IMETHOD Run() override
   14021             :   {
   14022           0 :     nsAutoPopupStatePusher popupStatePusher(mPopupState);
   14023             : 
   14024             :     // We need to set up an AutoJSAPI here for the following reason: When we do
   14025             :     // OnLinkClickSync we'll eventually end up in nsGlobalWindow::OpenInternal
   14026             :     // which only does popup blocking if !LegacyIsCallerChromeOrNativeCode().
   14027             :     // So we need to fake things so that we don't look like native code as far
   14028             :     // as LegacyIsCallerNativeCode() is concerned.
   14029           0 :     AutoJSAPI jsapi;
   14030           0 :     if (mIsTrusted || jsapi.Init(mContent->OwnerDoc()->GetScopeObject())) {
   14031           0 :       mHandler->OnLinkClickSync(mContent, mURI,
   14032             :                                 mTargetSpec.get(), mFileName,
   14033             :                                 mPostDataStream, mHeadersDataStream,
   14034           0 :                                 mNoOpenerImplied,
   14035           0 :                                 nullptr, nullptr, mTriggeringPrincipal);
   14036             :     }
   14037           0 :     return NS_OK;
   14038             :   }
   14039             : 
   14040             : private:
   14041             :   RefPtr<nsDocShell> mHandler;
   14042             :   nsCOMPtr<nsIURI> mURI;
   14043             :   nsString mTargetSpec;
   14044             :   nsString mFileName;
   14045             :   nsCOMPtr<nsIInputStream> mPostDataStream;
   14046             :   nsCOMPtr<nsIInputStream> mHeadersDataStream;
   14047             :   nsCOMPtr<nsIContent> mContent;
   14048             :   PopupControlState mPopupState;
   14049             :   bool mNoOpenerImplied;
   14050             :   bool mIsTrusted;
   14051             :   nsCOMPtr<nsIPrincipal> mTriggeringPrincipal;
   14052             : };
   14053             : 
   14054           0 : OnLinkClickEvent::OnLinkClickEvent(nsDocShell* aHandler,
   14055             :                                    nsIContent* aContent,
   14056             :                                    nsIURI* aURI,
   14057             :                                    const char16_t* aTargetSpec,
   14058             :                                    const nsAString& aFileName,
   14059             :                                    nsIInputStream* aPostDataStream,
   14060             :                                    nsIInputStream* aHeadersDataStream,
   14061             :                                    bool aNoOpenerImplied,
   14062             :                                    bool aIsTrusted,
   14063           0 :                                    nsIPrincipal* aTriggeringPrincipal)
   14064             :   : mozilla::Runnable("OnLinkClickEvent")
   14065             :   , mHandler(aHandler)
   14066             :   , mURI(aURI)
   14067             :   , mTargetSpec(aTargetSpec)
   14068             :   , mFileName(aFileName)
   14069             :   , mPostDataStream(aPostDataStream)
   14070             :   , mHeadersDataStream(aHeadersDataStream)
   14071             :   , mContent(aContent)
   14072           0 :   , mPopupState(mHandler->mScriptGlobal->GetPopupControlState())
   14073             :   , mNoOpenerImplied(aNoOpenerImplied)
   14074             :   , mIsTrusted(aIsTrusted)
   14075           0 :   , mTriggeringPrincipal(aTriggeringPrincipal)
   14076             : {
   14077           0 : }
   14078             : 
   14079             : NS_IMETHODIMP
   14080           0 : nsDocShell::OnLinkClick(nsIContent* aContent,
   14081             :                         nsIURI* aURI,
   14082             :                         const char16_t* aTargetSpec,
   14083             :                         const nsAString& aFileName,
   14084             :                         nsIInputStream* aPostDataStream,
   14085             :                         nsIInputStream* aHeadersDataStream,
   14086             :                         bool aIsTrusted,
   14087             :                         nsIPrincipal* aTriggeringPrincipal)
   14088             : {
   14089           0 :   NS_ASSERTION(NS_IsMainThread(), "wrong thread");
   14090             : 
   14091           0 :   if (!IsNavigationAllowed() || !IsOKToLoadURI(aURI)) {
   14092           0 :     return NS_OK;
   14093             :   }
   14094             : 
   14095             :   // On history navigation through Back/Forward buttons, don't execute
   14096             :   // automatic JavaScript redirection such as |anchorElement.click()| or
   14097             :   // |formElement.submit()|.
   14098             :   //
   14099             :   // XXX |formElement.submit()| bypasses this checkpoint because it calls
   14100             :   //     nsDocShell::OnLinkClickSync(...) instead.
   14101           0 :   if (ShouldBlockLoadingForBackButton()) {
   14102           0 :     return NS_OK;
   14103             :   }
   14104             : 
   14105           0 :   if (aContent->IsEditable()) {
   14106           0 :     return NS_OK;
   14107             :   }
   14108             : 
   14109           0 :   nsresult rv = NS_ERROR_FAILURE;
   14110           0 :   nsAutoString target;
   14111             : 
   14112           0 :   nsCOMPtr<nsIWebBrowserChrome3> browserChrome3 = do_GetInterface(mTreeOwner);
   14113           0 :   bool noOpenerImplied = false;
   14114           0 :   if (browserChrome3) {
   14115           0 :     nsCOMPtr<nsIDOMNode> linkNode = do_QueryInterface(aContent);
   14116           0 :     nsAutoString oldTarget(aTargetSpec);
   14117           0 :     rv = browserChrome3->OnBeforeLinkTraversal(oldTarget, aURI,
   14118           0 :                                                linkNode, mIsAppTab, target);
   14119           0 :     if (!oldTarget.Equals(target)) {
   14120           0 :       noOpenerImplied = true;
   14121             :     }
   14122             :   }
   14123             : 
   14124           0 :   if (NS_FAILED(rv)) {
   14125           0 :     target = aTargetSpec;
   14126             :   }
   14127             : 
   14128             :   nsCOMPtr<nsIRunnable> ev =
   14129           0 :     new OnLinkClickEvent(this, aContent, aURI, target.get(), aFileName,
   14130             :                          aPostDataStream, aHeadersDataStream, noOpenerImplied,
   14131           0 :                          aIsTrusted, aTriggeringPrincipal);
   14132             :   return DispatchToTabGroup("nsDocShell::OnLinkClickEvent",
   14133           0 :                             TaskCategory::UI, ev.forget());
   14134             : }
   14135             : 
   14136             : NS_IMETHODIMP
   14137           0 : nsDocShell::OnLinkClickSync(nsIContent* aContent,
   14138             :                             nsIURI* aURI,
   14139             :                             const char16_t* aTargetSpec,
   14140             :                             const nsAString& aFileName,
   14141             :                             nsIInputStream* aPostDataStream,
   14142             :                             nsIInputStream* aHeadersDataStream,
   14143             :                             bool aNoOpenerImplied,
   14144             :                             nsIDocShell** aDocShell,
   14145             :                             nsIRequest** aRequest,
   14146             :                             nsIPrincipal* aTriggeringPrincipal)
   14147             : {
   14148             :   // Initialize the DocShell / Request
   14149           0 :   if (aDocShell) {
   14150           0 :     *aDocShell = nullptr;
   14151             :   }
   14152           0 :   if (aRequest) {
   14153           0 :     *aRequest = nullptr;
   14154             :   }
   14155             : 
   14156           0 :   if (!IsNavigationAllowed() || !IsOKToLoadURI(aURI)) {
   14157           0 :     return NS_OK;
   14158             :   }
   14159             : 
   14160             :   // XXX When the linking node was HTMLFormElement, it is synchronous event.
   14161             :   //     That is, the caller of this method is not |OnLinkClickEvent::Run()|
   14162             :   //     but |HTMLFormElement::SubmitSubmission(...)|.
   14163           0 :   if (aContent->IsHTMLElement(nsGkAtoms::form) &&
   14164           0 :       ShouldBlockLoadingForBackButton()) {
   14165           0 :     return NS_OK;
   14166             :   }
   14167             : 
   14168           0 :   if (aContent->IsEditable()) {
   14169           0 :     return NS_OK;
   14170             :   }
   14171             : 
   14172             :   {
   14173             :     // defer to an external protocol handler if necessary...
   14174             :     nsCOMPtr<nsIExternalProtocolService> extProtService =
   14175           0 :       do_GetService(NS_EXTERNALPROTOCOLSERVICE_CONTRACTID);
   14176           0 :     if (extProtService) {
   14177           0 :       nsAutoCString scheme;
   14178           0 :       aURI->GetScheme(scheme);
   14179           0 :       if (!scheme.IsEmpty()) {
   14180             :         // if the URL scheme does not correspond to an exposed protocol, then we
   14181             :         // need to hand this link click over to the external protocol handler.
   14182             :         bool isExposed;
   14183             :         nsresult rv =
   14184           0 :           extProtService->IsExposedProtocol(scheme.get(), &isExposed);
   14185           0 :         if (NS_SUCCEEDED(rv) && !isExposed) {
   14186           0 :           return extProtService->LoadURI(aURI, this);
   14187             :         }
   14188             :       }
   14189             :     }
   14190             :   }
   14191             : 
   14192           0 :   uint32_t flags = INTERNAL_LOAD_FLAGS_NONE;
   14193           0 :   if (IsElementAnchor(aContent)) {
   14194           0 :     MOZ_ASSERT(aContent->IsHTMLElement());
   14195           0 :     nsAutoString referrer;
   14196           0 :     aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::rel, referrer);
   14197           0 :     nsWhitespaceTokenizerTemplate<nsContentUtils::IsHTMLWhitespace> tok(referrer);
   14198           0 :     while (tok.hasMoreTokens()) {
   14199           0 :       const nsAString& token = tok.nextToken();
   14200           0 :       if (token.LowerCaseEqualsLiteral("noreferrer")) {
   14201           0 :         flags |= INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER |
   14202             :                  INTERNAL_LOAD_FLAGS_NO_OPENER;
   14203             :         // We now have all the flags we could possibly have, so just stop.
   14204           0 :         break;
   14205             :       }
   14206           0 :       if (token.LowerCaseEqualsLiteral("noopener")) {
   14207           0 :         flags |= INTERNAL_LOAD_FLAGS_NO_OPENER;
   14208             :       }
   14209             :     }
   14210           0 :     if (aNoOpenerImplied) {
   14211           0 :       flags |= INTERNAL_LOAD_FLAGS_NO_OPENER;
   14212             :     }
   14213             :   }
   14214             : 
   14215             :   // Get the owner document of the link that was clicked, this will be
   14216             :   // the document that the link is in, or the last document that the
   14217             :   // link was in. From that document, we'll get the URI to use as the
   14218             :   // referer, since the current URI in this docshell may be a
   14219             :   // new document that we're in the process of loading.
   14220           0 :   nsCOMPtr<nsIDocument> refererDoc = aContent->OwnerDoc();
   14221           0 :   NS_ENSURE_TRUE(refererDoc, NS_ERROR_UNEXPECTED);
   14222             : 
   14223             :   // Now check that the refererDoc's inner window is the current inner
   14224             :   // window for mScriptGlobal.  If it's not, then we don't want to
   14225             :   // follow this link.
   14226           0 :   nsPIDOMWindowInner* refererInner = refererDoc->GetInnerWindow();
   14227           0 :   NS_ENSURE_TRUE(refererInner, NS_ERROR_UNEXPECTED);
   14228           0 :   if (!mScriptGlobal ||
   14229           0 :       mScriptGlobal->AsOuter()->GetCurrentInnerWindow() != refererInner) {
   14230             :     // We're no longer the current inner window
   14231           0 :     return NS_OK;
   14232             :   }
   14233             : 
   14234           0 :   nsCOMPtr<nsIURI> referer = refererDoc->GetDocumentURI();
   14235           0 :   uint32_t refererPolicy = refererDoc->GetReferrerPolicy();
   14236             : 
   14237             :   // get referrer attribute from clicked link and parse it
   14238             :   // if per element referrer is enabled, the element referrer overrules
   14239             :   // the document wide referrer
   14240           0 :   if (IsElementAnchor(aContent)) {
   14241           0 :     net::ReferrerPolicy refPolEnum = aContent->AsElement()->GetReferrerPolicyAsEnum();
   14242           0 :     if (refPolEnum != net::RP_Unset) {
   14243           0 :       refererPolicy = refPolEnum;
   14244             :     }
   14245             :   }
   14246             : 
   14247             :   // referer could be null here in some odd cases, but that's ok,
   14248             :   // we'll just load the link w/o sending a referer in those cases.
   14249             : 
   14250           0 :   nsAutoString target(aTargetSpec);
   14251             : 
   14252             :   // If this is an anchor element, grab its type property to use as a hint
   14253           0 :   nsAutoString typeHint;
   14254           0 :   nsCOMPtr<nsIDOMHTMLAnchorElement> anchor(do_QueryInterface(aContent));
   14255           0 :   if (anchor) {
   14256           0 :     anchor->GetType(typeHint);
   14257           0 :     NS_ConvertUTF16toUTF8 utf8Hint(typeHint);
   14258           0 :     nsAutoCString type, dummy;
   14259           0 :     NS_ParseRequestContentType(utf8Hint, type, dummy);
   14260           0 :     CopyUTF8toUTF16(type, typeHint);
   14261             :   }
   14262             : 
   14263             :   // Clone the URI now, in case a content policy or something messes
   14264             :   // with it under InternalLoad; we do _not_ want to change the URI
   14265             :   // our caller passed in.
   14266           0 :   nsCOMPtr<nsIURI> clonedURI;
   14267           0 :   aURI->Clone(getter_AddRefs(clonedURI));
   14268           0 :   if (!clonedURI) {
   14269           0 :     return NS_ERROR_OUT_OF_MEMORY;
   14270             :   }
   14271             : 
   14272             :   // if the triggeringPrincipal is not passed explicitly, then we
   14273             :   // fall back to using doc->NodePrincipal() as the triggeringPrincipal.
   14274             :   nsCOMPtr<nsIPrincipal> triggeringPrincipal =
   14275             :     aTriggeringPrincipal ? aTriggeringPrincipal
   14276           0 :                          : aContent->NodePrincipal();
   14277             : 
   14278           0 :   nsresult rv = InternalLoad(clonedURI,                 // New URI
   14279             :                              nullptr,                   // Original URI
   14280           0 :                              Nothing(),                 // Let the protocol handler assign it
   14281             :                              false,                     // LoadReplace
   14282             :                              referer,                   // Referer URI
   14283             :                              refererPolicy,             // Referer policy
   14284             :                              triggeringPrincipal,
   14285             :                              aContent->NodePrincipal(),
   14286             :                              flags,
   14287             :                              target,                    // Window target
   14288           0 :                              NS_LossyConvertUTF16toASCII(typeHint).get(),
   14289             :                              aFileName,                 // Download as file
   14290             :                              aPostDataStream,           // Post data stream
   14291             :                              aHeadersDataStream,        // Headers stream
   14292             :                              LOAD_LINK,                 // Load type
   14293             :                              nullptr,                   // No SHEntry
   14294             :                              true,                      // first party site
   14295           0 :                              NullString(),              // No srcdoc
   14296             :                              this,                      // We are the source
   14297             :                              nullptr,                   // baseURI not needed
   14298             :                              true,                      // Check for prerendered doc
   14299             :                              aDocShell,                 // DocShell out-param
   14300           0 :                              aRequest);                 // Request out-param
   14301           0 :   if (NS_SUCCEEDED(rv)) {
   14302           0 :     DispatchPings(this, aContent, aURI, referer, refererPolicy);
   14303             :   }
   14304           0 :   return rv;
   14305             : }
   14306             : 
   14307             : NS_IMETHODIMP
   14308           0 : nsDocShell::OnOverLink(nsIContent* aContent,
   14309             :                        nsIURI* aURI,
   14310             :                        const char16_t* aTargetSpec)
   14311             : {
   14312           0 :   if (aContent->IsEditable()) {
   14313           0 :     return NS_OK;
   14314             :   }
   14315             : 
   14316           0 :   nsCOMPtr<nsIWebBrowserChrome2> browserChrome2 = do_GetInterface(mTreeOwner);
   14317           0 :   nsresult rv = NS_ERROR_FAILURE;
   14318             : 
   14319           0 :   nsCOMPtr<nsIWebBrowserChrome> browserChrome;
   14320           0 :   if (!browserChrome2) {
   14321           0 :     browserChrome = do_GetInterface(mTreeOwner);
   14322           0 :     if (!browserChrome) {
   14323           0 :       return rv;
   14324             :     }
   14325             :   }
   14326             : 
   14327           0 :   nsAutoCString spec;
   14328           0 :   rv = aURI->GetSpec(spec);
   14329           0 :   NS_ENSURE_SUCCESS(rv, rv);
   14330             : 
   14331           0 :   NS_ConvertUTF8toUTF16 uStr(spec);
   14332             : 
   14333           0 :   mozilla::net::PredictorPredict(aURI, mCurrentURI,
   14334             :                                  nsINetworkPredictor::PREDICT_LINK,
   14335           0 :                                  aContent->NodePrincipal()->OriginAttributesRef(),
   14336           0 :                                  nullptr);
   14337             : 
   14338           0 :   if (browserChrome2) {
   14339           0 :     nsCOMPtr<nsIDOMElement> element = do_QueryInterface(aContent);
   14340           0 :     rv = browserChrome2->SetStatusWithContext(nsIWebBrowserChrome::STATUS_LINK,
   14341           0 :                                               uStr, element);
   14342             :   } else {
   14343           0 :     rv = browserChrome->SetStatus(nsIWebBrowserChrome::STATUS_LINK, uStr.get());
   14344             :   }
   14345           0 :   return rv;
   14346             : }
   14347             : 
   14348             : NS_IMETHODIMP
   14349           0 : nsDocShell::OnLeaveLink()
   14350             : {
   14351           0 :   nsCOMPtr<nsIWebBrowserChrome> browserChrome(do_GetInterface(mTreeOwner));
   14352           0 :   nsresult rv = NS_ERROR_FAILURE;
   14353             : 
   14354           0 :   if (browserChrome) {
   14355           0 :     rv = browserChrome->SetStatus(nsIWebBrowserChrome::STATUS_LINK,
   14356           0 :                                   EmptyString().get());
   14357             :   }
   14358           0 :   return rv;
   14359             : }
   14360             : 
   14361             : bool
   14362           6 : nsDocShell::ShouldBlockLoadingForBackButton()
   14363             : {
   14364          12 :   if (!(mLoadType & LOAD_CMD_HISTORY) ||
   14365           6 :       EventStateManager::IsHandlingUserInput() ||
   14366           0 :       !Preferences::GetBool("accessibility.blockjsredirection")) {
   14367           6 :     return false;
   14368             :   }
   14369             : 
   14370           0 :   bool canGoForward = false;
   14371           0 :   GetCanGoForward(&canGoForward);
   14372           0 :   return canGoForward;
   14373             : }
   14374             : 
   14375             : bool
   14376           0 : nsDocShell::PluginsAllowedInCurrentDoc()
   14377             : {
   14378             : 
   14379           0 :   if (!mContentViewer) {
   14380           0 :     return false;
   14381             :   }
   14382             : 
   14383           0 :   nsIDocument* doc = mContentViewer->GetDocument();
   14384           0 :   if (!doc) {
   14385           0 :     return false;
   14386             :   }
   14387             : 
   14388           0 :   return doc->GetAllowPlugins();
   14389             : }
   14390             : 
   14391             : //----------------------------------------------------------------------
   14392             : // Web Shell Services API
   14393             : 
   14394             : // This functions is only called when a new charset is detected in loading a
   14395             : // document. Its name should be changed to "CharsetReloadDocument"
   14396             : NS_IMETHODIMP
   14397           0 : nsDocShell::ReloadDocument(const char* aCharset, int32_t aSource)
   14398             : {
   14399             :   // XXX hack. keep the aCharset and aSource wait to pick it up
   14400           0 :   nsCOMPtr<nsIContentViewer> cv;
   14401           0 :   NS_ENSURE_SUCCESS(GetContentViewer(getter_AddRefs(cv)), NS_ERROR_FAILURE);
   14402           0 :   if (cv) {
   14403             :     int32_t hint;
   14404           0 :     cv->GetHintCharacterSetSource(&hint);
   14405           0 :     if (aSource > hint) {
   14406           0 :       nsCString charset(aCharset);
   14407           0 :       cv->SetHintCharacterSet(charset);
   14408           0 :       cv->SetHintCharacterSetSource(aSource);
   14409           0 :       if (eCharsetReloadRequested != mCharsetReloadState) {
   14410           0 :         mCharsetReloadState = eCharsetReloadRequested;
   14411           0 :         return Reload(LOAD_FLAGS_CHARSET_CHANGE);
   14412             :       }
   14413             :     }
   14414             :   }
   14415             :   // return failure if this request is not accepted due to mCharsetReloadState
   14416           0 :   return NS_ERROR_DOCSHELL_REQUEST_REJECTED;
   14417             : }
   14418             : 
   14419             : NS_IMETHODIMP
   14420           0 : nsDocShell::StopDocumentLoad(void)
   14421             : {
   14422           0 :   if (eCharsetReloadRequested != mCharsetReloadState) {
   14423           0 :     Stop(nsIWebNavigation::STOP_ALL);
   14424           0 :     return NS_OK;
   14425             :   }
   14426             :   // return failer if this request is not accepted due to mCharsetReloadState
   14427           0 :   return NS_ERROR_DOCSHELL_REQUEST_REJECTED;
   14428             : }
   14429             : 
   14430             : NS_IMETHODIMP
   14431           0 : nsDocShell::GetPrintPreview(nsIWebBrowserPrint** aPrintPreview)
   14432             : {
   14433           0 :   *aPrintPreview = nullptr;
   14434             : #if NS_PRINT_PREVIEW
   14435           0 :   nsCOMPtr<nsIDocumentViewerPrint> print = do_QueryInterface(mContentViewer);
   14436           0 :   if (!print || !print->IsInitializedForPrintPreview()) {
   14437             :     // XXX: Creating a brand new content viewer to host preview every
   14438             :     // time we enter here seems overwork. We could skip ahead to where
   14439             :     // we QI the mContentViewer if the current URI is either about:blank
   14440             :     // or about:printpreview.
   14441           0 :     Stop(nsIWebNavigation::STOP_ALL);
   14442           0 :     nsCOMPtr<nsIPrincipal> principal = NullPrincipal::CreateWithInheritedAttributes(this);
   14443           0 :     nsCOMPtr<nsIURI> uri;
   14444           0 :     NS_NewURI(getter_AddRefs(uri), NS_LITERAL_CSTRING("about:printpreview"));
   14445           0 :     nsresult rv = CreateAboutBlankContentViewer(principal, uri);
   14446           0 :     NS_ENSURE_SUCCESS(rv, rv);
   14447             :     // Here we manually set current URI since we have just created a
   14448             :     // brand new content viewer (about:blank) to host preview.
   14449           0 :     SetCurrentURI(uri, nullptr, true, 0);
   14450           0 :     print = do_QueryInterface(mContentViewer);
   14451           0 :     NS_ENSURE_STATE(print);
   14452           0 :     print->InitializeForPrintPreview();
   14453             :   }
   14454           0 :   nsCOMPtr<nsIWebBrowserPrint> result = do_QueryInterface(print);
   14455           0 :   result.forget(aPrintPreview);
   14456           0 :   return NS_OK;
   14457             : #else
   14458             :   return NS_ERROR_NOT_IMPLEMENTED;
   14459             : #endif
   14460             : }
   14461             : 
   14462             : #ifdef DEBUG
   14463             : unsigned long nsDocShell::gNumberOfDocShells = 0;
   14464             : #endif
   14465             : 
   14466             : NS_IMETHODIMP
   14467           7 : nsDocShell::GetCanExecuteScripts(bool* aResult)
   14468             : {
   14469           7 :   *aResult = mCanExecuteScripts;
   14470           7 :   return NS_OK;
   14471             : }
   14472             : 
   14473             : /* [infallible] */ NS_IMETHODIMP
   14474           1 : nsDocShell::SetFrameType(uint32_t aFrameType)
   14475             : {
   14476           1 :   mFrameType = aFrameType;
   14477           1 :   return NS_OK;
   14478             : }
   14479             : 
   14480             : /* [infallible] */ NS_IMETHODIMP
   14481           0 : nsDocShell::GetFrameType(uint32_t* aFrameType)
   14482             : {
   14483           0 :   *aFrameType = mFrameType;
   14484           0 :   return NS_OK;
   14485             : }
   14486             : 
   14487             : /* [infallible] */ NS_IMETHODIMP
   14488         347 : nsDocShell::GetIsMozBrowser(bool* aIsMozBrowser)
   14489             : {
   14490         347 :   *aIsMozBrowser = (mFrameType == FRAME_TYPE_BROWSER);
   14491         347 :   return NS_OK;
   14492             : }
   14493             : 
   14494             : uint32_t
   14495           4 : nsDocShell::GetInheritedFrameType()
   14496             : {
   14497           4 :   if (mFrameType != FRAME_TYPE_REGULAR) {
   14498           0 :     return mFrameType;
   14499             :   }
   14500             : 
   14501           8 :   nsCOMPtr<nsIDocShellTreeItem> parentAsItem;
   14502           4 :   GetSameTypeParent(getter_AddRefs(parentAsItem));
   14503             : 
   14504           8 :   nsCOMPtr<nsIDocShell> parent = do_QueryInterface(parentAsItem);
   14505           4 :   if (!parent) {
   14506           3 :     return FRAME_TYPE_REGULAR;
   14507             :   }
   14508             : 
   14509           1 :   return static_cast<nsDocShell*>(parent.get())->GetInheritedFrameType();
   14510             : }
   14511             : 
   14512             : /* [infallible] */ NS_IMETHODIMP
   14513           0 : nsDocShell::GetIsIsolatedMozBrowserElement(bool* aIsIsolatedMozBrowserElement)
   14514             : {
   14515           0 :   bool result = mFrameType == FRAME_TYPE_BROWSER &&
   14516           0 :                 mOriginAttributes.mInIsolatedMozBrowser;
   14517           0 :   *aIsIsolatedMozBrowserElement = result;
   14518           0 :   return NS_OK;
   14519             : }
   14520             : 
   14521             : /* [infallible] */ NS_IMETHODIMP
   14522           3 : nsDocShell::GetIsInIsolatedMozBrowserElement(bool* aIsInIsolatedMozBrowserElement)
   14523             : {
   14524           3 :   MOZ_ASSERT(!mOriginAttributes.mInIsolatedMozBrowser ||
   14525             :              (GetInheritedFrameType() == FRAME_TYPE_BROWSER),
   14526             :              "Isolated mozbrowser should only be true inside browser frames");
   14527           3 :   bool result = (GetInheritedFrameType() == FRAME_TYPE_BROWSER) &&
   14528           3 :                 mOriginAttributes.mInIsolatedMozBrowser;
   14529           3 :   *aIsInIsolatedMozBrowserElement = result;
   14530           3 :   return NS_OK;
   14531             : }
   14532             : 
   14533             : /* [infallible] */ NS_IMETHODIMP
   14534           0 : nsDocShell::GetIsInMozBrowser(bool* aIsInMozBrowser)
   14535             : {
   14536           0 :   *aIsInMozBrowser = (GetInheritedFrameType() == FRAME_TYPE_BROWSER);
   14537           0 :   return NS_OK;
   14538             : }
   14539             : 
   14540             : /* [infallible] */ NS_IMETHODIMP
   14541           0 : nsDocShell::GetIsTopLevelContentDocShell(bool* aIsTopLevelContentDocShell)
   14542             : {
   14543           0 :   *aIsTopLevelContentDocShell = false;
   14544             : 
   14545           0 :   if (mItemType == typeContent) {
   14546           0 :     nsCOMPtr<nsIDocShellTreeItem> root;
   14547           0 :     GetSameTypeRootTreeItem(getter_AddRefs(root));
   14548           0 :     *aIsTopLevelContentDocShell = root.get() == static_cast<nsIDocShellTreeItem*>(this);
   14549             :   }
   14550             : 
   14551           0 :   return NS_OK;
   14552             : }
   14553             : 
   14554             : // Implements nsILoadContext.originAttributes
   14555             : NS_IMETHODIMP
   14556           3 : nsDocShell::GetScriptableOriginAttributes(JS::MutableHandle<JS::Value> aVal)
   14557             : {
   14558           3 :   JSContext* cx = nsContentUtils::GetCurrentJSContext();
   14559           3 :   MOZ_ASSERT(cx);
   14560             : 
   14561           3 :   return GetOriginAttributes(cx, aVal);
   14562             : }
   14563             : 
   14564             : // Implements nsIDocShell.GetOriginAttributes()
   14565             : NS_IMETHODIMP
   14566           3 : nsDocShell::GetOriginAttributes(JSContext* aCx,
   14567             :                                 JS::MutableHandle<JS::Value> aVal)
   14568             : {
   14569           3 :   bool ok = ToJSValue(aCx, mOriginAttributes, aVal);
   14570           3 :   NS_ENSURE_TRUE(ok, NS_ERROR_FAILURE);
   14571           3 :   return NS_OK;
   14572             : }
   14573             : 
   14574             : bool
   14575           3 : nsDocShell::CanSetOriginAttributes()
   14576             : {
   14577           3 :   MOZ_ASSERT(mChildList.IsEmpty());
   14578           3 :   if (!mChildList.IsEmpty()) {
   14579           0 :     return false;
   14580             :   }
   14581             : 
   14582             :   // TODO: Bug 1273058 - mContentViewer should be null when setting origin
   14583             :   // attributes.
   14584           3 :   if (mContentViewer) {
   14585           0 :     nsIDocument* doc = mContentViewer->GetDocument();
   14586           0 :     if (doc) {
   14587           0 :       nsIURI* uri = doc->GetDocumentURI();
   14588           0 :       if (!uri) {
   14589           0 :         return false;
   14590             :       }
   14591           0 :       nsCString uriSpec = uri->GetSpecOrDefault();
   14592           0 :       MOZ_ASSERT(uriSpec.EqualsLiteral("about:blank"));
   14593           0 :       if (!uriSpec.EqualsLiteral("about:blank")) {
   14594           0 :         return false;
   14595             :       }
   14596             :     }
   14597             :   }
   14598             : 
   14599           3 :   return true;
   14600             : }
   14601             : 
   14602             : nsresult
   14603           3 : nsDocShell::SetOriginAttributes(const OriginAttributes& aAttrs)
   14604             : {
   14605           3 :   if (!CanSetOriginAttributes()) {
   14606           0 :     return NS_ERROR_FAILURE;
   14607             :   }
   14608             : 
   14609           3 :   AssertOriginAttributesMatchPrivateBrowsing();
   14610           3 :   mOriginAttributes = aAttrs;
   14611             : 
   14612           3 :   bool isPrivate = mOriginAttributes.mPrivateBrowsingId > 0;
   14613             :   // Chrome docshell can not contain OriginAttributes.mPrivateBrowsingId
   14614           3 :   if (mItemType == typeChrome && isPrivate) {
   14615           0 :     mOriginAttributes.mPrivateBrowsingId = 0;
   14616             :   }
   14617             : 
   14618           3 :   SetPrivateBrowsing(isPrivate);
   14619           3 :   AssertOriginAttributesMatchPrivateBrowsing();
   14620             : 
   14621           3 :   return NS_OK;
   14622             : }
   14623             : 
   14624             : NS_IMETHODIMP
   14625           0 : nsDocShell::SetOriginAttributesBeforeLoading(JS::Handle<JS::Value> aOriginAttributes)
   14626             : {
   14627           0 :   if (!aOriginAttributes.isObject()) {
   14628           0 :     return NS_ERROR_INVALID_ARG;
   14629             :   }
   14630             : 
   14631           0 :   AutoJSAPI jsapi;
   14632           0 :   if (!jsapi.Init(&aOriginAttributes.toObject())) {
   14633           0 :     return NS_ERROR_UNEXPECTED;
   14634             :   }
   14635             : 
   14636           0 :   JSContext* cx = jsapi.cx();
   14637           0 :   if (NS_WARN_IF(!cx)) {
   14638           0 :     return NS_ERROR_FAILURE;
   14639             :   }
   14640             : 
   14641           0 :   OriginAttributes attrs;
   14642           0 :   if (!aOriginAttributes.isObject() || !attrs.Init(cx, aOriginAttributes)) {
   14643           0 :     return NS_ERROR_INVALID_ARG;
   14644             :   }
   14645             : 
   14646           0 :   return SetOriginAttributes(attrs);
   14647             : }
   14648             : 
   14649             : NS_IMETHODIMP
   14650           0 : nsDocShell::SetOriginAttributes(JS::Handle<JS::Value> aOriginAttributes,
   14651             :                                 JSContext* aCx)
   14652             : {
   14653           0 :   OriginAttributes attrs;
   14654           0 :   if (!aOriginAttributes.isObject() || !attrs.Init(aCx, aOriginAttributes)) {
   14655           0 :     return NS_ERROR_INVALID_ARG;
   14656             :   }
   14657             : 
   14658           0 :   return SetOriginAttributes(attrs);
   14659             : }
   14660             : 
   14661             : NS_IMETHODIMP
   14662           0 : nsDocShell::GetAsyncPanZoomEnabled(bool* aOut)
   14663             : {
   14664           0 :   if (nsIPresShell* presShell = GetPresShell()) {
   14665           0 :     *aOut = presShell->AsyncPanZoomEnabled();
   14666           0 :     return NS_OK;
   14667             :   }
   14668             : 
   14669             :   // If we don't have a presShell, fall back to the default platform value of
   14670             :   // whether or not APZ is enabled.
   14671           0 :   *aOut = gfxPlatform::AsyncPanZoomEnabled();
   14672           0 :   return NS_OK;
   14673             : }
   14674             : 
   14675             : bool
   14676           6 : nsDocShell::HasUnloadedParent()
   14677             : {
   14678          12 :   RefPtr<nsDocShell> parent = GetParentDocshell();
   14679          10 :   while (parent) {
   14680           2 :     bool inUnload = false;
   14681           2 :     parent->GetIsInUnload(&inUnload);
   14682           2 :     if (inUnload) {
   14683           0 :       return true;
   14684             :     }
   14685           2 :     parent = parent->GetParentDocshell();
   14686             :   }
   14687           6 :   return false;
   14688             : }
   14689             : 
   14690             : void
   14691           3 : nsDocShell::UpdateGlobalHistoryTitle(nsIURI* aURI)
   14692             : {
   14693           3 :   if (mUseGlobalHistory && !UsePrivateBrowsing()) {
   14694           2 :     nsCOMPtr<IHistory> history = services::GetHistoryService();
   14695           1 :     if (mPrerenderGlobalHistory) {
   14696           0 :       mPrerenderGlobalHistory->SetURITitle(aURI, mTitle);
   14697           1 :     } else if (history) {
   14698           1 :       history->SetURITitle(aURI, mTitle);
   14699           0 :     } else if (mGlobalHistory) {
   14700           0 :       mGlobalHistory->SetPageTitle(aURI, nsString(mTitle));
   14701             :     }
   14702             :   }
   14703           3 : }
   14704             : 
   14705             : bool
   14706           7 : nsDocShell::IsInvisible()
   14707             : {
   14708           7 :   return mInvisible;
   14709             : }
   14710             : 
   14711             : void
   14712           0 : nsDocShell::SetInvisible(bool aInvisible)
   14713             : {
   14714           0 :   mInvisible = aInvisible;
   14715           0 : }
   14716             : 
   14717             : void
   14718           2 : nsDocShell::SetOpener(nsITabParent* aOpener)
   14719             : {
   14720           2 :   mOpener = do_GetWeakReference(aOpener);
   14721           2 : }
   14722             : 
   14723             : nsITabParent*
   14724           1 : nsDocShell::GetOpener()
   14725             : {
   14726           2 :   nsCOMPtr<nsITabParent> opener(do_QueryReferent(mOpener));
   14727           2 :   return opener;
   14728             : }
   14729             : 
   14730             : // The caller owns |aAsyncCause| here.
   14731             : void
   14732           0 : nsDocShell::NotifyJSRunToCompletionStart(const char* aReason,
   14733             :                                          const char16_t* aFunctionName,
   14734             :                                          const char16_t* aFilename,
   14735             :                                          const uint32_t aLineNumber,
   14736             :                                          JS::Handle<JS::Value> aAsyncStack,
   14737             :                                          const char* aAsyncCause)
   14738             : {
   14739             :   // If first start, mark interval start.
   14740           0 :   if (mJSRunToCompletionDepth == 0) {
   14741           0 :     RefPtr<TimelineConsumers> timelines = TimelineConsumers::Get();
   14742           0 :     if (timelines && timelines->HasConsumer(this)) {
   14743           0 :       timelines->AddMarkerForDocShell(this, Move(
   14744           0 :         mozilla::MakeUnique<JavascriptTimelineMarker>(
   14745             :           aReason, aFunctionName, aFilename, aLineNumber, MarkerTracingType::START,
   14746           0 :           aAsyncStack, aAsyncCause)));
   14747             :     }
   14748             :   }
   14749             : 
   14750           0 :   mJSRunToCompletionDepth++;
   14751           0 : }
   14752             : 
   14753             : void
   14754           0 : nsDocShell::NotifyJSRunToCompletionStop()
   14755             : {
   14756           0 :   mJSRunToCompletionDepth--;
   14757             : 
   14758             :   // If last stop, mark interval end.
   14759           0 :   if (mJSRunToCompletionDepth == 0) {
   14760           0 :     RefPtr<TimelineConsumers> timelines = TimelineConsumers::Get();
   14761           0 :     if (timelines && timelines->HasConsumer(this)) {
   14762           0 :       timelines->AddMarkerForDocShell(this, "Javascript", MarkerTracingType::END);
   14763             :     }
   14764             :   }
   14765           0 : }
   14766             : 
   14767             : void
   14768           3 : nsDocShell::MaybeNotifyKeywordSearchLoading(const nsString& aProvider,
   14769             :                                             const nsString& aKeyword)
   14770             : {
   14771           3 :   if (aProvider.IsEmpty()) {
   14772           6 :     return;
   14773             :   }
   14774             : 
   14775           0 :   if (XRE_IsContentProcess()) {
   14776           0 :     dom::ContentChild* contentChild = dom::ContentChild::GetSingleton();
   14777           0 :     if (contentChild) {
   14778           0 :       contentChild->SendNotifyKeywordSearchLoading(aProvider, aKeyword);
   14779             :     }
   14780           0 :     return;
   14781             :   }
   14782             : 
   14783             : #ifdef MOZ_TOOLKIT_SEARCH
   14784             :   nsCOMPtr<nsIBrowserSearchService> searchSvc =
   14785           0 :     do_GetService("@mozilla.org/browser/search-service;1");
   14786           0 :   if (searchSvc) {
   14787           0 :     nsCOMPtr<nsISearchEngine> searchEngine;
   14788           0 :     searchSvc->GetEngineByName(aProvider, getter_AddRefs(searchEngine));
   14789           0 :     if (searchEngine) {
   14790           0 :       nsCOMPtr<nsIObserverService> obsSvc = services::GetObserverService();
   14791           0 :       if (obsSvc) {
   14792             :         // Note that "keyword-search" refers to a search via the url
   14793             :         // bar, not a bookmarks keyword search.
   14794           0 :         obsSvc->NotifyObservers(searchEngine, "keyword-search", aKeyword.get());
   14795             :       }
   14796             :     }
   14797             :   }
   14798             : #endif
   14799             : }
   14800             : 
   14801             : NS_IMETHODIMP
   14802           4 : nsDocShell::ShouldPrepareForIntercept(nsIURI* aURI, bool aIsNonSubresourceRequest,
   14803             :                                       bool* aShouldIntercept)
   14804             : {
   14805           4 :   *aShouldIntercept = false;
   14806             :   // No in private browsing
   14807           4 :   if (UsePrivateBrowsing()) {
   14808           0 :     return NS_OK;
   14809             :   }
   14810             : 
   14811           4 :   if (mSandboxFlags) {
   14812             :     // If we're sandboxed, don't intercept.
   14813           0 :     return NS_OK;
   14814             :   }
   14815             : 
   14816           8 :   RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
   14817           4 :   if (!swm) {
   14818           0 :     return NS_OK;
   14819             :   }
   14820             : 
   14821             :   nsresult result;
   14822             :   nsCOMPtr<mozIThirdPartyUtil> thirdPartyUtil =
   14823           8 :     do_GetService(THIRDPARTYUTIL_CONTRACTID, &result);
   14824           4 :   NS_ENSURE_SUCCESS(result, result);
   14825             : 
   14826           8 :   if (mCurrentURI &&
   14827           8 :       nsContentUtils::CookiesBehavior() == nsICookieService::BEHAVIOR_REJECT_FOREIGN) {
   14828           0 :     nsAutoCString uriSpec;
   14829           0 :     if (!(mCurrentURI->GetSpecOrDefault().EqualsLiteral("about:blank"))) {
   14830             :       // Reject the interception of third-party iframes if the cookie behaviour
   14831             :       // is set to reject all third-party cookies (1). In case that this pref
   14832             :       // is not set or can't be read, we default to allow all cookies (0) as
   14833             :       // this is the default value in all.js.
   14834           0 :       bool isThirdPartyURI = true;
   14835           0 :       result = thirdPartyUtil->IsThirdPartyURI(mCurrentURI, aURI,
   14836           0 :                                                &isThirdPartyURI);
   14837           0 :       if (NS_FAILED(result)) {
   14838           0 :           return result;
   14839             :       }
   14840             : 
   14841           0 :       if (isThirdPartyURI) {
   14842           0 :         return NS_OK;
   14843             :       }
   14844             :     }
   14845             :   }
   14846             : 
   14847           4 :   if (aIsNonSubresourceRequest) {
   14848             :     nsCOMPtr<nsIPrincipal> principal =
   14849           2 :       BasePrincipal::CreateCodebasePrincipal(aURI, mOriginAttributes);
   14850           1 :     *aShouldIntercept = swm->IsAvailable(principal, aURI);
   14851           1 :     return NS_OK;
   14852             :   }
   14853             : 
   14854           6 :   nsCOMPtr<nsIDocument> doc = GetDocument();
   14855           3 :   if (!doc) {
   14856           0 :     return NS_ERROR_NOT_AVAILABLE;
   14857             :   }
   14858             : 
   14859           6 :   ErrorResult rv;
   14860           3 :   *aShouldIntercept = swm->IsControlled(doc, rv);
   14861           3 :   if (NS_WARN_IF(rv.Failed())) {
   14862           0 :     return rv.StealNSResult();
   14863             :   }
   14864             : 
   14865           3 :   return NS_OK;
   14866             : }
   14867             : 
   14868             : NS_IMETHODIMP
   14869           0 : nsDocShell::ChannelIntercepted(nsIInterceptedChannel* aChannel)
   14870             : {
   14871           0 :   RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
   14872           0 :   if (!swm) {
   14873           0 :     aChannel->Cancel(NS_ERROR_INTERCEPTION_FAILED);
   14874           0 :     return NS_OK;
   14875             :   }
   14876             : 
   14877           0 :   nsCOMPtr<nsIChannel> channel;
   14878           0 :   nsresult rv = aChannel->GetChannel(getter_AddRefs(channel));
   14879           0 :   NS_ENSURE_SUCCESS(rv, rv);
   14880             : 
   14881           0 :   nsCOMPtr<nsIDocument> doc;
   14882             : 
   14883           0 :   bool isSubresourceLoad = !nsContentUtils::IsNonSubresourceRequest(channel);
   14884           0 :   if (isSubresourceLoad) {
   14885           0 :     doc = GetDocument();
   14886           0 :     if (!doc) {
   14887           0 :       return NS_ERROR_NOT_AVAILABLE;
   14888             :     }
   14889             :   } else {
   14890             :     // For top-level navigations, save a document ID which will be passed to
   14891             :     // the FetchEvent as the clientId later on.
   14892           0 :     rv = nsIDocument::GenerateDocumentId(mInterceptedDocumentId);
   14893           0 :     NS_ENSURE_SUCCESS(rv, rv);
   14894             :   }
   14895             : 
   14896           0 :   bool isReload = mLoadType & LOAD_CMD_RELOAD;
   14897             : 
   14898           0 :   ErrorResult error;
   14899           0 :   swm->DispatchFetchEvent(mOriginAttributes, doc, mInterceptedDocumentId,
   14900           0 :                           aChannel, isReload, isSubresourceLoad, error);
   14901           0 :   if (NS_WARN_IF(error.Failed())) {
   14902           0 :     return error.StealNSResult();
   14903             :   }
   14904             : 
   14905           0 :   return NS_OK;
   14906             : }
   14907             : 
   14908             : bool
   14909           0 : nsDocShell::InFrameSwap()
   14910             : {
   14911           0 :   RefPtr<nsDocShell> shell = this;
   14912           0 :   do {
   14913           0 :     if (shell->mInFrameSwap) {
   14914           0 :       return true;
   14915             :     }
   14916           0 :     shell = shell->GetParentDocshell();
   14917             :   } while (shell);
   14918           0 :   return false;
   14919             : }
   14920             : 
   14921             : NS_IMETHODIMP
   14922           0 : nsDocShell::IssueWarning(uint32_t aWarning, bool aAsError)
   14923             : {
   14924           0 :   if (mContentViewer) {
   14925           0 :     nsCOMPtr<nsIDocument> doc = mContentViewer->GetDocument();
   14926           0 :     if (doc) {
   14927           0 :       doc->WarnOnceAbout(nsIDocument::DeprecatedOperations(aWarning), aAsError);
   14928             :     }
   14929             :   }
   14930           0 :   return NS_OK;
   14931             : }
   14932             : 
   14933             : NS_IMETHODIMP
   14934           0 : nsDocShell::GetEditingSession(nsIEditingSession** aEditSession)
   14935             : {
   14936           0 :   if (!NS_SUCCEEDED(EnsureEditorData())) {
   14937           0 :     return NS_ERROR_FAILURE;
   14938             :   }
   14939             : 
   14940           0 :   mEditorData->GetEditingSession(aEditSession);
   14941           0 :   return *aEditSession ? NS_OK : NS_ERROR_FAILURE;
   14942             : }
   14943             : 
   14944             : NS_IMETHODIMP
   14945           0 : nsDocShell::GetScriptableTabChild(nsITabChild** aTabChild)
   14946             : {
   14947           0 :   *aTabChild = GetTabChild().take();
   14948           0 :   return *aTabChild ? NS_OK : NS_ERROR_FAILURE;
   14949             : }
   14950             : 
   14951             : already_AddRefed<nsITabChild>
   14952          29 : nsDocShell::GetTabChild()
   14953             : {
   14954          58 :   nsCOMPtr<nsIDocShellTreeOwner> owner(mTreeOwner);
   14955          58 :   nsCOMPtr<nsITabChild> tc = do_GetInterface(owner);
   14956          58 :   return tc.forget();
   14957             : }
   14958             : 
   14959             : nsICommandManager*
   14960           0 : nsDocShell::GetCommandManager()
   14961             : {
   14962           0 :   NS_ENSURE_SUCCESS(EnsureCommandHandler(), nullptr);
   14963           0 :   return mCommandManager;
   14964             : }
   14965             : 
   14966             : NS_IMETHODIMP
   14967           0 : nsDocShell::GetIsOnlyToplevelInTabGroup(bool* aResult)
   14968             : {
   14969           0 :   MOZ_ASSERT(aResult);
   14970             : 
   14971           0 :   nsPIDOMWindowOuter* outer = GetWindow();
   14972           0 :   MOZ_ASSERT(outer);
   14973             : 
   14974             :   // If we are not toplevel then we are not the only toplevel window in the tab
   14975             :   // group.
   14976           0 :   if (outer->GetScriptableParentOrNull()) {
   14977           0 :     *aResult = false;
   14978           0 :     return NS_OK;
   14979             :   }
   14980             : 
   14981             :   // If we have any other toplevel windows in our tab group, then we are not the
   14982             :   // only toplevel window in the tab group.
   14983             :   nsTArray<nsPIDOMWindowOuter*> toplevelWindows =
   14984           0 :     outer->TabGroup()->GetTopLevelWindows();
   14985           0 :   if (toplevelWindows.Length() > 1) {
   14986           0 :     *aResult = false;
   14987           0 :     return NS_OK;
   14988             :   }
   14989           0 :   MOZ_ASSERT(toplevelWindows.Length() == 1);
   14990           0 :   MOZ_ASSERT(toplevelWindows[0] == outer);
   14991             : 
   14992           0 :   *aResult = true;
   14993           0 :   return NS_OK;
   14994             : }
   14995             : 
   14996             : NS_IMETHODIMP
   14997           0 : nsDocShell::GetAwaitingLargeAlloc(bool* aResult)
   14998             : {
   14999           0 :   MOZ_ASSERT(aResult);
   15000           0 :   nsCOMPtr<nsITabChild> tabChild = GetTabChild();
   15001           0 :   if (!tabChild) {
   15002           0 :     *aResult = false;
   15003           0 :     return NS_OK;
   15004             :   }
   15005           0 :   *aResult = static_cast<TabChild*>(tabChild.get())->IsAwaitingLargeAlloc();
   15006           0 :   return NS_OK;
   15007             : }
   15008             : 
   15009             : NS_IMETHODIMP_(void)
   15010          11 : nsDocShell::GetOriginAttributes(mozilla::OriginAttributes& aAttrs)
   15011             : {
   15012          11 :   aAttrs = mOriginAttributes;
   15013          11 : }

Generated by: LCOV version 1.13