Bug 1492648 - Move from nsDocShellLoadInfo to nsDocShellLoadState r=bzbarsky,nika
☠☠ backed out by d0a571485527 ☠ ☠
authorKyle Machulis <kyle@nonpolynomial.com>
Thu, 18 Oct 2018 22:14:54 +0000
changeset 490383 8dd09fad1f352d3814244908f0ea04f29fa2a307
parent 490382 38c1fc84fcaf42dbbdf53f286a0878cbadb0dbaf
child 490384 889b103b4e312bf7f0b407c0485bdd7c3e14e516
push id247
push userfmarier@mozilla.com
push dateSat, 27 Oct 2018 01:06:44 +0000
reviewersbzbarsky, nika
bugs1492648
milestone64.0a1
Bug 1492648 - Move from nsDocShellLoadInfo to nsDocShellLoadState r=bzbarsky,nika Creates the nsDocShellLoadState object, which is basically nsDocShellLoadInfo plus a few extra fields to make it usable as a single argument to nsDocShell::LoadURI (and eventually nsDocShell::InternalLoad). Subframe history handling is a huge logic block in nsDocShell::LoadURI, which is only used on history loads. This patch also extracts the logic out into its own function to make the body of LoadURI clearer. Differential Revision: https://phabricator.services.mozilla.com/D6944
caps/NullPrincipal.cpp
caps/NullPrincipal.h
docshell/base/moz.build
docshell/base/nsDocShell.cpp
docshell/base/nsDocShell.h
docshell/base/nsDocShellLoadInfo.cpp
docshell/base/nsDocShellLoadInfo.h
docshell/base/nsDocShellLoadState.cpp
docshell/base/nsDocShellLoadState.h
docshell/base/nsDocShellLoadTypes.h
docshell/base/nsIDocShell.idl
docshell/shistory/nsSHEntry.cpp
docshell/shistory/nsSHistory.cpp
dom/base/Location.cpp
dom/base/Location.h
dom/base/nsFrameLoader.cpp
dom/base/nsGlobalWindowOuter.cpp
dom/base/nsGlobalWindowOuter.h
dom/base/nsPIDOMWindow.h
dom/clients/manager/ClientNavigateOpChild.cpp
dom/ipc/ContentChild.cpp
dom/ipc/ContentChild.h
dom/ipc/TabChild.cpp
toolkit/components/windowcreator/nsIWindowProvider.idl
toolkit/components/windowwatcher/nsPIWindowWatcher.idl
toolkit/components/windowwatcher/nsWindowWatcher.cpp
toolkit/components/windowwatcher/nsWindowWatcher.h
xpfe/appshell/nsContentTreeOwner.cpp
--- a/caps/NullPrincipal.cpp
+++ b/caps/NullPrincipal.cpp
@@ -33,29 +33,34 @@ NS_IMPL_QUERY_INTERFACE_CI(NullPrincipal
                            nsISerializable)
 NS_IMPL_CI_INTERFACE_GETTER(NullPrincipal,
                             nsIPrincipal,
                             nsISerializable)
 
 /* static */ already_AddRefed<NullPrincipal>
 NullPrincipal::CreateWithInheritedAttributes(nsIPrincipal* aInheritFrom)
 {
-  RefPtr<NullPrincipal> nullPrin = new NullPrincipal();
-  nsresult rv = nullPrin->Init(Cast(aInheritFrom)->OriginAttributesRef());
-  MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv));
-  return nullPrin.forget();
+  MOZ_ASSERT(aInheritFrom);
+  return CreateWithInheritedAttributes(Cast(aInheritFrom)->OriginAttributesRef(), false);
 }
 
 /* static */ already_AddRefed<NullPrincipal>
 NullPrincipal::CreateWithInheritedAttributes(nsIDocShell* aDocShell, bool aIsFirstParty)
 {
+  MOZ_ASSERT(aDocShell);
+
   OriginAttributes attrs = nsDocShell::Cast(aDocShell)->GetOriginAttributes();
+  return CreateWithInheritedAttributes(attrs, aIsFirstParty);
+}
 
+/* static */ already_AddRefed<NullPrincipal>
+NullPrincipal::CreateWithInheritedAttributes(const OriginAttributes& aOriginAttributes, bool aIsFirstParty)
+{
   RefPtr<NullPrincipal> nullPrin = new NullPrincipal();
-  nsresult rv = nullPrin->Init(attrs, aIsFirstParty);
+  nsresult rv = nullPrin->Init(aOriginAttributes, aIsFirstParty);
   MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv));
   return nullPrin.forget();
 }
 
 /* static */ already_AddRefed<NullPrincipal>
 NullPrincipal::Create(const OriginAttributes& aOriginAttributes, nsIURI* aURI)
 {
   RefPtr<NullPrincipal> nullPrin = new NullPrincipal();
--- a/caps/NullPrincipal.h
+++ b/caps/NullPrincipal.h
@@ -51,24 +51,29 @@ public:
   NS_IMETHOD GetHashValue(uint32_t* aHashValue) override;
   NS_IMETHOD SetCsp(nsIContentSecurityPolicy* aCsp) override;
   NS_IMETHOD GetURI(nsIURI** aURI) override;
   NS_IMETHOD GetDomain(nsIURI** aDomain) override;
   NS_IMETHOD SetDomain(nsIURI* aDomain) override;
   NS_IMETHOD GetBaseDomain(nsACString& aBaseDomain) override;
   NS_IMETHOD GetAddonId(nsAString& aAddonId) override;
 
-  static already_AddRefed<NullPrincipal> CreateWithInheritedAttributes(nsIPrincipal* aInheritFrom);
+  static already_AddRefed<NullPrincipal>
+  CreateWithInheritedAttributes(nsIPrincipal* aInheritFrom);
 
   // Create NullPrincipal with origin attributes from docshell.
   // If aIsFirstParty is true, and the pref 'privacy.firstparty.isolate' is also
   // enabled, the mFirstPartyDomain value of the origin attributes will be set
   // to an unique value.
   static already_AddRefed<NullPrincipal>
-  CreateWithInheritedAttributes(nsIDocShell* aDocShell, bool aIsFirstParty = false);
+  CreateWithInheritedAttributes(nsIDocShell* aDocShell,
+                                bool aIsFirstParty = false);
+  static already_AddRefed<NullPrincipal>
+  CreateWithInheritedAttributes(const OriginAttributes& aOriginAttributes,
+                                bool aIsFirstParty = false);
 
   static already_AddRefed<NullPrincipal>
   Create(const OriginAttributes& aOriginAttributes,
          nsIURI* aURI = nullptr);
 
   static already_AddRefed<NullPrincipal>
   CreateWithoutOriginAttributes();
 
@@ -80,17 +85,18 @@ public:
   nsresult GetSiteIdentifier(SiteIdentifier& aSite) override {
     aSite.Init(this);
     return NS_OK;
   }
 
  protected:
   virtual ~NullPrincipal() = default;
 
-  bool SubsumesInternal(nsIPrincipal* aOther, DocumentDomainConsideration aConsideration) override
+  bool SubsumesInternal(nsIPrincipal* aOther,
+                        DocumentDomainConsideration aConsideration) override
   {
     return aOther == this;
   }
 
   bool MayLoadInternal(nsIURI* aURI) override;
 
   nsCOMPtr<nsIURI> mURI;
 
--- a/docshell/base/moz.build
+++ b/docshell/base/moz.build
@@ -56,17 +56,17 @@ XPIDL_SOURCES += [
     'nsIWebPageDescriptor.idl',
 ]
 
 XPIDL_MODULE = 'docshell'
 
 EXPORTS += [
     'nsCTooltipTextProvider.h',
     'nsDocShell.h',
-    'nsDocShellLoadInfo.h',
+    'nsDocShellLoadState.h',
     'nsDocShellLoadTypes.h',
     'nsDocShellTreeOwner.h',
     'nsILinkHandler.h',
     'nsIScrollObserver.h',
     'SerializedLoadContext.h',
 ]
 
 EXPORTS.mozilla += [
@@ -83,17 +83,17 @@ UNIFIED_SOURCES += [
     'BrowsingContext.cpp',
     'ChromeBrowsingContext.cpp',
     'LoadContext.cpp',
     'nsAboutRedirector.cpp',
     'nsDefaultURIFixup.cpp',
     'nsDocShell.cpp',
     'nsDocShellEditorData.cpp',
     'nsDocShellEnumerator.cpp',
-    'nsDocShellLoadInfo.cpp',
+    'nsDocShellLoadState.cpp',
     'nsDocShellTreeOwner.cpp',
     'nsDSURIContentListener.cpp',
     'nsPingListener.cpp',
     'nsRefreshTimer.cpp',
     'nsWebNavigationInfo.cpp',
     'SerializedLoadContext.cpp',
 ]
 
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -164,17 +164,17 @@
 #include "nsContentDLF.h"
 #include "nsContentPolicyUtils.h" // NS_CheckContentLoadPolicy(...)
 #include "nsContentSecurityManager.h"
 #include "nsContentUtils.h"
 #include "nsCURILoader.h"
 #include "nsDocShellCID.h"
 #include "nsDocShellEditorData.h"
 #include "nsDocShellEnumerator.h"
-#include "nsDocShellLoadInfo.h"
+#include "nsDocShellLoadState.h"
 #include "nsDocShellLoadTypes.h"
 #include "nsDOMCID.h"
 #include "nsDOMNavigationTiming.h"
 #include "nsDSURIContentListener.h"
 #include "nsError.h"
 #include "nsEscape.h"
 #include "nsFocusManager.h"
 #include "nsGlobalWindow.h"
@@ -638,385 +638,247 @@ nsDocShell::GetInterface(const nsIID& aI
     return nsDocLoader::GetInterface(aIID, aSink);
   }
 
   NS_IF_ADDREF(((nsISupports*)*aSink));
   return *aSink ? NS_OK : NS_NOINTERFACE;
 }
 
 NS_IMETHODIMP
-nsDocShell::LoadURI(nsIURI* aURI,
-                    nsDocShellLoadInfo* aLoadInfo,
-                    uint32_t aLoadFlags,
-                    bool aFirstParty)
-{
-  MOZ_ASSERT(aLoadInfo || (aLoadFlags & EXTRA_LOAD_FLAGS) == 0,
-             "Unexpected flags");
-  MOZ_ASSERT((aLoadFlags & 0xf) == 0, "Should not have these flags set");
+nsDocShell::LoadURI(nsDocShellLoadState* aLoadState)
+{
+  MOZ_ASSERT(aLoadState, "Must have a valid load state!");
+  MOZ_ASSERT((aLoadState->LoadFlags() & INTERNAL_LOAD_FLAGS_LOADURI_SETUP_FLAGS) == 0,
+             "Should not have these flags set");
+  MOZ_ASSERT(aLoadState->URI(), "Should have a valid URI to load");
 
   // Note: we allow loads to get through here even if mFiredUnloadEvent is
   // true; that case will get handled in LoadInternal or LoadHistoryEntry,
   // so we pass false as the second parameter to IsNavigationAllowed.
   // However, we don't allow the page to change location *in the middle of*
   // firing beforeunload, so we do need to check if *beforeunload* is currently
   // firing, so we call IsNavigationAllowed rather than just IsPrintingOrPP.
   if (!IsNavigationAllowed(true, false)) {
     return NS_OK; // JS may not handle returning of an error code
   }
 
-  nsCOMPtr<nsIURI> referrer;
-  nsCOMPtr<nsIURI> originalURI;
-  Maybe<nsCOMPtr<nsIURI>> resultPrincipalURI;
-  bool keepResultPrincipalURIIfSet = false;
-  bool loadReplace = false;
-  nsCOMPtr<nsIInputStream> postStream;
-  nsCOMPtr<nsIInputStream> headersStream;
-  nsCOMPtr<nsIPrincipal> triggeringPrincipal;
-  bool inheritPrincipal = false;
-  bool principalIsExplicit = false;
-  bool sendReferrer = true;
-  uint32_t referrerPolicy = RP_Unset;
-  bool isSrcdoc = false;
-  nsCOMPtr<nsISHEntry> shEntry;
-  nsString target;
-  nsAutoString srcdoc;
-  bool forceAllowDataURI = false;
-  bool originalFrameSrc = false;
-  nsCOMPtr<nsIDocShell> sourceDocShell;
-  nsCOMPtr<nsIURI> baseURI;
-
-  uint32_t loadType = MAKE_LOAD_TYPE(LOAD_NORMAL, aLoadFlags);
-
-  NS_ENSURE_ARG(aURI);
-
   if (!StartupTimeline::HasRecord(StartupTimeline::FIRST_LOAD_URI) &&
-      mItemType == typeContent && !NS_IsAboutBlank(aURI)) {
+      mItemType == typeContent && !NS_IsAboutBlank(aLoadState->URI())) {
     StartupTimeline::RecordOnce(StartupTimeline::FIRST_LOAD_URI);
   }
 
-  // Extract the info from the DocShellLoadInfo struct...
-  if (aLoadInfo) {
-    referrer = aLoadInfo->Referrer();
-    originalURI = aLoadInfo->OriginalURI();
-    aLoadInfo->GetMaybeResultPrincipalURI(resultPrincipalURI);
-    keepResultPrincipalURIIfSet = aLoadInfo->KeepResultPrincipalURIIfSet();
-    loadReplace = aLoadInfo->LoadReplace();
-    // Get the appropriate loadType from nsIDocShellLoadInfo type
-    loadType = aLoadInfo->LoadType();
-
-    triggeringPrincipal = aLoadInfo->TriggeringPrincipal();
-    inheritPrincipal = aLoadInfo->InheritPrincipal();
-    principalIsExplicit = aLoadInfo->PrincipalIsExplicit();
-    shEntry = aLoadInfo->SHEntry();
-    aLoadInfo->GetTarget(target);
-    postStream = aLoadInfo->PostDataStream();
-    headersStream = aLoadInfo->HeadersStream();
-    sendReferrer = aLoadInfo->SendReferrer();
-    referrerPolicy = aLoadInfo->ReferrerPolicy();
-    isSrcdoc = aLoadInfo->IsSrcdocLoad();
-    aLoadInfo->GetSrcdocData(srcdoc);
-    sourceDocShell = aLoadInfo->SourceDocShell();
-    baseURI = aLoadInfo->BaseURI();
-    forceAllowDataURI = aLoadInfo->ForceAllowDataURI();
-    originalFrameSrc = aLoadInfo->OriginalFrameSrc();
-  }
-
   MOZ_LOG(gDocShellLeakLog, LogLevel::Debug,
           ("nsDocShell[%p]: loading %s with flags 0x%08x",
-           this, aURI->GetSpecOrDefault().get(), aLoadFlags));
-
-  if (!shEntry &&
-      !LOAD_TYPE_HAS_FLAGS(loadType, LOAD_FLAGS_REPLACE_HISTORY)) {
-    // First verify if this is a subframe.
+           this, aLoadState->URI()->GetSpecOrDefault().get(),
+           aLoadState->LoadFlags()));
+
+  if (!aLoadState->SHEntry() &&
+      !LOAD_TYPE_HAS_FLAGS(aLoadState->LoadType(),
+                           LOAD_FLAGS_REPLACE_HISTORY)) {
+    // This is possibly a subframe, so handle it accordingly.
+    //
+    // If history exists, it will be loaded into the aLoadState object, and the
+    // LoadType will be changed.
+    MaybeHandleSubframeHistory(aLoadState);
+  }
+
+  if (aLoadState->SHEntry()) {
+#ifdef DEBUG
+    MOZ_LOG(gDocShellLog, LogLevel::Debug,
+           ("nsDocShell[%p]: loading from session history", this));
+#endif
+
+    return LoadHistoryEntry(aLoadState->SHEntry(), aLoadState->LoadType());
+  }
+
+  // On history navigation via Back/Forward buttons, don't execute
+  // automatic JavaScript redirection such as |location.href = ...| or
+  // |window.open()|
+  //
+  // LOAD_NORMAL:        window.open(...) etc.
+  // LOAD_STOP_CONTENT:  location.href = ..., location.assign(...)
+  if ((aLoadState->LoadType() == LOAD_NORMAL ||
+       aLoadState->LoadType() == LOAD_STOP_CONTENT) &&
+      ShouldBlockLoadingForBackButton()) {
+    return NS_OK;
+  }
+
+  // Set up the inheriting principal in LoadState.
+  nsresult rv = aLoadState->SetupInheritingPrincipal(mItemType, mOriginAttributes);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  rv = aLoadState->SetupTriggeringPrincipal(mOriginAttributes);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  aLoadState->CalculateDocShellInternalLoadFlags();
+
+  mozilla::Maybe<nsCOMPtr<nsIURI>> resultPrincipalURI;
+  aLoadState->GetMaybeResultPrincipalURI(resultPrincipalURI);
+
+  MOZ_ASSERT(aLoadState->TypeHint().IsVoid(),
+             "Typehint should be null when calling InternalLoad from LoadURI");
+  MOZ_ASSERT(aLoadState->FileName().IsVoid(),
+             "FileName should be null when calling InternalLoad from LoadURI");
+  MOZ_ASSERT(aLoadState->SHEntry() == nullptr,
+             "SHEntry should be null when calling InternalLoad from LoadURI");
+
+  return InternalLoad(aLoadState->URI(),
+                      aLoadState->OriginalURI(),
+                      resultPrincipalURI,
+                      aLoadState->KeepResultPrincipalURIIfSet(),
+                      aLoadState->LoadReplace(),
+                      aLoadState->Referrer(),
+                      aLoadState->ReferrerPolicy(),
+                      aLoadState->TriggeringPrincipal(),
+                      aLoadState->PrincipalToInherit(),
+                      aLoadState->DocShellInternalLoadFlags(),
+                      aLoadState->Target(),
+                      aLoadState->TypeHint(),
+                      aLoadState->FileName(),
+                      aLoadState->PostDataStream(),
+                      aLoadState->HeadersStream(),
+                      aLoadState->LoadType(),
+                      aLoadState->SHEntry(),
+                      aLoadState->FirstParty(),
+                      aLoadState->SrcdocData(),
+                      aLoadState->SourceDocShell(),
+                      aLoadState->BaseURI(),
+                      nullptr, // no nsIDocShell
+                      nullptr); // no nsIRequest
+}
+
+void
+nsDocShell::MaybeHandleSubframeHistory(nsDocShellLoadState* aLoadState)
+{
+  // First, verify if this is a subframe.
     nsCOMPtr<nsIDocShellTreeItem> parentAsItem;
     GetSameTypeParent(getter_AddRefs(parentAsItem));
     nsCOMPtr<nsIDocShell> parentDS(do_QueryInterface(parentAsItem));
-    uint32_t parentLoadType;
-
-    if (parentDS && parentDS != static_cast<nsIDocShell*>(this)) {
-      /* OK. It is a subframe. Checkout the
-       * parent's loadtype. If the parent was loaded thro' a history
-       * mechanism, then get the SH entry for the child from the parent.
-       * This is done to restore frameset navigation while going back/forward.
-       * If the parent was loaded through any other loadType, set the
-       * child's loadType too accordingly, so that session history does not
-       * get confused.
+
+  if (!parentDS || parentDS == static_cast<nsIDocShell*>(this)) {
+    // This is the root docshell. If we got here while
+    // executing an onLoad Handler,this load will not go
+    // into session history.
+    bool inOnLoadHandler = false;
+    GetIsExecutingOnLoadHandler(&inOnLoadHandler);
+    if (inOnLoadHandler) {
+      aLoadState->SetLoadType(LOAD_NORMAL_REPLACE);
+    }
+    return;
+  }
+
+  /* OK. It is a subframe. Checkout the parent's loadtype. If the parent was
+   * loaded through a history mechanism, then get the SH entry for the child from
+   * the parent. This is done to restore frameset navigation while going
+   * back/forward. If the parent was loaded through any other loadType, set the
+   * child's loadType too accordingly, so that session history does not get
+   * confused.
        */
 
       // Get the parent's load type
+  uint32_t parentLoadType;
       parentDS->GetLoadType(&parentLoadType);
 
       // Get the ShEntry for the child from the parent
       nsCOMPtr<nsISHEntry> currentSH;
       bool oshe = false;
       parentDS->GetCurrentSHEntry(getter_AddRefs(currentSH), &oshe);
       bool dynamicallyAddedChild = mDynamicallyCreated;
+
       if (!dynamicallyAddedChild && !oshe && currentSH) {
         currentSH->HasDynamicallyAddedChild(&dynamicallyAddedChild);
       }
+
       if (!dynamicallyAddedChild) {
         // Only use the old SHEntry, if we're sure enough that
         // it wasn't originally for some other frame.
+    nsCOMPtr<nsISHEntry> shEntry;
         parentDS->GetChildSHEntry(mChildOffset, getter_AddRefs(shEntry));
+    aLoadState->SetSHEntry(shEntry);
       }
 
       // Make some decisions on the child frame's loadType based on the
       // parent's loadType, if the subframe hasn't loaded anything into it.
       //
       // In some cases privileged scripts may try to get the DOMWindow
       // reference of this docshell before the loading starts, causing the
       // initial about:blank content viewer being created and mCurrentURI being
       // set. To handle this case we check if mCurrentURI is about:blank and
       // currentSHEntry is null.
       nsCOMPtr<nsISHEntry> currentChildEntry;
       GetCurrentSHEntry(getter_AddRefs(currentChildEntry), &oshe);
-      if (!mCurrentURI || (NS_IsAboutBlank(mCurrentURI) && !currentChildEntry)) {
-        // This is a newly created frame. Check for exception cases first.
-        // By default the subframe will inherit the parent's loadType.
-        if (shEntry && (parentLoadType == LOAD_NORMAL ||
-                        parentLoadType == LOAD_LINK   ||
-                        parentLoadType == LOAD_NORMAL_EXTERNAL)) {
-          // The parent was loaded normally. In this case, this *brand new*
-          // child really shouldn't have a SHEntry. If it does, it could be
-          // because the parent is replacing an existing frame with a new frame,
-          // in the onLoadHandler. We don't want this url to get into session
-          // history. Clear off shEntry, and set load type to
-          // LOAD_BYPASS_HISTORY.
-          bool inOnLoadHandler = false;
-          parentDS->GetIsExecutingOnLoadHandler(&inOnLoadHandler);
-          if (inOnLoadHandler) {
-            loadType = LOAD_NORMAL_REPLACE;
-            shEntry = nullptr;
-          }
-        } else if (parentLoadType == LOAD_REFRESH) {
-          // Clear shEntry. For refresh loads, we have to load
-          // what comes thro' the pipe, not what's in history.
-          shEntry = nullptr;
-        } else if ((parentLoadType == LOAD_BYPASS_HISTORY) ||
-                   (shEntry &&
-                    ((parentLoadType & LOAD_CMD_HISTORY) ||
-                     (parentLoadType == LOAD_RELOAD_NORMAL) ||
-                     (parentLoadType == LOAD_RELOAD_CHARSET_CHANGE) ||
-                     (parentLoadType == LOAD_RELOAD_CHARSET_CHANGE_BYPASS_CACHE) ||
-                     (parentLoadType == LOAD_RELOAD_CHARSET_CHANGE_BYPASS_PROXY_AND_CACHE)))) {
-          // If the parent url, bypassed history or was loaded from
-          // history, pass on the parent's loadType to the new child
-          // frame too, so that the child frame will also
-          // avoid getting into history.
-          loadType = parentLoadType;
-        } else if (parentLoadType == LOAD_ERROR_PAGE) {
-          // If the parent document is an error page, we don't
-          // want to update global/session history. However,
-          // this child frame is not an error page.
-          loadType = LOAD_BYPASS_HISTORY;
-        } else if ((parentLoadType == LOAD_RELOAD_BYPASS_CACHE) ||
-                   (parentLoadType == LOAD_RELOAD_BYPASS_PROXY) ||
-                   (parentLoadType == LOAD_RELOAD_BYPASS_PROXY_AND_CACHE)) {
-          // the new frame should inherit the parent's load type so that it also
-          // bypasses the cache and/or proxy
-          loadType = parentLoadType;
-        }
-      } else {
+
+  if (mCurrentURI && (!NS_IsAboutBlank(mCurrentURI) || currentChildEntry)) {
         // This is a pre-existing subframe. If
         // 1. The load of this frame was not originally initiated by session
         //    history directly (i.e. (!shEntry) condition succeeded, but it can
         //    still be a history load on parent which causes this frame being
-        //    loaded), and
+    //    loaded), which we checked with the above assert, and
         // 2. mCurrentURI is not null, nor the initial about:blank,
         // it is possible that a parent's onLoadHandler or even self's
         // onLoadHandler is loading a new page in this child. Check parent's and
         // self's busy flag and if it is set, we don't want this onLoadHandler
         // load to get in to session history.
         uint32_t parentBusy = BUSY_FLAGS_NONE;
         uint32_t selfBusy = BUSY_FLAGS_NONE;
         parentDS->GetBusyFlags(&parentBusy);
         GetBusyFlags(&selfBusy);
         if (parentBusy & BUSY_FLAGS_BUSY ||
             selfBusy & BUSY_FLAGS_BUSY) {
-          loadType = LOAD_NORMAL_REPLACE;
-          shEntry = nullptr;
-        }
-      }
-    } // parentDS
-    else {
-      // This is the root docshell. If we got here while
-      // executing an onLoad Handler,this load will not go
-      // into session history.
+      aLoadState->SetLoadType(LOAD_NORMAL_REPLACE);
+      aLoadState->SetSHEntry(nullptr);
+    }
+    return;
+  }
+
+  // This is a newly created frame. Check for exception cases first.
+  // By default the subframe will inherit the parent's loadType.
+  if (aLoadState->SHEntry() && (parentLoadType == LOAD_NORMAL ||
+                                parentLoadType == LOAD_LINK   ||
+                                parentLoadType == LOAD_NORMAL_EXTERNAL)) {
+    // The parent was loaded normally. In this case, this *brand new*
+    // child really shouldn't have a SHEntry. If it does, it could be
+    // because the parent is replacing an existing frame with a new frame,
+    // in the onLoadHandler. We don't want this url to get into session
+    // history. Clear off shEntry, and set load type to
+    // LOAD_BYPASS_HISTORY.
       bool inOnLoadHandler = false;
-      GetIsExecutingOnLoadHandler(&inOnLoadHandler);
+    parentDS->GetIsExecutingOnLoadHandler(&inOnLoadHandler);
       if (inOnLoadHandler) {
-        loadType = LOAD_NORMAL_REPLACE;
-      }
-    }
-  } // !shEntry
-
-  if (shEntry) {
-#ifdef DEBUG
-    MOZ_LOG(gDocShellLog, LogLevel::Debug,
-           ("nsDocShell[%p]: loading from session history", this));
-#endif
-
-    return LoadHistoryEntry(shEntry, loadType);
-  }
-
-  // On history navigation via Back/Forward buttons, don't execute
-  // automatic JavaScript redirection such as |location.href = ...| or
-  // |window.open()|
-  //
-  // LOAD_NORMAL:        window.open(...) etc.
-  // LOAD_STOP_CONTENT:  location.href = ..., location.assign(...)
-  if ((loadType == LOAD_NORMAL || loadType == LOAD_STOP_CONTENT) &&
-      ShouldBlockLoadingForBackButton()) {
-    return NS_OK;
-  }
-
-  // Perform the load...
-
-  // We need a principalToInherit.
-  //
-  // If principalIsExplicit is not set there are 4 possibilities:
-  // (1) If the system principal or an expanded principal was passed
-  //     in and we're a typeContent docshell, inherit the principal
-  //     from the current document instead.
-  // (2) In all other cases when the principal passed in is not null,
-  //     use that principal.
-  // (3) If the caller has allowed inheriting from the current document,
-  //     or if we're being called from system code (eg chrome JS or pure
-  //     C++) then inheritPrincipal should be true and InternalLoad will get
-  //     a principal from the current document. If none of these things are
-  //     true, then
-  // (4) we don't pass a principal into the channel, and a principal will be
-  //     created later from the channel's internal data.
-  //
-  // If principalIsExplicit *is* set, there are 4 possibilities
-  // (1) If the system principal or an expanded principal was passed in
-  //     and we're a typeContent docshell, return an error.
-  // (2) In all other cases when the principal passed in is not null,
-  //     use that principal.
-  // (3) If the caller has allowed inheriting from the current document,
-  //     then inheritPrincipal should be true and InternalLoad will get
-  //     a principal from the current document. If none of these things are
-  //     true, then
-  // (4) we dont' pass a principal into the channel, and a principal will be
-  //     created later from the channel's internal data.
-  nsCOMPtr<nsIPrincipal> principalToInherit = triggeringPrincipal;
-  if (principalToInherit && mItemType != typeChrome) {
-    if (nsContentUtils::IsSystemPrincipal(principalToInherit)) {
-      if (principalIsExplicit) {
-        return NS_ERROR_DOM_SECURITY_ERR;
-      }
-      principalToInherit = nullptr;
-      inheritPrincipal = true;
-    } else if (nsContentUtils::IsExpandedPrincipal(principalToInherit)) {
-      if (principalIsExplicit) {
-        return NS_ERROR_DOM_SECURITY_ERR;
-      }
-      // Don't inherit from the current page.  Just do the safe thing
-      // and pretend that we were loaded by a nullprincipal.
-      //
-      // We didn't inherit OriginAttributes here as ExpandedPrincipal doesn't
-      // have origin attributes.
-      principalToInherit = NullPrincipal::CreateWithInheritedAttributes(this);
-      inheritPrincipal = false;
-    }
-  }
-  if (!principalToInherit && !inheritPrincipal && !principalIsExplicit) {
-    // See if there's system or chrome JS code running
-    inheritPrincipal = nsContentUtils::LegacyIsCallerChromeOrNativeCode();
-  }
-
-  if (aLoadFlags & LOAD_FLAGS_DISALLOW_INHERIT_PRINCIPAL) {
-    inheritPrincipal = false;
-    // If aFirstParty is true and the pref 'privacy.firstparty.isolate' is
-    // enabled, we will set firstPartyDomain on the origin attributes.
-    principalToInherit = NullPrincipal::CreateWithInheritedAttributes(this, aFirstParty);
-  }
-
-  // If the triggeringPrincipal is not passed explicitly, we first try to create
-  // a principal from the referrer, since the referrer URI reflects the web origin
-  // that triggered the load. If there is no referrer URI, we fall back to using
-  // the SystemPrincipal. It's safe to assume that no provided triggeringPrincipal
-  // and no referrer simulate a load that was triggered by the system.
-  // It's important to note that this block of code needs to appear *after* the block
-  // where we munge the principalToInherit, because otherwise we would never enter
-  // code blocks checking if the principalToInherit is null and we will end up with
-  // a wrong inheritPrincipal flag.
-  if (!triggeringPrincipal) {
-    if (referrer) {
-      nsresult rv = CreatePrincipalFromReferrer(referrer,
-                                                getter_AddRefs(triggeringPrincipal));
-      NS_ENSURE_SUCCESS(rv, rv);
-    }
-    else {
-      triggeringPrincipal = nsContentUtils::GetSystemPrincipal();
-    }
-  }
-
-  uint32_t flags = 0;
-
-  if (inheritPrincipal) {
-    MOZ_ASSERT(!nsContentUtils::IsSystemPrincipal(principalToInherit), "Should not inherit SystemPrincipal");
-    flags |= INTERNAL_LOAD_FLAGS_INHERIT_PRINCIPAL;
-  }
-
-  if (!sendReferrer) {
-    flags |= INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER;
-  }
-
-  if (aLoadFlags & LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP) {
-    flags |= INTERNAL_LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP;
-  }
-
-  if (aLoadFlags & LOAD_FLAGS_FIRST_LOAD) {
-    flags |= INTERNAL_LOAD_FLAGS_FIRST_LOAD;
-  }
-
-  if (aLoadFlags & LOAD_FLAGS_BYPASS_CLASSIFIER) {
-    flags |= INTERNAL_LOAD_FLAGS_BYPASS_CLASSIFIER;
-  }
-
-  if (aLoadFlags & LOAD_FLAGS_FORCE_ALLOW_COOKIES) {
-    flags |= INTERNAL_LOAD_FLAGS_FORCE_ALLOW_COOKIES;
-  }
-
-  if (isSrcdoc) {
-    flags |= INTERNAL_LOAD_FLAGS_IS_SRCDOC;
-  }
-
-  if (forceAllowDataURI) {
-    flags |= INTERNAL_LOAD_FLAGS_FORCE_ALLOW_DATA_URI;
-  }
-
-  if (originalFrameSrc) {
-    flags |= INTERNAL_LOAD_FLAGS_ORIGINAL_FRAME_SRC;
-  }
-
-  return InternalLoad(aURI,
-                      originalURI,
-                      resultPrincipalURI,
-                      keepResultPrincipalURIIfSet,
-                      loadReplace,
-                      referrer,
-                      referrerPolicy,
-                      triggeringPrincipal,
-                      principalToInherit,
-                      flags,
-                      target,
-                      nullptr,      // No type hint
-                      VoidString(), // No forced download
-                      postStream,
-                      headersStream,
-                      loadType,
-                      nullptr, // No SHEntry
-                      aFirstParty,
-                      srcdoc,
-                      sourceDocShell,
-                      baseURI,
-                      nullptr,  // No nsIDocShell
-                      nullptr); // No nsIRequest
+      aLoadState->SetLoadType(LOAD_NORMAL_REPLACE);
+      aLoadState->SetSHEntry(nullptr);
+    }
+  } else if (parentLoadType == LOAD_REFRESH) {
+    // Clear shEntry. For refresh loads, we have to load
+    // what comes through the pipe, not what's in history.
+    aLoadState->SetSHEntry(nullptr);
+  } else if ((parentLoadType == LOAD_BYPASS_HISTORY) ||
+             (aLoadState->SHEntry() &&
+              ((parentLoadType & LOAD_CMD_HISTORY) ||
+               (parentLoadType == LOAD_RELOAD_NORMAL) ||
+               (parentLoadType == LOAD_RELOAD_CHARSET_CHANGE) ||
+               (parentLoadType == LOAD_RELOAD_CHARSET_CHANGE_BYPASS_CACHE) ||
+               (parentLoadType == LOAD_RELOAD_CHARSET_CHANGE_BYPASS_PROXY_AND_CACHE)))) {
+    // If the parent url, bypassed history or was loaded from
+    // history, pass on the parent's loadType to the new child
+    // frame too, so that the child frame will also
+    // avoid getting into history.
+    aLoadState->SetLoadType(parentLoadType);
+  } else if (parentLoadType == LOAD_ERROR_PAGE) {
+    // If the parent document is an error page, we don't
+    // want to update global/session history. However,
+    // this child frame is not an error page.
+    aLoadState->SetLoadType(LOAD_BYPASS_HISTORY);
+  } else if ((parentLoadType == LOAD_RELOAD_BYPASS_CACHE) ||
+             (parentLoadType == LOAD_RELOAD_BYPASS_PROXY) ||
+             (parentLoadType == LOAD_RELOAD_BYPASS_PROXY_AND_CACHE)) {
+    // the new frame should inherit the parent's load type so that it also
+    // bypasses the cache and/or proxy
+    aLoadState->SetLoadType(parentLoadType);
+  }
 }
 
 /*
  * Reset state to a new content model within the current document and the
  * document viewer. Called by the document before initiating an out of band
  * document.write().
  */
 NS_IMETHODIMP
@@ -4221,17 +4083,17 @@ nsDocShell::LoadURIWithOptions(const nsA
                                uint32_t aLoadFlags,
                                nsIURI* aReferringURI,
                                uint32_t aReferrerPolicy,
                                nsIInputStream* aPostStream,
                                nsIInputStream* aHeaderStream,
                                nsIURI* aBaseURI,
                                nsIPrincipal* aTriggeringPrincipal)
 {
-  NS_ASSERTION((aLoadFlags & 0xf) == 0, "Unexpected flags");
+  NS_ASSERTION((aLoadFlags & INTERNAL_LOAD_FLAGS_LOADURI_SETUP_FLAGS) == 0, "Unexpected flags");
 
   if (!IsNavigationAllowed()) {
     return NS_OK; // JS may not handle returning of an error code
   }
   nsCOMPtr<nsIURI> uri;
   nsCOMPtr<nsIInputStream> postStream(aPostStream);
   nsresult rv = NS_OK;
 
@@ -4316,46 +4178,47 @@ nsDocShell::LoadURIWithOptions(const nsA
     aLoadFlags & LOAD_FLAGS_FORCE_ALLOW_DATA_URI;
 
   // Don't pass certain flags that aren't needed and end up confusing
   // ConvertLoadTypeToDocShellInfoLoadType.  We do need to ensure that they are
   // passed to LoadURI though, since it uses them.
   uint32_t extraFlags = (aLoadFlags & EXTRA_LOAD_FLAGS);
   aLoadFlags &= ~EXTRA_LOAD_FLAGS;
 
-  RefPtr<nsDocShellLoadInfo> loadInfo = new nsDocShellLoadInfo();
+  RefPtr<nsDocShellLoadState> loadState = new nsDocShellLoadState();
 
   /*
    * If the user "Disables Protection on This Page", we have to make sure to
    * remember the users decision when opening links in child tabs [Bug 906190]
    */
-  uint32_t loadType;
   if (aLoadFlags & LOAD_FLAGS_ALLOW_MIXED_CONTENT) {
-    loadType = MAKE_LOAD_TYPE(LOAD_NORMAL_ALLOW_MIXED_CONTENT, aLoadFlags);
+    loadState->SetLoadType(MAKE_LOAD_TYPE(LOAD_NORMAL_ALLOW_MIXED_CONTENT, aLoadFlags));
   } else {
-    loadType = MAKE_LOAD_TYPE(LOAD_NORMAL, aLoadFlags);
-  }
-
-  loadInfo->SetLoadType(loadType);
-  loadInfo->SetPostDataStream(postStream);
-  loadInfo->SetReferrer(aReferringURI);
-  loadInfo->SetReferrerPolicy((mozilla::net::ReferrerPolicy)aReferrerPolicy);
-  loadInfo->SetHeadersStream(aHeaderStream);
-  loadInfo->SetBaseURI(aBaseURI);
-  loadInfo->SetTriggeringPrincipal(aTriggeringPrincipal);
-  loadInfo->SetForceAllowDataURI(forceAllowDataURI);
+    loadState->SetLoadType(MAKE_LOAD_TYPE(LOAD_NORMAL, aLoadFlags));
+  }
+
+  loadState->SetURI(uri);
+  loadState->SetLoadFlags(extraFlags);
+  loadState->SetFirstParty(true);
+  loadState->SetPostDataStream(postStream);
+  loadState->SetReferrer(aReferringURI);
+  loadState->SetReferrerPolicy((mozilla::net::ReferrerPolicy)aReferrerPolicy);
+  loadState->SetHeadersStream(aHeaderStream);
+  loadState->SetBaseURI(aBaseURI);
+  loadState->SetTriggeringPrincipal(aTriggeringPrincipal);
+  loadState->SetForceAllowDataURI(forceAllowDataURI);
 
   if (fixupInfo) {
     nsAutoString searchProvider, keyword;
     fixupInfo->GetKeywordProviderName(searchProvider);
     fixupInfo->GetKeywordAsSent(keyword);
     MaybeNotifyKeywordSearchLoading(searchProvider, keyword);
   }
 
-  rv = LoadURI(uri, loadInfo, extraFlags, true);
+  rv = LoadURI(loadState);
 
   // Save URI string in case it's needed later when
   // sending to search engine service in EndPageLoad()
   mOriginalUriString = uriString;
 
   return rv;
 }
 
@@ -4913,29 +4776,29 @@ nsDocShell::LoadErrorPage(nsIURI* aError
     // we go back or forward to another SHEntry with the same doc
     // identifier, the error page won't persist.
     mLSHE->AbandonBFCacheEntry();
   }
 
   return InternalLoad(aErrorURI, nullptr, Nothing(), false, false, nullptr, RP_Unset,
                       nsContentUtils::GetSystemPrincipal(), nullptr,
                       INTERNAL_LOAD_FLAGS_NONE, EmptyString(),
-                      nullptr, VoidString(), nullptr, nullptr,
+                      VoidCString(), VoidString(), nullptr, nullptr,
                       LOAD_ERROR_PAGE, nullptr, true, VoidString(), this,
                       nullptr, nullptr, nullptr);
 }
 
 NS_IMETHODIMP
 nsDocShell::Reload(uint32_t aReloadFlags)
 {
   if (!IsNavigationAllowed()) {
     return NS_OK; // JS may not handle returning of an error code
   }
   nsresult rv;
-  NS_ASSERTION(((aReloadFlags & 0xf) == 0),
+  NS_ASSERTION(((aReloadFlags & INTERNAL_LOAD_FLAGS_LOADURI_SETUP_FLAGS) == 0),
                "Reload command not updated to use load flags!");
   NS_ASSERTION((aReloadFlags & EXTRA_LOAD_FLAGS) == 0,
                "Don't pass these flags to Reload");
 
   uint32_t loadType = MAKE_LOAD_TYPE(LOAD_RELOAD_NORMAL, aReloadFlags);
   NS_ENSURE_TRUE(IsValidLoadType(loadType), NS_ERROR_INVALID_ARG);
 
   // Send notifications to the HistoryListener if any, about the impending
@@ -5013,17 +4876,17 @@ nsDocShell::Reload(uint32_t aReloadFlags
                       false,
                       loadReplace,
                       referrerURI,
                       referrerPolicy,
                       triggeringPrincipal,
                       triggeringPrincipal,
                       flags,
                       EmptyString(),   // No window target
-                      NS_LossyConvertUTF16toASCII(contentTypeHint).get(),
+                      NS_LossyConvertUTF16toASCII(contentTypeHint),
                       VoidString(),    // No forced download
                       nullptr,         // No post data
                       nullptr,         // No headers data
                       loadType,        // Load type
                       nullptr,         // No SHEntry
                       true,
                       srcdoc,          // srcdoc argument for iframe
                       this,            // For reloads we are the source
@@ -6265,76 +6128,80 @@ nsDocShell::ForceRefreshURIFromTimer(nsI
   return ForceRefreshURI(aURI, aPrincipal, aDelay, aMetaRefresh);
 }
 
 NS_IMETHODIMP
 nsDocShell::ForceRefreshURI(nsIURI* aURI, nsIPrincipal* aPrincipal, int32_t aDelay, bool aMetaRefresh)
 {
   NS_ENSURE_ARG(aURI);
 
-  RefPtr<nsDocShellLoadInfo> loadInfo = new nsDocShellLoadInfo();
+  RefPtr<nsDocShellLoadState> loadState = new nsDocShellLoadState();
 
   /* We do need to pass in a referrer, but we don't want it to
    * be sent to the server.
    */
-  loadInfo->SetSendReferrer(false);
+  loadState->SetSendReferrer(false);
 
   /* for most refreshes the current URI is an appropriate
    * internal referrer
    */
-  loadInfo->SetReferrer(mCurrentURI);
-
-  loadInfo->SetOriginalURI(mCurrentURI);
-  loadInfo->SetResultPrincipalURI(aURI);
-  loadInfo->SetResultPrincipalURIIsSome(true);
-  loadInfo->SetKeepResultPrincipalURIIfSet(true);
+  loadState->SetReferrer(mCurrentURI);
+
+  loadState->SetOriginalURI(mCurrentURI);
+  loadState->SetResultPrincipalURI(aURI);
+  loadState->SetResultPrincipalURIIsSome(true);
+  loadState->SetKeepResultPrincipalURIIfSet(true);
 
   // Set the triggering pricipal to aPrincipal if available, or current
   // document's principal otherwise.
   nsCOMPtr<nsIPrincipal> principal = aPrincipal;
   if (!principal) {
     nsCOMPtr<nsIDocument> doc = GetDocument();
     if (!doc) {
       return NS_ERROR_FAILURE;
     }
     principal = doc->NodePrincipal();
   }
-  loadInfo->SetTriggeringPrincipal(principal);
-  loadInfo->SetPrincipalIsExplicit(true);
+  loadState->SetTriggeringPrincipal(principal);
+  loadState->SetPrincipalIsExplicit(true);
 
   /* Check if this META refresh causes a redirection
    * to another site.
    */
   bool equalUri = false;
   nsresult rv = aURI->Equals(mCurrentURI, &equalUri);
   if (NS_SUCCEEDED(rv) && (!equalUri) && aMetaRefresh &&
       aDelay <= REFRESH_REDIRECT_TIMER) {
     /* It is a META refresh based redirection within the threshold time
      * we have in mind (15000 ms as defined by REFRESH_REDIRECT_TIMER).
      * Pass a REPLACE flag to LoadURI().
      */
-    loadInfo->SetLoadType(LOAD_NORMAL_REPLACE);
+    loadState->SetLoadType(LOAD_NORMAL_REPLACE);
 
     /* for redirects we mimic HTTP, which passes the
      *  original referrer
      */
     nsCOMPtr<nsIURI> internalReferrer;
     GetReferringURI(getter_AddRefs(internalReferrer));
     if (internalReferrer) {
-      loadInfo->SetReferrer(internalReferrer);
+      loadState->SetReferrer(internalReferrer);
     }
   } else {
-    loadInfo->SetLoadType(LOAD_REFRESH);
-  }
+    loadState->SetLoadType(LOAD_REFRESH);
+  }
+
+  loadState->SetURI(aURI);
+  loadState->SetLoadFlags(nsIWebNavigation::LOAD_FLAGS_DISALLOW_INHERIT_PRINCIPAL);
+  loadState->SetFirstParty(true);
 
   /*
    * LoadURI(...) will cancel all refresh timers... This causes the
    * Timer and its refreshData instance to be released...
    */
-  LoadURI(aURI, loadInfo, nsIWebNavigation::LOAD_FLAGS_DISALLOW_INHERIT_PRINCIPAL, true);
+  LoadURI(loadState);
 
   return NS_OK;
 }
 
 nsresult
 nsDocShell::SetupRefreshURIFromHeader(nsIURI* aBaseURI,
                                       nsIPrincipal* aPrincipal,
                                       const nsACString& aHeader)
@@ -9090,26 +8957,27 @@ public:
                     nsIURI* aOriginalURI,
                     Maybe<nsCOMPtr<nsIURI>> const& aResultPrincipalURI,
                     bool aKeepResultPrincipalURIIfSet,
                     bool aLoadReplace,
                     nsIURI* aReferrer, uint32_t aReferrerPolicy,
                     nsIPrincipal* aTriggeringPrincipal,
                     nsIPrincipal* aPrincipalToInherit,
                     uint32_t aFlags,
-                    const char* aTypeHint,
+                    const nsACString& aTypeHint,
                     nsIInputStream* aPostData,
                     nsIInputStream* aHeadersData,
                     uint32_t aLoadType,
                     nsISHEntry* aSHEntry,
                     bool aFirstParty,
                     const nsAString& aSrcdoc,
                     nsIDocShell* aSourceDocShell,
                     nsIURI* aBaseURI)
     : mozilla::Runnable("InternalLoadEvent")
+    , mTypeHint(aTypeHint)
     , mSrcdoc(aSrcdoc)
     , mDocShell(aDocShell)
     , mURI(aURI)
     , mOriginalURI(aOriginalURI)
     , mResultPrincipalURI(aResultPrincipalURI)
     , mKeepResultPrincipalURIIfSet(aKeepResultPrincipalURIIfSet)
     , mLoadReplace(aLoadReplace)
     , mReferrer(aReferrer)
@@ -9120,36 +8988,29 @@ public:
     , mHeadersData(aHeadersData)
     , mSHEntry(aSHEntry)
     , mFlags(aFlags)
     , mLoadType(aLoadType)
     , mFirstParty(aFirstParty)
     , mSourceDocShell(aSourceDocShell)
     , mBaseURI(aBaseURI)
   {
-    // Make sure to keep null things null as needed
-    if (aTypeHint) {
-      mTypeHint = aTypeHint;
-    } else {
-      mTypeHint.SetIsVoid(true);
-    }
   }
 
   NS_IMETHOD
   Run() override
   {
     return mDocShell->InternalLoad(mURI, mOriginalURI, mResultPrincipalURI,
                                    mKeepResultPrincipalURIIfSet,
                                    mLoadReplace,
                                    mReferrer,
                                    mReferrerPolicy,
                                    mTriggeringPrincipal, mPrincipalToInherit,
                                    mFlags, EmptyString(),
-                                   mTypeHint.IsVoid() ? nullptr
-                                                      : mTypeHint.get(),
+                                   mTypeHint,
                                    VoidString(), mPostData,
                                    mHeadersData, mLoadType, mSHEntry,
                                    mFirstParty, mSrcdoc, mSourceDocShell,
                                    mBaseURI, nullptr,
                                    nullptr);
   }
 
 private:
@@ -9210,17 +9071,17 @@ nsDocShell::InternalLoad(nsIURI* aURI,
                          bool aKeepResultPrincipalURIIfSet,
                          bool aLoadReplace,
                          nsIURI* aReferrer,
                          uint32_t aReferrerPolicy,
                          nsIPrincipal* aTriggeringPrincipal,
                          nsIPrincipal* aPrincipalToInherit,
                          uint32_t aFlags,
                          const nsAString& aWindowTarget,
-                         const char* aTypeHint,
+                         const nsACString& aTypeHint,
                          const nsAString& aFileName,
                          nsIInputStream* aPostData,
                          nsIInputStream* aHeadersData,
                          uint32_t aLoadType,
                          nsISHEntry* aSHEntry,
                          bool aFirstParty,
                          const nsAString& aSrcdoc,
                          nsIDocShell* aSourceDocShell,
@@ -9491,41 +9352,41 @@ nsDocShell::InternalLoad(nsIURI* aURI,
         // If OnLinkClickSync was invoked inside the onload handler, the load
         // type would be set to LOAD_NORMAL_REPLACE; otherwise it should be
         // LOAD_LINK.
         MOZ_ASSERT(aLoadType == LOAD_LINK ||
                    aLoadType == LOAD_NORMAL_REPLACE);
         MOZ_ASSERT(!aSHEntry);
         MOZ_ASSERT(aFirstParty); // Windowwatcher will assume this.
 
-        RefPtr<nsDocShellLoadInfo> loadInfo = new nsDocShellLoadInfo();
+        RefPtr<nsDocShellLoadState> loadState = new nsDocShellLoadState();
 
         // Set up our loadinfo so it will do the load as much like we would have
         // as possible.
-        loadInfo->SetReferrer(aReferrer);
-        loadInfo->SetReferrerPolicy((mozilla::net::ReferrerPolicy)aReferrerPolicy);
-        loadInfo->SetSendReferrer(!(aFlags &
+        loadState->SetReferrer(aReferrer);
+        loadState->SetReferrerPolicy((mozilla::net::ReferrerPolicy)aReferrerPolicy);
+        loadState->SetSendReferrer(!(aFlags &
                                     INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER));
-        loadInfo->SetOriginalURI(aOriginalURI);
-        loadInfo->SetMaybeResultPrincipalURI(aResultPrincipalURI);
-        loadInfo->SetKeepResultPrincipalURIIfSet(aKeepResultPrincipalURIIfSet);
-        loadInfo->SetLoadReplace(aLoadReplace);
-        loadInfo->SetTriggeringPrincipal(aTriggeringPrincipal);
-        loadInfo->SetInheritPrincipal(
+        loadState->SetOriginalURI(aOriginalURI);
+        loadState->SetMaybeResultPrincipalURI(aResultPrincipalURI);
+        loadState->SetKeepResultPrincipalURIIfSet(aKeepResultPrincipalURIIfSet);
+        loadState->SetLoadReplace(aLoadReplace);
+        loadState->SetTriggeringPrincipal(aTriggeringPrincipal);
+        loadState->SetInheritPrincipal(
           aFlags & INTERNAL_LOAD_FLAGS_INHERIT_PRINCIPAL);
         // Explicit principal because we do not want any guesses as to what the
         // principal to inherit is: it should be aTriggeringPrincipal.
-        loadInfo->SetPrincipalIsExplicit(true);
-        loadInfo->SetLoadType(LOAD_LINK);
-        loadInfo->SetForceAllowDataURI(aFlags & INTERNAL_LOAD_FLAGS_FORCE_ALLOW_DATA_URI);
+        loadState->SetPrincipalIsExplicit(true);
+        loadState->SetLoadType(LOAD_LINK);
+        loadState->SetForceAllowDataURI(aFlags & INTERNAL_LOAD_FLAGS_FORCE_ALLOW_DATA_URI);
 
         rv = win->Open(NS_ConvertUTF8toUTF16(spec),
                        aWindowTarget, // window name
                        EmptyString(), // Features
-                       loadInfo,
+                       loadState,
                        true, // aForceNoOpener
                        getter_AddRefs(newWin));
         MOZ_ASSERT(!newWin);
         return rv;
       }
 
       rv = win->OpenNoNavigate(NS_ConvertUTF8toUTF16(spec),
                                aWindowTarget,  // window name
@@ -10326,17 +10187,17 @@ nsDocShell::DoURILoad(nsIURI* aURI,
                       bool aLoadFromExternal,
                       bool aForceAllowDataURI,
                       bool aOriginalFrameSrc,
                       nsIURI* aReferrerURI,
                       bool aSendReferrer,
                       uint32_t aReferrerPolicy,
                       nsIPrincipal* aTriggeringPrincipal,
                       nsIPrincipal* aPrincipalToInherit,
-                      const char* aTypeHint,
+                      const nsACString& aTypeHint,
                       const nsAString& aFileName,
                       nsIInputStream* aPostData,
                       nsIInputStream* aHeadersData,
                       bool aFirstParty,
                       nsIDocShell** aDocShell,
                       nsIRequest** aRequest,
                       bool aIsNewWindowTarget,
                       bool aBypassClassifier,
@@ -10675,18 +10536,18 @@ nsDocShell::DoURILoad(nsIURI* aURI,
   loadInfo->GetResultPrincipalURI(getter_AddRefs(rpURI));
   if (aResultPrincipalURI &&
       (!aKeepResultPrincipalURIIfSet || !rpURI)) {
     // Unconditionally override, we want the replay to be equal to what has
     // been captured.
     loadInfo->SetResultPrincipalURI(aResultPrincipalURI.ref());
   }
 
-  if (aTypeHint && *aTypeHint) {
-    channel->SetContentType(nsDependentCString(aTypeHint));
+  if (!aTypeHint.IsVoid()) {
+    channel->SetContentType(aTypeHint);
     mContentTypeHint = aTypeHint;
   } else {
     mContentTypeHint.Truncate();
   }
 
   if (!aFileName.IsVoid()) {
     rv = channel->SetContentDisposition(nsIChannel::DISPOSITION_ATTACHMENT);
     NS_ENSURE_SUCCESS(rv, rv);
@@ -12230,17 +12091,17 @@ nsDocShell::LoadHistoryEntry(nsISHEntry*
                     false,
                     loadReplace,
                     referrerURI,
                     referrerPolicy,
                     triggeringPrincipal,
                     principalToInherit,
                     flags,
                     EmptyString(),      // No window target
-                    contentType.get(),  // Type hint
+                    contentType,        // Type hint
                     VoidString(),       // No forced file download
                     postData,           // Post data stream
                     nullptr,            // No headers stream
                     aLoadType,          // Load type
                     aEntry,             // SHEntry
                     true,
                     srcdoc,
                     nullptr,            // Source docshell, see comment above
@@ -13418,17 +13279,17 @@ nsDocShell::OnLinkClickSync(nsIContent* 
                              false,
                              false,                     // LoadReplace
                              referer,                   // Referer URI
                              refererPolicy,             // Referer policy
                              triggeringPrincipal,
                              aContent->NodePrincipal(),
                              flags,
                              target,                    // Window target
-                             NS_LossyConvertUTF16toASCII(typeHint).get(),
+                             NS_LossyConvertUTF16toASCII(typeHint),
                              aFileName,                 // Download as file
                              aPostDataStream,           // Post data stream
                              aHeadersDataStream,        // Headers stream
                              loadType,                  // Load type
                              nullptr,                   // No SHEntry
                              true,                      // first party site
                              VoidString(),              // No srcdoc
                              this,                      // We are the source
--- a/docshell/base/nsDocShell.h
+++ b/docshell/base/nsDocShell.h
@@ -529,17 +529,17 @@ private: // member functions
                      bool aLoadFromExternal,
                      bool aForceAllowDataURI,
                      bool aOriginalFrameSrc,
                      nsIURI* aReferrer,
                      bool aSendReferrer,
                      uint32_t aReferrerPolicy,
                      nsIPrincipal* aTriggeringPrincipal,
                      nsIPrincipal* aPrincipalToInherit,
-                     const char* aTypeHint,
+                     const nsACString& aTypeHint,
                      const nsAString& aFileName,
                      nsIInputStream* aPostData,
                      nsIInputStream* aHeadersData,
                      bool aFirstParty,
                      nsIDocShell** aDocShell,
                      nsIRequest** aRequest,
                      bool aIsNewWindowTarget,
                      bool aBypassClassifier,
@@ -900,16 +900,24 @@ private: // member functions
     return (mObserveErrorPages ? sUseErrorPages : mUseErrorPages);
   }
 
   bool CSSErrorReportingEnabled() const
   {
     return mCSSErrorReportingEnabled;
   }
 
+  // Handles retrieval of subframe session history for nsDocShell::LoadURI. If a
+  // load is requested in a subframe of the current DocShell, the subframe
+  // loadType may need to reflect the loadType of the parent document, or in
+  // some cases (like reloads), the history load may need to be cancelled. See
+  // function comments for in-depth logic descriptions.
+  void
+  MaybeHandleSubframeHistory(nsDocShellLoadState* aLoadState);
+
 private: // data members
   static nsIURIFixup* sURIFixup;
 
   // Cached value of the "browser.xul.error_pages.enabled" preference.
   static bool sUseErrorPages;
 
 #ifdef DEBUG
   // We're counting the number of |nsDocShells| to help find leaks
rename from docshell/base/nsDocShellLoadInfo.cpp
rename to docshell/base/nsDocShellLoadState.cpp
--- a/docshell/base/nsDocShellLoadInfo.cpp
+++ b/docshell/base/nsDocShellLoadState.cpp
@@ -1,318 +1,554 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#include "nsDocShellLoadInfo.h"
-#include "nsISHEntry.h"
-#include "nsIInputStream.h"
-#include "nsIURI.h"
+#include "nsDocShellLoadState.h"
 #include "nsIDocShell.h"
-#include "mozilla/net/ReferrerPolicy.h"
-#include "mozilla/Unused.h"
-#include "mozilla/Maybe.h"
+#include "nsIDocShellTreeItem.h"
+#include "nsIScriptSecurityManager.h"
+#include "nsIWebNavigation.h"
 
-namespace mozilla {
-
+#include "mozilla/OriginAttributes.h"
+#include "mozilla/NullPrincipal.h"
 
-} // mozilla
-
-nsDocShellLoadInfo::nsDocShellLoadInfo()
+nsDocShellLoadState::nsDocShellLoadState()
   : mResultPrincipalURIIsSome(false)
   , mKeepResultPrincipalURIIfSet(false)
   , mLoadReplace(false)
   , mInheritPrincipal(false)
   , mPrincipalIsExplicit(false)
   , mForceAllowDataURI(false)
   , mOriginalFrameSrc(false)
   , mSendReferrer(true)
   , mReferrerPolicy(mozilla::net::RP_Unset)
   , mLoadType(LOAD_NORMAL)
   , mIsSrcdocLoad(false)
+  , mLoadFlags(0)
+  , mFirstParty(false)
+  , mTypeHint(VoidCString())
+  , mFileName(VoidString())
+  , mDocShellInternalLoadFlags(0)
 {
 }
 
-nsDocShellLoadInfo::~nsDocShellLoadInfo()
+nsDocShellLoadState::~nsDocShellLoadState()
 {
 }
 
 nsIURI*
-nsDocShellLoadInfo::Referrer() const
+nsDocShellLoadState::Referrer() const
 {
   return mReferrer;
 }
 
 void
-nsDocShellLoadInfo::SetReferrer(nsIURI* aReferrer)
+nsDocShellLoadState::SetReferrer(nsIURI* aReferrer)
 {
   mReferrer = aReferrer;
 }
 
 nsIURI*
-nsDocShellLoadInfo::OriginalURI() const
+nsDocShellLoadState::URI() const
+{
+  return mURI;
+}
+
+void
+nsDocShellLoadState::SetURI(nsIURI* aURI)
+{
+  mURI = aURI;
+}
+
+nsIURI*
+nsDocShellLoadState::OriginalURI() const
 {
   return mOriginalURI;
 }
 
 void
-nsDocShellLoadInfo::SetOriginalURI(nsIURI* aOriginalURI)
+nsDocShellLoadState::SetOriginalURI(nsIURI* aOriginalURI)
 {
   mOriginalURI = aOriginalURI;
 }
 
 nsIURI*
-nsDocShellLoadInfo::ResultPrincipalURI() const
+nsDocShellLoadState::ResultPrincipalURI() const
 {
   return mResultPrincipalURI;
 }
 
 void
-nsDocShellLoadInfo::SetResultPrincipalURI(nsIURI* aResultPrincipalURI)
+nsDocShellLoadState::SetResultPrincipalURI(nsIURI* aResultPrincipalURI)
 {
   mResultPrincipalURI = aResultPrincipalURI;
 }
 
 bool
-nsDocShellLoadInfo::ResultPrincipalURIIsSome() const
+nsDocShellLoadState::ResultPrincipalURIIsSome() const
 {
   return mResultPrincipalURIIsSome;
 }
 
 void
-nsDocShellLoadInfo::SetResultPrincipalURIIsSome(bool aIsSome)
+nsDocShellLoadState::SetResultPrincipalURIIsSome(bool aIsSome)
 {
   mResultPrincipalURIIsSome = aIsSome;
 }
 
 bool
-nsDocShellLoadInfo::KeepResultPrincipalURIIfSet() const
+nsDocShellLoadState::KeepResultPrincipalURIIfSet() const
 {
   return mKeepResultPrincipalURIIfSet;
 }
 
 void
-nsDocShellLoadInfo::SetKeepResultPrincipalURIIfSet(bool aKeep)
+nsDocShellLoadState::SetKeepResultPrincipalURIIfSet(bool aKeep)
 {
   mKeepResultPrincipalURIIfSet = aKeep;
 }
 
 bool
-nsDocShellLoadInfo::LoadReplace() const
+nsDocShellLoadState::LoadReplace() const
 {
   return mLoadReplace;
 }
 
 void
-nsDocShellLoadInfo::SetLoadReplace(bool aLoadReplace)
+nsDocShellLoadState::SetLoadReplace(bool aLoadReplace)
 {
   mLoadReplace = aLoadReplace;
 }
 
 nsIPrincipal*
-nsDocShellLoadInfo::TriggeringPrincipal() const
+nsDocShellLoadState::TriggeringPrincipal() const
 {
   return mTriggeringPrincipal;
 }
 
 void
-nsDocShellLoadInfo::SetTriggeringPrincipal(nsIPrincipal* aTriggeringPrincipal)
+nsDocShellLoadState::SetTriggeringPrincipal(nsIPrincipal* aTriggeringPrincipal)
 {
   mTriggeringPrincipal = aTriggeringPrincipal;
 }
 
+nsIPrincipal*
+nsDocShellLoadState::PrincipalToInherit() const
+{
+  return mPrincipalToInherit;
+}
+
+void
+nsDocShellLoadState::SetPrincipalToInherit(nsIPrincipal* aPrincipalToInherit)
+{
+  mPrincipalToInherit = aPrincipalToInherit;
+}
+
 bool
-nsDocShellLoadInfo::InheritPrincipal() const
+nsDocShellLoadState::InheritPrincipal() const
 {
   return mInheritPrincipal;
 }
 
 void
-nsDocShellLoadInfo::SetInheritPrincipal(bool aInheritPrincipal)
+nsDocShellLoadState::SetInheritPrincipal(bool aInheritPrincipal)
 {
   mInheritPrincipal = aInheritPrincipal;
 }
 
 bool
-nsDocShellLoadInfo::PrincipalIsExplicit() const
+nsDocShellLoadState::PrincipalIsExplicit() const
 {
   return mPrincipalIsExplicit;
 }
 
 void
-nsDocShellLoadInfo::SetPrincipalIsExplicit(bool aPrincipalIsExplicit)
+nsDocShellLoadState::SetPrincipalIsExplicit(bool aPrincipalIsExplicit)
 {
   mPrincipalIsExplicit = aPrincipalIsExplicit;
 }
 
 bool
-nsDocShellLoadInfo::ForceAllowDataURI() const
+nsDocShellLoadState::ForceAllowDataURI() const
 {
   return mForceAllowDataURI;
 }
 
 void
-nsDocShellLoadInfo::SetForceAllowDataURI(bool aForceAllowDataURI)
+nsDocShellLoadState::SetForceAllowDataURI(bool aForceAllowDataURI)
 {
   mForceAllowDataURI = aForceAllowDataURI;
 }
 
 bool
-nsDocShellLoadInfo::OriginalFrameSrc() const
+nsDocShellLoadState::OriginalFrameSrc() const
 {
   return mOriginalFrameSrc;
 }
 
 void
-nsDocShellLoadInfo::SetOriginalFrameSrc(bool aOriginalFrameSrc)
+nsDocShellLoadState::SetOriginalFrameSrc(bool aOriginalFrameSrc)
 {
   mOriginalFrameSrc = aOriginalFrameSrc;
 }
 
 uint32_t
-nsDocShellLoadInfo::LoadType() const
+nsDocShellLoadState::LoadType() const
 {
   return mLoadType;
 }
 
 void
-nsDocShellLoadInfo::SetLoadType(uint32_t aLoadType)
+nsDocShellLoadState::SetLoadType(uint32_t aLoadType)
 {
   mLoadType = aLoadType;
 }
 
 nsISHEntry*
-nsDocShellLoadInfo::SHEntry() const
+nsDocShellLoadState::SHEntry() const
 {
   return mSHEntry;
 }
 
 void
-nsDocShellLoadInfo::SetSHEntry(nsISHEntry* aSHEntry)
+nsDocShellLoadState::SetSHEntry(nsISHEntry* aSHEntry)
 {
   mSHEntry = aSHEntry;
 }
 
-void
-nsDocShellLoadInfo::GetTarget(nsAString& aTarget) const
+const nsString&
+nsDocShellLoadState::Target() const
 {
-  aTarget = mTarget;
+  return mTarget;
 }
 
 void
-nsDocShellLoadInfo::SetTarget(const nsAString& aTarget)
+nsDocShellLoadState::SetTarget(const nsAString& aTarget)
 {
   mTarget = aTarget;
 }
 
 nsIInputStream*
-nsDocShellLoadInfo::PostDataStream() const
+nsDocShellLoadState::PostDataStream() const
 {
   return mPostDataStream;
 }
 
 void
-nsDocShellLoadInfo::SetPostDataStream(nsIInputStream* aStream)
+nsDocShellLoadState::SetPostDataStream(nsIInputStream* aStream)
 {
   mPostDataStream = aStream;
 }
 
 nsIInputStream*
-nsDocShellLoadInfo::HeadersStream() const
+nsDocShellLoadState::HeadersStream() const
 {
   return mHeadersStream;
 }
 
 void
-nsDocShellLoadInfo::SetHeadersStream(nsIInputStream* aHeadersStream)
+nsDocShellLoadState::SetHeadersStream(nsIInputStream* aHeadersStream)
 {
   mHeadersStream = aHeadersStream;
 }
 
 bool
-nsDocShellLoadInfo::SendReferrer() const
+nsDocShellLoadState::SendReferrer() const
 {
   return mSendReferrer;
 }
 
 void
-nsDocShellLoadInfo::SetSendReferrer(bool aSendReferrer)
+nsDocShellLoadState::SetSendReferrer(bool aSendReferrer)
 {
   mSendReferrer = aSendReferrer;
 }
 
 uint32_t
-nsDocShellLoadInfo::ReferrerPolicy() const
+nsDocShellLoadState::ReferrerPolicy() const
 {
   return mReferrerPolicy;
 }
 
 void
-nsDocShellLoadInfo::SetReferrerPolicy(mozilla::net::ReferrerPolicy aReferrerPolicy)
+nsDocShellLoadState::SetReferrerPolicy(mozilla::net::ReferrerPolicy aReferrerPolicy)
 {
   mReferrerPolicy = aReferrerPolicy;
 }
 
 bool
-nsDocShellLoadInfo::IsSrcdocLoad() const
+nsDocShellLoadState::IsSrcdocLoad() const
 {
   return mIsSrcdocLoad;
 }
 
-void
-nsDocShellLoadInfo::GetSrcdocData(nsAString& aSrcdocData) const
+const nsString&
+nsDocShellLoadState::SrcdocData() const
 {
-  aSrcdocData = mSrcdocData;
+  return mSrcdocData;
 }
 
 void
-nsDocShellLoadInfo::SetSrcdocData(const nsAString& aSrcdocData)
+nsDocShellLoadState::SetSrcdocData(const nsAString& aSrcdocData)
 {
   mSrcdocData = aSrcdocData;
   mIsSrcdocLoad = true;
 }
 
 nsIDocShell*
-nsDocShellLoadInfo::SourceDocShell() const
+nsDocShellLoadState::SourceDocShell() const
 {
   return mSourceDocShell;
 }
 
 void
-nsDocShellLoadInfo::SetSourceDocShell(nsIDocShell* aSourceDocShell)
+nsDocShellLoadState::SetSourceDocShell(nsIDocShell* aSourceDocShell)
 {
   mSourceDocShell = aSourceDocShell;
 }
 
 nsIURI*
-nsDocShellLoadInfo::BaseURI() const
+nsDocShellLoadState::BaseURI() const
 {
   return mBaseURI;
 }
 
 void
-nsDocShellLoadInfo::SetBaseURI(nsIURI* aBaseURI)
+nsDocShellLoadState::SetBaseURI(nsIURI* aBaseURI)
 {
   mBaseURI = aBaseURI;
 }
 
 void
-nsDocShellLoadInfo::GetMaybeResultPrincipalURI(mozilla::Maybe<nsCOMPtr<nsIURI>>& aRPURI) const
+nsDocShellLoadState::GetMaybeResultPrincipalURI(mozilla::Maybe<nsCOMPtr<nsIURI>>& aRPURI) const
 {
   bool isSome = ResultPrincipalURIIsSome();
   aRPURI.reset();
 
   if (!isSome) {
     return;
   }
 
   nsCOMPtr<nsIURI> uri = ResultPrincipalURI();
   aRPURI.emplace(std::move(uri));
 }
 
 void
-nsDocShellLoadInfo::SetMaybeResultPrincipalURI(mozilla::Maybe<nsCOMPtr<nsIURI>> const& aRPURI)
+nsDocShellLoadState::SetMaybeResultPrincipalURI(mozilla::Maybe<nsCOMPtr<nsIURI>> const& aRPURI)
 {
   SetResultPrincipalURI(aRPURI.refOr(nullptr));
   SetResultPrincipalURIIsSome(aRPURI.isSome());
 }
+
+uint32_t
+nsDocShellLoadState::LoadFlags() const
+{
+  return mLoadFlags;
+}
+
+void
+nsDocShellLoadState::SetLoadFlags(uint32_t aLoadFlags)
+{
+  mLoadFlags = aLoadFlags;
+}
+
+bool
+nsDocShellLoadState::FirstParty() const
+{
+  return mFirstParty;
+}
+
+void
+nsDocShellLoadState::SetFirstParty(bool aFirstParty)
+{
+  mFirstParty = aFirstParty;
+}
+
+const nsCString&
+nsDocShellLoadState::TypeHint() const
+{
+  return mTypeHint;
+}
+
+void
+nsDocShellLoadState::SetTypeHint(const nsCString& aTypeHint)
+{
+  mTypeHint = aTypeHint;
+}
+
+const nsString&
+nsDocShellLoadState::FileName() const
+{
+  return mFileName;
+}
+
+void
+nsDocShellLoadState::SetFileName(const nsAString& aFileName)
+{
+  mFileName = aFileName;
+}
+
+uint32_t
+nsDocShellLoadState::DocShellInternalLoadFlags() const
+{
+  return mDocShellInternalLoadFlags;
+}
+
+void
+nsDocShellLoadState::SetDocShellInternalLoadFlags(uint32_t aFlags)
+{
+  mDocShellInternalLoadFlags = aFlags;
+}
+
+
+nsresult
+nsDocShellLoadState::SetupInheritingPrincipal(uint32_t aItemType,
+                                              const mozilla::OriginAttributes& aOriginAttributes)
+{
+  // We need a principalToInherit.
+  //
+  // If principalIsExplicit is not set there are 4 possibilities:
+  // (1) If the system principal or an expanded principal was passed
+  //     in and we're a typeContent docshell, inherit the principal
+  //     from the current document instead.
+  // (2) In all other cases when the principal passed in is not null,
+  //     use that principal.
+  // (3) If the caller has allowed inheriting from the current document,
+  //     or if we're being called from system code (eg chrome JS or pure
+  //     C++) then inheritPrincipal should be true and InternalLoad will get
+  //     a principal from the current document. If none of these things are
+  //     true, then
+  // (4) we don't pass a principal into the channel, and a principal will be
+  //     created later from the channel's internal data.
+  //
+  // If principalIsExplicit *is* set, there are 4 possibilities
+  // (1) If the system principal or an expanded principal was passed in
+  //     and we're a typeContent docshell, return an error.
+  // (2) In all other cases when the principal passed in is not null,
+  //     use that principal.
+  // (3) If the caller has allowed inheriting from the current document,
+  //     then inheritPrincipal should be true and InternalLoad will get
+  //     a principal from the current document. If none of these things are
+  //     true, then
+  // (4) we dont' pass a principal into the channel, and a principal will be
+  //     created later from the channel's internal data.
+  mPrincipalToInherit = mTriggeringPrincipal;
+  if (mPrincipalToInherit && aItemType != nsIDocShellTreeItem::typeChrome) {
+    if (nsContentUtils::IsSystemPrincipal(mPrincipalToInherit)) {
+      if (mPrincipalIsExplicit) {
+        return NS_ERROR_DOM_SECURITY_ERR;
+      }
+      mPrincipalToInherit = nullptr;
+      mInheritPrincipal = true;
+    } else if (nsContentUtils::IsExpandedPrincipal(mPrincipalToInherit)) {
+      if (mPrincipalIsExplicit) {
+        return NS_ERROR_DOM_SECURITY_ERR;
+      }
+      // Don't inherit from the current page.  Just do the safe thing
+      // and pretend that we were loaded by a nullprincipal.
+      //
+      // We didn't inherit OriginAttributes here as ExpandedPrincipal doesn't
+      // have origin attributes.
+      mPrincipalToInherit =
+        NullPrincipal::CreateWithInheritedAttributes(aOriginAttributes,
+                                                     false);
+      mInheritPrincipal = false;
+    }
+  }
+
+  if (!mPrincipalToInherit && !mInheritPrincipal && !mPrincipalIsExplicit) {
+    // See if there's system or chrome JS code running
+    mInheritPrincipal = nsContentUtils::LegacyIsCallerChromeOrNativeCode();
+  }
+
+  if (mLoadFlags & nsIWebNavigation::LOAD_FLAGS_DISALLOW_INHERIT_PRINCIPAL) {
+    mInheritPrincipal = false;
+    // If mFirstParty is true and the pref 'privacy.firstparty.isolate' is
+    // enabled, we will set firstPartyDomain on the origin attributes.
+    mPrincipalToInherit =
+      NullPrincipal::CreateWithInheritedAttributes(aOriginAttributes,
+                                                   mFirstParty);
+  }
+
+  return NS_OK;
+}
+
+nsresult
+nsDocShellLoadState::SetupTriggeringPrincipal(const mozilla::OriginAttributes& aOriginAttributes)
+{
+  // If the triggeringPrincipal is not set, we first try to create a principal
+  // from the referrer, since the referrer URI reflects the web origin that
+  // triggered the load. If there is no referrer URI, we fall back to using the
+  // SystemPrincipal. It's safe to assume that no provided triggeringPrincipal
+  // and no referrer simulate a load that was triggered by the system. It's
+  // important to note that this block of code needs to appear *after* the block
+  // where we munge the principalToInherit, because otherwise we would never
+  // enter code blocks checking if the principalToInherit is null and we will
+  // end up with a wrong inheritPrincipal flag.
+  if (!mTriggeringPrincipal) {
+    if (mReferrer) {
+      mTriggeringPrincipal =
+        BasePrincipal::CreateCodebasePrincipal(mReferrer, aOriginAttributes);
+
+      if (!mTriggeringPrincipal) {
+        return NS_ERROR_FAILURE;
+      }
+    } else {
+      mTriggeringPrincipal = nsContentUtils::GetSystemPrincipal();
+    }
+  }
+  return NS_OK;
+}
+
+void
+nsDocShellLoadState::CalculateDocShellInternalLoadFlags()
+{
+  MOZ_ASSERT(mDocShellInternalLoadFlags == 0,
+             "Shouldn't have any load flags set at this point.");
+
+  if (mInheritPrincipal) {
+    MOZ_ASSERT(!nsContentUtils::IsSystemPrincipal(mPrincipalToInherit),
+               "Should not inherit SystemPrincipal");
+    mDocShellInternalLoadFlags |=
+      nsIDocShell::INTERNAL_LOAD_FLAGS_INHERIT_PRINCIPAL;
+  }
+
+  if (!mSendReferrer) {
+    mDocShellInternalLoadFlags |=
+      nsIDocShell::INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER;
+  }
+
+  if (mDocShellInternalLoadFlags & nsIWebNavigation::LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP) {
+    mDocShellInternalLoadFlags |=
+      nsIDocShell::INTERNAL_LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP;
+  }
+
+  if (mDocShellInternalLoadFlags & nsIWebNavigation::LOAD_FLAGS_FIRST_LOAD) {
+    mDocShellInternalLoadFlags |= nsIDocShell::INTERNAL_LOAD_FLAGS_FIRST_LOAD;
+  }
+
+  if (mDocShellInternalLoadFlags & nsIWebNavigation::LOAD_FLAGS_BYPASS_CLASSIFIER) {
+    mDocShellInternalLoadFlags |=
+      nsIDocShell::INTERNAL_LOAD_FLAGS_BYPASS_CLASSIFIER;
+  }
+
+  if (mDocShellInternalLoadFlags & nsIWebNavigation::LOAD_FLAGS_FORCE_ALLOW_COOKIES) {
+    mDocShellInternalLoadFlags |=
+      nsIDocShell::INTERNAL_LOAD_FLAGS_FORCE_ALLOW_COOKIES;
+  }
+
+  if (mIsSrcdocLoad) {
+    mDocShellInternalLoadFlags |= nsIDocShell::INTERNAL_LOAD_FLAGS_IS_SRCDOC;
+  }
+
+  if (mForceAllowDataURI) {
+    mDocShellInternalLoadFlags |=
+      nsIDocShell::INTERNAL_LOAD_FLAGS_FORCE_ALLOW_DATA_URI;
+  }
+
+  if (mOriginalFrameSrc) {
+    mDocShellInternalLoadFlags |=
+      nsIDocShell::INTERNAL_LOAD_FLAGS_ORIGINAL_FRAME_SRC;
+  }
+}
rename from docshell/base/nsDocShellLoadInfo.h
rename to docshell/base/nsDocShellLoadState.h
--- a/docshell/base/nsDocShellLoadInfo.h
+++ b/docshell/base/nsDocShellLoadState.h
@@ -1,59 +1,70 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#ifndef nsDocShellLoadInfo_h__
-#define nsDocShellLoadInfo_h__
+#ifndef nsDocShellLoadState_h__
+#define nsDocShellLoadState_h__
 
 // Helper Classes
 #include "nsCOMPtr.h"
 #include "nsString.h"
 #include "nsDocShellLoadTypes.h"
 #include "mozilla/net/ReferrerPolicy.h"
 
 class nsIInputStream;
 class nsISHEntry;
 class nsIURI;
 class nsIDocShell;
+class OriginAttibutes;
 
 /**
- * nsDocShellLoadInfo contains setup information used in a nsIDocShell::loadURI
+ * nsDocShellLoadState contains setup information used in a nsIDocShell::loadURI
  * call.
  */
-class nsDocShellLoadInfo
+class nsDocShellLoadState final
 {
 public:
-  NS_INLINE_DECL_REFCOUNTING(nsDocShellLoadInfo);
+  NS_INLINE_DECL_REFCOUNTING(nsDocShellLoadState);
 
-  nsDocShellLoadInfo();
+  nsDocShellLoadState();
+
+  // Getters and Setters
 
   nsIURI* Referrer() const;
 
   void SetReferrer(nsIURI* aReferrer);
 
+  nsIURI* URI() const;
+
+  void SetURI(nsIURI* aURI);
+
   nsIURI* OriginalURI() const;
 
   void SetOriginalURI(nsIURI* aOriginalURI);
 
   nsIURI* ResultPrincipalURI() const;
 
   void SetResultPrincipalURI(nsIURI* aResultPrincipalURI);
 
   bool ResultPrincipalURIIsSome() const;
 
   void SetResultPrincipalURIIsSome(bool aIsSome);
 
   bool KeepResultPrincipalURIIfSet() const;
 
   void SetKeepResultPrincipalURIIfSet(bool aKeep);
 
+  nsIPrincipal* PrincipalToInherit() const;
+
+  void SetPrincipalToInherit(nsIPrincipal* aPrincipalToInherit);
+
   bool LoadReplace() const;
 
   void SetLoadReplace(bool aLoadReplace);
 
   nsIPrincipal* TriggeringPrincipal() const;
 
   void SetTriggeringPrincipal(nsIPrincipal* aTriggeringPrincipal);
 
@@ -76,17 +87,17 @@ public:
   uint32_t LoadType() const;
 
   void SetLoadType(uint32_t aLoadType);
 
   nsISHEntry* SHEntry() const;
 
   void SetSHEntry(nsISHEntry* aSHEntry);
 
-  void GetTarget(nsAString& aTarget) const;
+  const nsString& Target() const;
 
   void SetTarget(const nsAString& aTarget);
 
   nsIInputStream* PostDataStream() const;
 
   void SetPostDataStream(nsIInputStream* aStream);
 
   nsIInputStream* HeadersStream() const;
@@ -98,17 +109,17 @@ public:
   void SetSendReferrer(bool aSendReferrer);
 
   uint32_t ReferrerPolicy() const;
 
   void SetReferrerPolicy(mozilla::net::ReferrerPolicy aReferrerPolicy);
 
   bool IsSrcdocLoad() const;
 
-  void GetSrcdocData(nsAString& aSrcdocData) const;
+  const nsString& SrcdocData() const;
 
   void SetSrcdocData(const nsAString& aSrcdocData);
 
   nsIDocShell* SourceDocShell() const;
 
   void SetSourceDocShell(nsIDocShell* aSourceDocShell);
 
   nsIURI* BaseURI() const;
@@ -118,23 +129,64 @@ public:
   // Helper function allowing convenient work with mozilla::Maybe in C++, hiding
   // resultPrincipalURI and resultPrincipalURIIsSome attributes from the consumer.
   void
   GetMaybeResultPrincipalURI(mozilla::Maybe<nsCOMPtr<nsIURI>>& aRPURI) const;
 
   void
   SetMaybeResultPrincipalURI(mozilla::Maybe<nsCOMPtr<nsIURI>> const& aRPURI);
 
+  uint32_t LoadFlags() const;
+
+  void SetLoadFlags(uint32_t aFlags);
+
+  bool FirstParty() const;
+
+  void SetFirstParty(bool aFirstParty);
+
+  const nsCString& TypeHint() const;
+
+  void SetTypeHint(const nsCString& aTypeHint);
+
+  const nsString& FileName() const;
+
+  void SetFileName(const nsAString& aFileName);
+
+  uint32_t DocShellInternalLoadFlags() const;
+
+  void SetDocShellInternalLoadFlags(uint32_t aFlags);
+
+  // Give the type of DocShell we're loading into (chrome/content/etc) and
+  // origin attributes for the URI we're loading, figure out if we should
+  // inherit our principal from the document the load was requested from, or
+  // else if the principal should be set up later in the process (after loads).
+  // See comments in function for more info on principal selection algorithm
+  nsresult SetupInheritingPrincipal(uint32_t aItemType, const mozilla::OriginAttributes& aOriginAttributes);
+
+  // If no triggering principal exists at the moment, create one using referrer
+  // information and origin attributes.
+  nsresult SetupTriggeringPrincipal(const mozilla::OriginAttributes& aOriginAttributes);
+
+  // When loading a document through nsDocShell::LoadURI(), a special set of
+  // flags needs to be set based on other values in nsDocShellLoadState. This
+  // function calculates those flags, before the LoadState is passed to
+  // nsDocShell::InternalLoad.
+  void CalculateDocShellInternalLoadFlags();
 protected:
-  virtual ~nsDocShellLoadInfo();
+  // Destructor can't be defaulted or inlined, as header doesn't have all type
+  // includes it needs to do so.
+  ~nsDocShellLoadState();
 
 protected:
   // This is the referrer for the load.
   nsCOMPtr<nsIURI> mReferrer;
 
+  // The URI we are navigating to. Will not be null once set.
+  nsCOMPtr<nsIURI> mURI;
+
   // The originalURI to be passed to nsIDocShell.internalLoad. May be null.
   nsCOMPtr<nsIURI> mOriginalURI;
 
   // Result principal URL from nsILoadInfo, may be null. Valid only if
   // mResultPrincipalURIIsSome is true (has the same meaning as isSome() on
   // mozilla::Maybe.)
   nsCOMPtr<nsIURI> mResultPrincipalURI;
   bool mResultPrincipalURIIsSome;
@@ -157,16 +209,22 @@ protected:
 
   // If this attribute is true only ever use the principal specified
   // by the triggeringPrincipal and inheritPrincipal attributes.
   // If there are security reasons for why this is unsafe, such
   // as trying to use a systemprincipal as the triggeringPrincipal
   // for a content docshell the load fails.
   bool mPrincipalIsExplicit;
 
+  // Principal we're inheriting. If null, this means the principal should be
+  // inherited from the current document. If set to NullPrincipal, the channel
+  // will fill in principal information later in the load. See internal function
+  // comments for more info.
+  nsCOMPtr<nsIPrincipal> mPrincipalToInherit;
+
   // If this attribute is true, then a top-level navigation
   // to a data URI will be allowed.
   bool mForceAllowDataURI;
 
   // If this attribute is true, this load corresponds to a frame
   // element loading its original src (or srcdoc) attribute.
   bool mOriginalFrameSrc;
 
@@ -204,11 +262,32 @@ protected:
   nsString mSrcdocData;
 
   // When set, this is the Source Browsing Context for the navigation.
   nsCOMPtr<nsIDocShell> mSourceDocShell;
 
   // Used for srcdoc loads to give view-source knowledge of the load's base URI
   // as this information isn't embedded in the load's URI.
   nsCOMPtr<nsIURI> mBaseURI;
+
+  // Set of Load Flags, taken from nsDocShellLoadTypes.h
+  uint32_t mLoadFlags;
+
+  // Is this a First Party Load?
+  bool mFirstParty;
+
+  // A hint as to the content-type of the resulting data. If no hint, IsVoid()
+  // should return true.
+  nsCString mTypeHint;
+
+  // Non-void when the link should be downloaded as the given filename.
+  // mFileName being non-void but empty means that no filename hint was
+  // specified, but link should still trigger a download. If not a download,
+  // mFileName.IsVoid() should return true.
+  nsString mFileName;
+
+  // LoadFlags calculated in nsDocShell::LoadURI and passed to
+  // nsDocShell::InternalLoad, taken from the INTERNAL_LOAD consts in
+  // nsIDocShell.idl
+  uint32_t mDocShellInternalLoadFlags;
 };
 
-#endif /* nsDocShellLoadInfo_h__ */
+#endif /* nsDocShellLoadState_h__ */
--- a/docshell/base/nsDocShellLoadTypes.h
+++ b/docshell/base/nsDocShellLoadTypes.h
@@ -6,17 +6,16 @@
 
 #ifndef nsDocShellLoadTypes_h_
 #define nsDocShellLoadTypes_h_
 
 #ifdef MOZILLA_INTERNAL_API
 
 #include "nsDOMNavigationTiming.h"
 #include "nsIDocShell.h"
-#include "nsDocShellLoadInfo.h"
 #include "nsIWebNavigation.h"
 
 /**
  * Load flag for error pages. This uses one of the reserved flag
  * values from nsIWebNavigation.
  */
 #define LOAD_FLAGS_ERROR_PAGE 0x0001U
 
--- a/docshell/base/nsIDocShell.idl
+++ b/docshell/base/nsIDocShell.idl
@@ -12,17 +12,17 @@
 #include "js/TypeDecls.h"
 #include "mozilla/Maybe.h"
 #include "mozilla/NotNull.h"
 #include "mozilla/UniquePtr.h"
 #include "nsCOMPtr.h"
 #include "nsIURI.h"
 class nsPresContext;
 class nsIPresShell;
-class nsDocShellLoadInfo;
+class nsDocShellLoadState;
 namespace mozilla {
 class Encoding;
 class HTMLEditor;
 namespace dom {
 class BrowsingContext;
 class ClientSource;
 } // namespace dom
 }
@@ -58,58 +58,50 @@ interface nsIPrivacyTransitionObserver;
 interface nsIReflowObserver;
 interface nsIScrollObserver;
 interface nsITabParent;
 interface nsITabChild;
 interface nsICommandManager;
 interface nsICommandParams;
 interface nsILoadURIDelegate;
 native TabChildRef(already_AddRefed<nsITabChild>);
-native nsDocShellLoadInfoPtr(nsDocShellLoadInfo*);
+native nsDocShellLoadStatePtr(nsDocShellLoadState*);
 
 webidl BrowsingContext;
 webidl ContentFrameMessageManager;
 webidl EventTarget;
 
 [scriptable, builtinclass, uuid(049234fe-da10-478b-bc5d-bc6f9a1ba63d)]
 interface nsIDocShell : nsIDocShellTreeItem
 {
   /**
    * Loads a given URI.  This will give priority to loading the requested URI
    * in the object implementing this interface.  If it can't be loaded here
    * however, the URL dispatcher will go through its normal process of content
    * loading.
    *
-   * @param uri        - The URI to load.
-   * @param loadInfo   - This is the extended load info for this load.  This
-   *                     most often will be null, but if you need to do
-   *                     additional setup for this load you can get a loadInfo
-   *                     object by calling createLoadInfo.  Once you have this
-   *                     object you can set the needed properties on it and
-   *                     then pass it to loadURI.
-   * @param aLoadFlags - Flags to modify load behaviour. Flags are defined in
-   *                     nsIWebNavigation.  Note that using flags outside
-   *                     LOAD_FLAGS_MASK is only allowed if passing in a
-   *                     non-null loadInfo.  And even some of those might not
-   *                     be allowed.  Use at your own risk.
+   * @param loadState   - This is the extended load info for this load.
    */
-  [noscript]void loadURI(in nsIURI uri,
-                         in nsDocShellLoadInfoPtr loadInfo,
-                         in unsigned long aLoadFlags,
-                         in boolean firstParty);
+  [noscript]void loadURI(in nsDocShellLoadStatePtr loadState);
 
   const long INTERNAL_LOAD_FLAGS_NONE                    = 0x0;
   const long INTERNAL_LOAD_FLAGS_INHERIT_PRINCIPAL       = 0x1;
   const long INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER      = 0x2;
   const long INTERNAL_LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP = 0x4;
 
   // This flag marks the first load in this object
   // @see nsIWebNavigation::LOAD_FLAGS_FIRST_LOAD
   const long INTERNAL_LOAD_FLAGS_FIRST_LOAD              = 0x8;
 
+
+  // The set of flags that should not be set before calling into
+  // nsDocShell::LoadURI and other nsDocShell loading functions.
+  const long INTERNAL_LOAD_FLAGS_LOADURI_SETUP_FLAGS     = 0xf;
+
+
   const long INTERNAL_LOAD_FLAGS_BYPASS_CLASSIFIER       = 0x10;
   const long INTERNAL_LOAD_FLAGS_FORCE_ALLOW_COOKIES     = 0x20;
 
   // Whether the load should be treated as srcdoc load, rather than a URI one.
   const long INTERNAL_LOAD_FLAGS_IS_SRCDOC               = 0x40;
 
   // Whether this is the load of a frame's original src attribute
   const long INTERNAL_LOAD_FLAGS_ORIGINAL_FRAME_SRC      = 0x80;
@@ -193,17 +185,17 @@ interface nsIDocShell : nsIDocShellTreeI
                               in bool aKeepResultPrincipalURIIfSet,
                               in boolean aLoadReplace,
                               in nsIURI aReferrer,
                               in unsigned long aReferrerPolicy,
                               in nsIPrincipal aTriggeringPrincipal,
                               in nsIPrincipal aPrincipalToInherit,
                               in uint32_t aFlags,
                               in AString aWindowTarget,
-                              in string aTypeHint,
+                              in ACString aTypeHint,
                               in AString aFileName,
                               in nsIInputStream aPostDataStream,
                               in nsIInputStream aHeadersStream,
                               in unsigned long aLoadFlags,
                               in nsISHEntry aSHEntry,
                               in boolean aFirstParty,
                               in AString aSrcdoc,
                               in nsIDocShell aSourceDocShell,
--- a/docshell/shistory/nsSHEntry.cpp
+++ b/docshell/shistory/nsSHEntry.cpp
@@ -4,18 +4,18 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsSHEntry.h"
 
 #include <algorithm>
 
 #include "nsDocShellEditorData.h"
+#include "nsDocShellLoadTypes.h"
 #include "nsIContentViewer.h"
-#include "nsDocShellLoadInfo.h"
 #include "nsIDocShellTreeItem.h"
 #include "nsIInputStream.h"
 #include "nsILayoutHistoryState.h"
 #include "nsIStructuredCloneContainer.h"
 #include "nsIURI.h"
 #include "nsSHEntryShared.h"
 #include "nsSHistory.h"
 
--- a/docshell/shistory/nsSHistory.cpp
+++ b/docshell/shistory/nsSHistory.cpp
@@ -8,17 +8,17 @@
 
 #include <algorithm>
 
 #include "nsCOMArray.h"
 #include "nsComponentManagerUtils.h"
 #include "nsDocShell.h"
 #include "nsIContentViewer.h"
 #include "nsIDocShell.h"
-#include "nsDocShellLoadInfo.h"
+#include "nsDocShellLoadState.h"
 #include "nsIDocShellTreeItem.h"
 #include "nsILayoutHistoryState.h"
 #include "nsIObserverService.h"
 #include "nsISHEntry.h"
 #include "nsISHistoryListener.h"
 #include "nsIURI.h"
 #include "nsNetUtil.h"
 #include "nsTArray.h"
@@ -1570,37 +1570,39 @@ nsSHistory::LoadDifferingEntries(nsISHEn
 }
 
 nsresult
 nsSHistory::InitiateLoad(nsISHEntry* aFrameEntry, nsIDocShell* aFrameDS,
                          long aLoadType)
 {
   NS_ENSURE_STATE(aFrameDS && aFrameEntry);
 
-  RefPtr<nsDocShellLoadInfo> loadInfo = new nsDocShellLoadInfo();
+  RefPtr<nsDocShellLoadState> loadState = new nsDocShellLoadState();
 
   /* Set the loadType in the SHEntry too to  what was passed on.
    * This will be passed on to child subframes later in nsDocShell,
    * so that proper loadType is maintained through out a frameset
    */
   aFrameEntry->SetLoadType(aLoadType);
 
-  loadInfo->SetLoadType(aLoadType);
-  loadInfo->SetSHEntry(aFrameEntry);
+  loadState->SetLoadType(aLoadType);
+  loadState->SetSHEntry(aFrameEntry);
 
   nsCOMPtr<nsIURI> originalURI = aFrameEntry->GetOriginalURI();
-  loadInfo->SetOriginalURI(originalURI);
+  loadState->SetOriginalURI(originalURI);
 
-  loadInfo->SetLoadReplace(aFrameEntry->GetLoadReplace());
+  loadState->SetLoadReplace(aFrameEntry->GetLoadReplace());
 
-  nsCOMPtr<nsIURI> nextURI = aFrameEntry->GetURI();
+  nsCOMPtr<nsIURI> newURI = aFrameEntry->GetURI();
+  loadState->SetURI(newURI);
+  loadState->SetLoadFlags(nsIWebNavigation::LOAD_FLAGS_NONE);
+  loadState->SetFirstParty(false);
+
   // Time to initiate a document load
-  return aFrameDS->LoadURI(nextURI, loadInfo,
-                           nsIWebNavigation::LOAD_FLAGS_NONE, false);
-
+  return aFrameDS->LoadURI(loadState);
 }
 
 NS_IMETHODIMP_(void)
 nsSHistory::SetRootDocShell(nsIDocShell* aDocShell)
 {
   mRootDocShell = aDocShell;
 
   // Init mHistoryTracker on setting mRootDocShell so we can bind its event
--- a/dom/base/Location.cpp
+++ b/dom/base/Location.cpp
@@ -4,17 +4,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "Location.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsIScriptObjectPrincipal.h"
 #include "nsIScriptContext.h"
 #include "nsIDocShell.h"
-#include "nsDocShellLoadInfo.h"
+#include "nsDocShellLoadState.h"
 #include "nsIWebNavigation.h"
 #include "nsCDefaultURIFixup.h"
 #include "nsIURIFixup.h"
 #include "nsIURL.h"
 #include "nsIURIMutator.h"
 #include "nsIJARURI.h"
 #include "nsNetUtil.h"
 #include "nsCOMPtr.h"
@@ -56,17 +56,17 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(
   NS_INTERFACE_MAP_ENTRY(nsISupports)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(Location, mInnerWindow)
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(Location)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(Location)
 
-already_AddRefed<nsDocShellLoadInfo>
+already_AddRefed<nsDocShellLoadState>
 Location::CheckURL(nsIURI* aURI, nsIPrincipal& aSubjectPrincipal,
                    ErrorResult& aRv)
 {
   nsCOMPtr<nsIDocShell> docShell(do_QueryReferent(mDocShell));
   if (NS_WARN_IF(!docShell)) {
     aRv.Throw(NS_ERROR_NOT_AVAILABLE);
     return nullptr;
   }
@@ -147,26 +147,26 @@ Location::CheckURL(nsIURI* aURI, nsIPrin
       }
     }
   } else {
     // No document; just use our subject principal as the triggering principal.
     triggeringPrincipal = &aSubjectPrincipal;
   }
 
   // Create load info
-  RefPtr<nsDocShellLoadInfo> loadInfo = new nsDocShellLoadInfo();
+  RefPtr<nsDocShellLoadState> loadState = new nsDocShellLoadState();
 
-  loadInfo->SetTriggeringPrincipal(triggeringPrincipal);
+  loadState->SetTriggeringPrincipal(triggeringPrincipal);
 
   if (sourceURI) {
-    loadInfo->SetReferrer(sourceURI);
-    loadInfo->SetReferrerPolicy(referrerPolicy);
+    loadState->SetReferrer(sourceURI);
+    loadState->SetReferrerPolicy(referrerPolicy);
   }
 
-  return loadInfo.forget();
+  return loadState.forget();
 }
 
 nsresult
 Location::GetURI(nsIURI** aURI, bool aGetInnermostURI)
 {
   *aURI = nullptr;
 
   nsCOMPtr<nsIDocShell> docShell(do_QueryReferent(mDocShell));
@@ -207,37 +207,41 @@ Location::GetURI(nsIURI** aURI, bool aGe
 }
 
 void
 Location::SetURI(nsIURI* aURI, nsIPrincipal& aSubjectPrincipal,
                  ErrorResult& aRv, bool aReplace)
 {
   nsCOMPtr<nsIDocShell> docShell(do_QueryReferent(mDocShell));
   if (docShell) {
-    RefPtr<nsDocShellLoadInfo> loadInfo =
+
+    RefPtr<nsDocShellLoadState> loadState =
       CheckURL(aURI, aSubjectPrincipal, aRv);
     if (aRv.Failed()) {
       return;
     }
 
     if (aReplace) {
-      loadInfo->SetLoadType(LOAD_STOP_CONTENT_AND_REPLACE);
+      loadState->SetLoadType(LOAD_STOP_CONTENT_AND_REPLACE);
     } else {
-      loadInfo->SetLoadType(LOAD_STOP_CONTENT);
+      loadState->SetLoadType(LOAD_STOP_CONTENT);
     }
 
     // Get the incumbent script's browsing context to set as source.
     nsCOMPtr<nsPIDOMWindowInner> sourceWindow =
       do_QueryInterface(mozilla::dom::GetIncumbentGlobal());
     if (sourceWindow) {
-      loadInfo->SetSourceDocShell(sourceWindow->GetDocShell());
+      loadState->SetSourceDocShell(sourceWindow->GetDocShell());
     }
 
-    nsresult rv = docShell->LoadURI(aURI, loadInfo,
-                                    nsIWebNavigation::LOAD_FLAGS_NONE, true);
+    loadState->SetURI(aURI);
+    loadState->SetLoadFlags(nsIWebNavigation::LOAD_FLAGS_NONE);
+    loadState->SetFirstParty(true);
+
+    nsresult rv = docShell->LoadURI(loadState);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       aRv.Throw(rv);
     }
   }
 }
 
 void
 Location::GetHash(nsAString& aHash,
--- a/dom/base/Location.h
+++ b/dom/base/Location.h
@@ -12,16 +12,17 @@
 #include "nsCycleCollectionParticipant.h"
 #include "nsIWeakReferenceUtils.h"
 #include "nsPIDOMWindow.h"
 #include "nsString.h"
 #include "nsWrapperCache.h"
 
 class nsIDocShell;
 class nsIURI;
+class nsDocShellLoadState;
 
 namespace mozilla {
 namespace dom {
 
 //*****************************************************************************
 // Location: Script "location" object
 //*****************************************************************************
 
@@ -162,16 +163,17 @@ protected:
   virtual ~Location();
 
   // In the case of jar: uris, we sometimes want the place the jar was
   // fetched from as the URI instead of the jar: uri itself.  Pass in
   // true for aGetInnermostURI when that's the case.
   // Note, this method can return NS_OK with a null value for aURL. This happens
   // if the docShell is null.
   nsresult GetURI(nsIURI** aURL, bool aGetInnermostURI = false);
+
   void SetURI(nsIURI* aURL, nsIPrincipal& aSubjectPrincipal,
               ErrorResult& aRv, bool aReplace = false);
   void SetHrefWithBase(const nsAString& aHref, nsIURI* aBase,
                        nsIPrincipal& aSubjectPrincipal,
                        bool aReplace, ErrorResult& aRv);
 
   // Helper for Assign/SetHref/Replace
   void DoSetHref(const nsAString& aHref, nsIPrincipal& aSubjectPrincipal,
@@ -179,17 +181,17 @@ protected:
 
   // Get the base URL we should be using for our relative URL
   // resolution for SetHref/Assign/Replace.
   already_AddRefed<nsIURI> GetSourceBaseURL();
 
   // Check whether it's OK to load the given url with the given subject
   // principal, and if so construct the right nsDocShellLoadInfo for the load
   // and return it.
-  already_AddRefed<nsDocShellLoadInfo> CheckURL(nsIURI *url,
+  already_AddRefed<nsDocShellLoadState> CheckURL(nsIURI *url,
                                                 nsIPrincipal& aSubjectPrincipal,
                                                 ErrorResult& aRv);
 
   bool CallerSubsumes(nsIPrincipal* aSubjectPrincipal);
 
   nsString mCachedHash;
   nsCOMPtr<nsPIDOMWindowInner> mInnerWindow;
   nsWeakPtr mDocShell;
--- a/dom/base/nsFrameLoader.cpp
+++ b/dom/base/nsFrameLoader.cpp
@@ -20,17 +20,17 @@
 #include "nsIContentInlines.h"
 #include "nsIContentViewer.h"
 #include "nsIDocument.h"
 #include "nsPIDOMWindow.h"
 #include "nsIWebNavigation.h"
 #include "nsIWebProgress.h"
 #include "nsIDocShell.h"
 #include "nsIDocShellTreeOwner.h"
-#include "nsDocShellLoadInfo.h"
+#include "nsDocShellLoadState.h"
 #include "nsIBaseWindow.h"
 #include "nsIBrowser.h"
 #include "nsContentUtils.h"
 #include "nsIXPConnect.h"
 #include "nsUnicharUtils.h"
 #include "nsIScriptGlobalObject.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsIScrollable.h"
@@ -385,95 +385,97 @@ nsFrameLoader::ReallyStartLoadingInterna
   }
   NS_ASSERTION(mDocShell,
                "MaybeCreateDocShell succeeded with a null mDocShell");
 
   // Just to be safe, recheck uri.
   rv = CheckURILoad(mURIToLoad, mTriggeringPrincipal);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  RefPtr<nsDocShellLoadInfo> loadInfo = new nsDocShellLoadInfo();
-
-  loadInfo->SetOriginalFrameSrc(mLoadingOriginalSrc);
+  RefPtr<nsDocShellLoadState> loadState = new nsDocShellLoadState();
+
+  loadState->SetOriginalFrameSrc(mLoadingOriginalSrc);
   mLoadingOriginalSrc = false;
 
   // If this frame is sandboxed with respect to origin we will set it up with
   // a null principal later in nsDocShell::DoURILoad.
   // We do it there to correctly sandbox content that was loaded into
   // the frame via other methods than the src attribute.
   // We'll use our principal, not that of the document loaded inside us.  This
   // is very important; needed to prevent XSS attacks on documents loaded in
   // subframes!
   if (mTriggeringPrincipal) {
-    loadInfo->SetTriggeringPrincipal(mTriggeringPrincipal);
+    loadState->SetTriggeringPrincipal(mTriggeringPrincipal);
   } else {
-    loadInfo->SetTriggeringPrincipal(mOwnerContent->NodePrincipal());
+    loadState->SetTriggeringPrincipal(mOwnerContent->NodePrincipal());
   }
 
   nsCOMPtr<nsIURI> referrer;
 
   nsAutoString srcdoc;
   bool isSrcdoc = mOwnerContent->IsHTMLElement(nsGkAtoms::iframe) &&
                   mOwnerContent->GetAttr(kNameSpaceID_None, nsGkAtoms::srcdoc,
                                          srcdoc);
 
   if (isSrcdoc) {
     nsAutoString referrerStr;
     mOwnerContent->OwnerDoc()->GetReferrer(referrerStr);
     rv = NS_NewURI(getter_AddRefs(referrer), referrerStr);
 
-    loadInfo->SetSrcdocData(srcdoc);
+    loadState->SetSrcdocData(srcdoc);
     nsCOMPtr<nsIURI> baseURI = mOwnerContent->GetBaseURI();
-    loadInfo->SetBaseURI(baseURI);
+    loadState->SetBaseURI(baseURI);
   }
   else {
     rv = mOwnerContent->NodePrincipal()->GetURI(getter_AddRefs(referrer));
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   // Use referrer as long as it is not an NullPrincipalURI.
   // We could add a method such as GetReferrerURI to principals to make this
   // cleaner, but given that we need to start using Source Browsing Context for
   // referrer (see Bug 960639) this may be wasted effort at this stage.
   if (referrer) {
     bool isNullPrincipalScheme;
     rv = referrer->SchemeIs(NS_NULLPRINCIPAL_SCHEME, &isNullPrincipalScheme);
     if (NS_SUCCEEDED(rv) && !isNullPrincipalScheme) {
-      loadInfo->SetReferrer(referrer);
+      loadState->SetReferrer(referrer);
     }
   }
 
   // get referrer policy for this iframe:
   // first load document wide policy, then
   // load iframe referrer attribute if enabled in preferences
   // per element referrer overrules document wide referrer if enabled
   net::ReferrerPolicy referrerPolicy = mOwnerContent->OwnerDoc()->GetReferrerPolicy();
   HTMLIFrameElement* iframe = HTMLIFrameElement::FromNode(mOwnerContent);
   if (iframe) {
     net::ReferrerPolicy iframeReferrerPolicy = iframe->GetReferrerPolicyAsEnum();
     if (iframeReferrerPolicy != net::RP_Unset) {
       referrerPolicy = iframeReferrerPolicy;
     }
   }
-  loadInfo->SetReferrerPolicy(referrerPolicy);
+  loadState->SetReferrerPolicy(referrerPolicy);
 
   // Default flags:
   int32_t flags = nsIWebNavigation::LOAD_FLAGS_NONE;
 
   // Flags for browser frame:
   if (OwnerIsMozBrowserFrame()) {
     flags = nsIWebNavigation::LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP |
             nsIWebNavigation::LOAD_FLAGS_DISALLOW_INHERIT_PRINCIPAL;
   }
 
   // Kick off the load...
   bool tmpState = mNeedsAsyncDestroy;
   mNeedsAsyncDestroy = true;
-  nsCOMPtr<nsIURI> uriToLoad = mURIToLoad;
-  rv = mDocShell->LoadURI(uriToLoad, loadInfo, flags, false);
+  loadState->SetURI(mURIToLoad);
+  loadState->SetLoadFlags(flags);
+  loadState->SetFirstParty(false);
+  rv = mDocShell->LoadURI(loadState);
   mNeedsAsyncDestroy = tmpState;
   mURIToLoad = nullptr;
   NS_ENSURE_SUCCESS(rv, rv);
 
   return NS_OK;
 }
 
 nsresult
--- a/dom/base/nsGlobalWindowOuter.cpp
+++ b/dom/base/nsGlobalWindowOuter.cpp
@@ -60,17 +60,17 @@
 #include "nsWindowSizes.h"
 #include "WindowNamedPropertiesHandler.h"
 #include "nsFrameSelection.h"
 #include "nsNetUtil.h"
 #include "nsVariant.h"
 #include "nsPrintfCString.h"
 #include "mozilla/intl/LocaleService.h"
 #include "WindowDestroyedEvent.h"
-#include "nsDocShellLoadInfo.h"
+#include "nsDocShellLoadState.h"
 
 // Helper Classes
 #include "nsJSUtils.h"
 #include "jsapi.h"
 #include "js/Wrapper.h"
 #include "nsCharSeparatedTokenizer.h"
 #include "nsReadableUtils.h"
 #include "nsJSEnvironment.h"
@@ -5515,43 +5515,43 @@ nsGlobalWindowOuter::OpenOuter(const nsA
 {
   nsCOMPtr<nsPIDOMWindowOuter> window;
   aError = OpenJS(aUrl, aName, aOptions, getter_AddRefs(window));
   return window.forget();
 }
 
 nsresult
 nsGlobalWindowOuter::Open(const nsAString& aUrl, const nsAString& aName,
-                          const nsAString& aOptions, nsDocShellLoadInfo* aLoadInfo,
+                          const nsAString& aOptions, nsDocShellLoadState* aLoadState,
                           bool aForceNoOpener, nsPIDOMWindowOuter **_retval)
 {
   return OpenInternal(aUrl, aName, aOptions,
                       false,          // aDialog
                       false,          // aContentModal
                       true,           // aCalledNoScript
                       false,          // aDoJSFixups
                       true,           // aNavigate
                       nullptr, nullptr,  // No args
-                      aLoadInfo,
+                      aLoadState,
                       aForceNoOpener,
                       _retval);
 }
 
 nsresult
 nsGlobalWindowOuter::OpenJS(const nsAString& aUrl, const nsAString& aName,
                             const nsAString& aOptions, nsPIDOMWindowOuter **_retval)
 {
   return OpenInternal(aUrl, aName, aOptions,
                       false,          // aDialog
                       false,          // aContentModal
                       false,          // aCalledNoScript
                       true,           // aDoJSFixups
                       true,           // aNavigate
                       nullptr, nullptr,  // No args
-                      nullptr,        // aLoadInfo
+                      nullptr,        // aLoadState
                       false,          // aForceNoOpener
                       _retval);
 }
 
 // like Open, but attaches to the new window any extra parameters past
 // [features] as a JS property named "arguments"
 nsresult
 nsGlobalWindowOuter::OpenDialog(const nsAString& aUrl, const nsAString& aName,
@@ -5561,17 +5561,17 @@ nsGlobalWindowOuter::OpenDialog(const ns
 {
   return OpenInternal(aUrl, aName, aOptions,
                       true,                    // aDialog
                       false,                   // aContentModal
                       true,                    // aCalledNoScript
                       false,                   // aDoJSFixups
                       true,                    // aNavigate
                       nullptr, aExtraArgument, // Arguments
-                      nullptr,                 // aLoadInfo
+                      nullptr,                 // aLoadState
                       false,                   // aForceNoOpener
                       _retval);
 }
 
 // Like Open, but passes aNavigate=false.
 /* virtual */ nsresult
 nsGlobalWindowOuter::OpenNoNavigate(const nsAString& aUrl,
                                     const nsAString& aName,
@@ -5580,17 +5580,17 @@ nsGlobalWindowOuter::OpenNoNavigate(cons
 {
   return OpenInternal(aUrl, aName, aOptions,
                       false,          // aDialog
                       false,          // aContentModal
                       true,           // aCalledNoScript
                       false,          // aDoJSFixups
                       false,          // aNavigate
                       nullptr, nullptr,  // No args
-                      nullptr,        // aLoadInfo
+                      nullptr,        // aLoadState
                       false,          // aForceNoOpener
                       _retval);
 
 }
 
 already_AddRefed<nsPIDOMWindowOuter>
 nsGlobalWindowOuter::OpenDialogOuter(JSContext* aCx, const nsAString& aUrl,
                                      const nsAString& aName, const nsAString& aOptions,
@@ -5608,17 +5608,17 @@ nsGlobalWindowOuter::OpenDialogOuter(JSC
   nsCOMPtr<nsPIDOMWindowOuter> dialog;
   aError = OpenInternal(aUrl, aName, aOptions,
                         true,             // aDialog
                         false,            // aContentModal
                         false,            // aCalledNoScript
                         false,            // aDoJSFixups
                         true,                // aNavigate
                         argvArray, nullptr,  // Arguments
-                        nullptr,          // aLoadInfo
+                        nullptr,          // aLoadState
                         false,            // aForceNoOpener
                         getter_AddRefs(dialog));
   return dialog.forget();
 }
 
 already_AddRefed<nsPIDOMWindowOuter>
 nsGlobalWindowOuter::GetFramesOuter()
 {
@@ -6932,17 +6932,17 @@ public:
 
 nsresult
 nsGlobalWindowOuter::OpenInternal(const nsAString& aUrl, const nsAString& aName,
                                   const nsAString& aOptions, bool aDialog,
                                   bool aContentModal, bool aCalledNoScript,
                                   bool aDoJSFixups, bool aNavigate,
                                   nsIArray *argv,
                                   nsISupports *aExtraArgument,
-                                  nsDocShellLoadInfo* aLoadInfo,
+                                  nsDocShellLoadState* aLoadState,
                                   bool aForceNoOpener,
                                   nsPIDOMWindowOuter **aReturn)
 {
 #ifdef DEBUG
   uint32_t argc = 0;
   if (argv)
       argv->GetLength(&argc);
 #endif
@@ -7081,17 +7081,17 @@ nsGlobalWindowOuter::OpenInternal(const 
       // We asserted at the top of this function that aNavigate is true for
       // !aCalledNoScript.
       rv = pwwatch->OpenWindow2(this, url.IsVoid() ? nullptr : url.get(),
                                 name_ptr,
                                 options_ptr, /* aCalledFromScript = */ true,
                                 aDialog, aNavigate, argv,
                                 isPopupSpamWindow,
                                 forceNoOpener,
-                                aLoadInfo,
+                                aLoadState,
                                 getter_AddRefs(domReturn));
     } else {
       // Force a system caller here so that the window watcher won't screw us
       // up.  We do NOT want this case looking at the JS context on the stack
       // when searching.  Compare comments on
       // nsIDOMWindow::OpenWindow and nsIWindowWatcher::OpenWindow.
 
       // Note: Because nsWindowWatcher is so broken, it's actually important
@@ -7104,17 +7104,17 @@ nsGlobalWindowOuter::OpenInternal(const 
       }
 
       rv = pwwatch->OpenWindow2(this, url.IsVoid() ? nullptr : url.get(),
                                 name_ptr,
                                 options_ptr, /* aCalledFromScript = */ false,
                                 aDialog, aNavigate, aExtraArgument,
                                 isPopupSpamWindow,
                                 forceNoOpener,
-                                aLoadInfo,
+                                aLoadState,
                                 getter_AddRefs(domReturn));
 
     }
   }
 
   NS_ENSURE_SUCCESS(rv, rv);
 
   // success!
--- a/dom/base/nsGlobalWindowOuter.h
+++ b/dom/base/nsGlobalWindowOuter.h
@@ -67,17 +67,17 @@ class nsIControllers;
 class nsIJSID;
 class nsIScriptContext;
 class nsIScriptTimeoutHandler;
 class nsITabChild;
 class nsITimeoutHandler;
 class nsIWebBrowserChrome;
 class mozIDOMWindowProxy;
 
-class nsDocShellLoadInfo;
+class nsDocShellLoadState;
 class nsDOMWindowList;
 class nsScreen;
 class nsHistory;
 class nsGlobalWindowObserver;
 class nsGlobalWindowInner;
 class nsDOMWindowUtils;
 class nsIIdleService;
 struct nsRect;
@@ -602,17 +602,17 @@ public:
   mozilla::dom::Element* GetFrameElement() override;
   already_AddRefed<nsPIDOMWindowOuter>
   OpenOuter(const nsAString& aUrl,
             const nsAString& aName,
             const nsAString& aOptions,
             mozilla::ErrorResult& aError);
   nsresult Open(const nsAString& aUrl, const nsAString& aName,
                 const nsAString& aOptions,
-                nsDocShellLoadInfo* aLoadInfo,
+                nsDocShellLoadState* aLoadState,
                 bool aForceNoOpener,
                 nsPIDOMWindowOuter **_retval) override;
   mozilla::dom::Navigator* GetNavigator() override;
 
 #if defined(MOZ_WIDGET_ANDROID)
   int16_t Orientation(mozilla::dom::CallerType aCallerType) const;
 #endif
 
@@ -874,17 +874,17 @@ private:
    *
    * @param argv The arguments to pass to the new window.  The first
    *        three args, if present, will be aUrl, aName, and aOptions.  So this
    *        param only matters if there are more than 3 arguments.
    *
    * @param aExtraArgument Another way to pass arguments in.  This is mutually
    *        exclusive with the argv approach.
    *
-   * @param aLoadInfo to be passed on along to the windowwatcher.
+   * @param aLoadState to be passed on along to the windowwatcher.
    *
    * @param aForceNoOpener if true, will act as if "noopener" were passed in
    *                       aOptions, but without affecting any other window
    *                       features.
    *
    * @param aReturn [out] The window that was opened, if any.  Will be null if
    *                      aForceNoOpener is true of if aOptions contains
    *                      "noopener".
@@ -896,17 +896,17 @@ private:
                         const nsAString& aOptions,
                         bool aDialog,
                         bool aContentModal,
                         bool aCalledNoScript,
                         bool aDoJSFixups,
                         bool aNavigate,
                         nsIArray *argv,
                         nsISupports *aExtraArgument,
-                        nsDocShellLoadInfo* aLoadInfo,
+                        nsDocShellLoadState* aLoadState,
                         bool aForceNoOpener,
                         nsPIDOMWindowOuter **aReturn);
 
   // Checks that the channel was loaded by the URI currently loaded in aDoc
   static bool SameLoadingURI(nsIDocument *aDoc, nsIChannel *aChannel);
 
 public:
   // Helper Functions
--- a/dom/base/nsPIDOMWindow.h
+++ b/dom/base/nsPIDOMWindow.h
@@ -26,17 +26,17 @@ class nsDOMOfflineResourceList;
 class nsDOMWindowList;
 class nsGlobalWindowInner;
 class nsGlobalWindowOuter;
 class nsIArray;
 class nsIChannel;
 class nsIContent;
 class nsICSSDeclaration;
 class nsIDocShell;
-class nsDocShellLoadInfo;
+class nsDocShellLoadState;
 class nsIDocument;
 class nsIPrincipal;
 class nsIScriptTimeoutHandler;
 class nsISerialEventTarget;
 class nsIURI;
 class nsPIDOMWindowInner;
 class nsPIDOMWindowOuter;
 class nsPIWindowRoot;
@@ -1116,22 +1116,22 @@ public:
 
   virtual nsresult GetPrompter(nsIPrompt** aPrompt) = 0;
   virtual nsresult GetControllers(nsIControllers** aControllers) = 0;
   virtual already_AddRefed<mozilla::dom::Selection> GetSelection() = 0;
   virtual already_AddRefed<nsPIDOMWindowOuter> GetOpener() = 0;
 
   virtual nsDOMWindowList* GetFrames() = 0;
 
-  // aLoadInfo will be passed on through to the windowwatcher.
+  // aLoadState will be passed on through to the windowwatcher.
   // aForceNoOpener will act just like a "noopener" feature in aOptions except
   //                will not affect any other window features.
   virtual nsresult Open(const nsAString& aUrl, const nsAString& aName,
                         const nsAString& aOptions,
-                        nsDocShellLoadInfo* aLoadInfo,
+                        nsDocShellLoadState* aLoadState,
                         bool aForceNoOpener,
                         nsPIDOMWindowOuter **_retval) = 0;
   virtual nsresult OpenDialog(const nsAString& aUrl, const nsAString& aName,
                               const nsAString& aOptions,
                               nsISupports* aExtraArgument,
                               nsPIDOMWindowOuter** _retval) = 0;
 
   virtual nsresult GetInnerWidth(int32_t* aWidth) = 0;
--- a/dom/clients/manager/ClientNavigateOpChild.cpp
+++ b/dom/clients/manager/ClientNavigateOpChild.cpp
@@ -4,17 +4,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "ClientNavigateOpChild.h"
 
 #include "ClientState.h"
 #include "mozilla/Unused.h"
 #include "nsIDocShell.h"
-#include "nsDocShellLoadInfo.h"
+#include "nsDocShellLoadState.h"
 #include "nsIWebNavigation.h"
 #include "nsIWebProgress.h"
 #include "nsIWebProgressListener.h"
 #include "nsNetUtil.h"
 #include "nsPIDOMWindow.h"
 #include "nsURLHelper.h"
 
 namespace mozilla {
@@ -231,23 +231,26 @@ ClientNavigateOpChild::DoNavigate(const 
 
   nsCOMPtr<nsIDocShell> docShell = window->GetDocShell();
   nsCOMPtr<nsIWebProgress> webProgress = do_GetInterface(docShell);
   if (!docShell || !webProgress) {
     ref = ClientOpPromise::CreateAndReject(NS_ERROR_DOM_INVALID_STATE_ERR, __func__);
     return ref.forget();
   }
 
-  RefPtr<nsDocShellLoadInfo> loadInfo = new nsDocShellLoadInfo();
+  RefPtr<nsDocShellLoadState> loadState = new nsDocShellLoadState();
 
-  loadInfo->SetTriggeringPrincipal(principal);
-  loadInfo->SetReferrerPolicy(doc->GetReferrerPolicy());
-  loadInfo->SetLoadType(LOAD_STOP_CONTENT);
-  loadInfo->SetSourceDocShell(docShell);
-  rv = docShell->LoadURI(url, loadInfo, nsIWebNavigation::LOAD_FLAGS_NONE, true);
+  loadState->SetTriggeringPrincipal(principal);
+  loadState->SetReferrerPolicy(doc->GetReferrerPolicy());
+  loadState->SetLoadType(LOAD_STOP_CONTENT);
+  loadState->SetSourceDocShell(docShell);
+  loadState->SetURI(url);
+  loadState->SetLoadFlags(nsIWebNavigation::LOAD_FLAGS_NONE);
+  loadState->SetFirstParty(true);
+  rv = docShell->LoadURI(loadState);
   if (NS_FAILED(rv)) {
     ref = ClientOpPromise::CreateAndReject(rv, __func__);
     return ref.forget();
   }
 
   RefPtr<ClientOpPromise::Private> promise =
     new ClientOpPromise::Private(__func__);
 
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -114,17 +114,17 @@
 #include <unistd.h>
 #endif
 #endif
 
 #include "mozilla/Unused.h"
 
 #include "mozInlineSpellChecker.h"
 #include "nsDocShell.h"
-#include "nsDocShellLoadInfo.h"
+#include "nsDocShellLoadState.h"
 #include "nsIConsoleListener.h"
 #include "nsIContentViewer.h"
 #include "nsICycleCollectorListener.h"
 #include "nsIIdlePeriod.h"
 #include "nsIDragService.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsIMemoryReporter.h"
 #include "nsIMemoryInfoDumper.h"
@@ -769,29 +769,29 @@ ContentChild::ProvideWindow(mozIDOMWindo
                             uint32_t aChromeFlags,
                             bool aCalledFromJS,
                             bool aPositionSpecified,
                             bool aSizeSpecified,
                             nsIURI* aURI,
                             const nsAString& aName,
                             const nsACString& aFeatures,
                             bool aForceNoOpener,
-                            nsDocShellLoadInfo* aLoadInfo,
+                            nsDocShellLoadState* aLoadState,
                             bool* aWindowIsNew,
                             mozIDOMWindowProxy** aReturn)
 {
   return ProvideWindowCommon(nullptr, aParent, false, aChromeFlags,
                              aCalledFromJS, aPositionSpecified,
                              aSizeSpecified, aURI, aName, aFeatures,
-                             aForceNoOpener, aLoadInfo, aWindowIsNew, aReturn);
+                             aForceNoOpener, aLoadState, aWindowIsNew, aReturn);
 }
 
 static nsresult
 GetCreateWindowParams(mozIDOMWindowProxy* aParent,
-                      nsDocShellLoadInfo* aLoadInfo,
+                      nsDocShellLoadState* aLoadState,
                       nsACString& aBaseURIString, float* aFullZoom,
                       uint32_t* aReferrerPolicy,
                       nsIPrincipal** aTriggeringPrincipal)
 {
   *aFullZoom = 1.0f;
   if (!aTriggeringPrincipal) {
     NS_ERROR("aTriggeringPrincipal is null");
     return NS_ERROR_FAILURE;
@@ -809,21 +809,21 @@ GetCreateWindowParams(mozIDOMWindowProxy
   nsCOMPtr<nsIURI> baseURI = doc->GetDocBaseURI();
   if (!baseURI) {
     NS_ERROR("nsIDocument didn't return a base URI");
     return NS_ERROR_FAILURE;
   }
 
   baseURI->GetSpec(aBaseURIString);
 
-  if (aLoadInfo) {
-    if (!aLoadInfo->SendReferrer()) {
+  if (aLoadState) {
+    if (!aLoadState->SendReferrer()) {
       *aReferrerPolicy = mozilla::net::RP_No_Referrer;
     } else {
-      *aReferrerPolicy = aLoadInfo->ReferrerPolicy();
+      *aReferrerPolicy = aLoadState->ReferrerPolicy();
     }
   }
 
   RefPtr<nsDocShell> openerDocShell =
     static_cast<nsDocShell*>(opener->GetDocShell());
   if (!openerDocShell) {
     return NS_OK;
   }
@@ -844,17 +844,17 @@ ContentChild::ProvideWindowCommon(TabChi
                                   uint32_t aChromeFlags,
                                   bool aCalledFromJS,
                                   bool aPositionSpecified,
                                   bool aSizeSpecified,
                                   nsIURI* aURI,
                                   const nsAString& aName,
                                   const nsACString& aFeatures,
                                   bool aForceNoOpener,
-                                  nsDocShellLoadInfo* aLoadInfo,
+                                  nsDocShellLoadState* aLoadState,
                                   bool* aWindowIsNew,
                                   mozIDOMWindowProxy** aReturn)
 {
   *aReturn = nullptr;
 
   nsAutoPtr<IPCTabContext> ipcContext;
   TabId openerTabId = TabId(0);
   nsAutoCString features(aFeatures);
@@ -891,17 +891,17 @@ ContentChild::ProvideWindowCommon(TabChi
 
   // If we're in a content process and we have noopener set, there's no reason
   // to load in our process, so let's load it elsewhere!
   if (loadInDifferentProcess) {
     nsAutoCString baseURIString;
     float fullZoom;
     nsCOMPtr<nsIPrincipal> triggeringPrincipal;
     uint32_t referrerPolicy = mozilla::net::RP_Unset;
-    rv = GetCreateWindowParams(aParent, aLoadInfo, baseURIString, &fullZoom,
+    rv = GetCreateWindowParams(aParent, aLoadState, baseURIString, &fullZoom,
                                &referrerPolicy,
                                getter_AddRefs(triggeringPrincipal));
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
 
     OptionalURIParams uriToLoad;
     SerializeURI(aURI, uriToLoad);
@@ -1105,17 +1105,17 @@ ContentChild::ProvideWindowCommon(TabChi
                                          NS_ConvertUTF8toUTF16(url),
                                          name, NS_ConvertUTF8toUTF16(features),
                                          std::move(resolve), std::move(reject));
   } else {
     nsAutoCString baseURIString;
     float fullZoom;
     nsCOMPtr<nsIPrincipal> triggeringPrincipal;
     uint32_t referrerPolicy = mozilla::net::RP_Unset;
-    rv = GetCreateWindowParams(aParent, aLoadInfo, baseURIString, &fullZoom,
+    rv = GetCreateWindowParams(aParent, aLoadState, baseURIString, &fullZoom,
                                &referrerPolicy,
                                getter_AddRefs(triggeringPrincipal));
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
 
     OptionalURIParams uriToLoad;
     if (aURI) {
--- a/dom/ipc/ContentChild.h
+++ b/dom/ipc/ContentChild.h
@@ -29,17 +29,17 @@
 
 struct ChromePackage;
 class nsIObserver;
 struct SubstitutionMapping;
 struct OverrideMapping;
 class nsIDomainPolicy;
 class nsIURIClassifierCallback;
 struct LookAndFeelInt;
-class nsDocShellLoadInfo;
+class nsDocShellLoadState;
 
 namespace mozilla {
 class RemoteSpellcheckEngineChild;
 class ChildProfilerController;
 
 using mozilla::loader::PScriptCacheChild;
 
 #if !defined(XP_WIN)
@@ -114,17 +114,17 @@ public:
                       uint32_t aChromeFlags,
                       bool aCalledFromJS,
                       bool aPositionSpecified,
                       bool aSizeSpecified,
                       nsIURI* aURI,
                       const nsAString& aName,
                       const nsACString& aFeatures,
                       bool aForceNoOpener,
-                      nsDocShellLoadInfo* aLoadInfo,
+                      nsDocShellLoadState* aLoadState,
                       bool* aWindowIsNew,
                       mozIDOMWindowProxy** aReturn);
 
   bool Init(MessageLoop* aIOLoop,
             base::ProcessId aParentPid,
             const char* aParentBuildID,
             IPC::Channel* aChannel,
             uint64_t aChildID,
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -119,17 +119,17 @@
 #include "nsCommandParams.h"
 #include "nsISHistory.h"
 #include "nsQueryObject.h"
 #include "nsIHttpChannel.h"
 #include "mozilla/dom/DocGroup.h"
 #include "nsString.h"
 #include "nsISupportsPrimitives.h"
 #include "mozilla/Telemetry.h"
-#include "nsDocShellLoadInfo.h"
+#include "nsDocShellLoadState.h"
 #include "nsWebBrowser.h"
 
 #ifdef XP_WIN
 #include "mozilla/plugins/PluginWidgetChild.h"
 #endif
 
 #ifdef NS_PRINTING
 #include "nsIPrintSession.h"
@@ -955,17 +955,17 @@ TabChild::GetInterface(const nsIID & aII
 
 NS_IMETHODIMP
 TabChild::ProvideWindow(mozIDOMWindowProxy* aParent,
                         uint32_t aChromeFlags,
                         bool aCalledFromJS,
                         bool aPositionSpecified, bool aSizeSpecified,
                         nsIURI* aURI, const nsAString& aName,
                         const nsACString& aFeatures, bool aForceNoOpener,
-                        nsDocShellLoadInfo* aLoadInfo, bool* aWindowIsNew,
+                        nsDocShellLoadState* aLoadState, bool* aWindowIsNew,
                         mozIDOMWindowProxy** aReturn)
 {
     *aReturn = nullptr;
 
     // If aParent is inside an <iframe mozbrowser> and this isn't a request to
     // open a modal-type window, we're going to create a new <iframe mozbrowser>
     // and return its window here.
     nsCOMPtr<nsIDocShell> docshell = do_GetInterface(aParent);
@@ -999,17 +999,17 @@ TabChild::ProvideWindow(mozIDOMWindowPro
                                    aChromeFlags,
                                    aCalledFromJS,
                                    aPositionSpecified,
                                    aSizeSpecified,
                                    aURI,
                                    aName,
                                    aFeatures,
                                    aForceNoOpener,
-                                   aLoadInfo,
+                                   aLoadState,
                                    aWindowIsNew,
                                    aReturn);
 }
 
 void
 TabChild::DestroyWindow()
 {
     if (mCoalescedMouseEventFlusher) {
--- a/toolkit/components/windowcreator/nsIWindowProvider.idl
+++ b/toolkit/components/windowcreator/nsIWindowProvider.idl
@@ -9,22 +9,22 @@
  * wish to provide a custom "new window" of their own (for example by returning
  * a new tab, an existing window, etc) instead of just having a real new
  * toplevel window open.
  */
 
 #include "nsISupports.idl"
 
 %{ C++
-class nsDocShellLoadInfo;
+class nsDocShellLoadState;
 %}
 
 interface mozIDOMWindowProxy;
 interface nsIURI;
-native nsDocShellLoadInfoPtr(nsDocShellLoadInfo*);
+native nsDocShellLoadStatePtr(nsDocShellLoadState*);
 
 /**
  * The nsIWindowProvider interface exists so that the window watcher's default
  * behavior of opening a new window can be easly modified.  When the window
  * watcher needs to open a new window, it will first check with the
  * nsIWindowProvider it gets from the parent window.  If there is no provider
  * or the provider does not provide a window, the window watcher will proceed
  * to actually open a new window.
@@ -71,17 +71,17 @@ interface nsIWindowProvider : nsISupport
    *        is provided solely to help the nsIWindowProvider implementation
    *        make decisions.
    *
    * @param aFeatures The feature string for the window being opened.  This may
    *        be empty.  The nsIWindowProvider implementation is allowed to apply
    *        the feature string to the window it returns in any way it sees fit.
    *        See the nsIWindowWatcher interface for details on feature strings.
    *
-   * @param aLoadInfo Specify setup information of the load in the new window
+   * @param aLoadState Specify setup information of the load in the new window
    *
    * @param aWindowIsNew [out] Whether the window being returned was just
    *        created by the window provider implementation.  This can be used by
    *        callers to keep track of which windows were opened by the user as
    *        opposed to being opened programmatically.  This should be set to
    *        false if the window being returned existed before the
    *        provideWindow() call.  The value of this out parameter is
    *        meaningless if provideWindow() returns null.
@@ -101,11 +101,11 @@ interface nsIWindowProvider : nsISupport
                                    in unsigned long aChromeFlags,
                                    in boolean aCalledFromJS,
                                    in boolean aPositionSpecified,
                                    in boolean aSizeSpecified,
                                    in nsIURI aURI,
                                    in AString aName,
                                    in AUTF8String aFeatures,
                                    in boolean aForceNoOpener,
-                                   in nsDocShellLoadInfoPtr aLoadInfo,
+                                   in nsDocShellLoadStatePtr aLoadState,
                                    out boolean aWindowIsNew);
 };
--- a/toolkit/components/windowwatcher/nsPIWindowWatcher.idl
+++ b/toolkit/components/windowwatcher/nsPIWindowWatcher.idl
@@ -6,27 +6,27 @@
 
 /* Private "control" methods on the Window Watcher. These are annoying
    bookkeeping methods, not part of the public (embedding) interface.
 */
 
 #include "nsISupports.idl"
 
 %{ C++
-class nsDocShellLoadInfo;
+class nsDocShellLoadState;
 %}
 
 interface mozIDOMWindowProxy;
 interface nsIDOMWindow;
 interface nsISimpleEnumerator;
 interface nsIWebBrowserChrome;
 interface nsIDocShellTreeItem;
 interface nsIArray;
 interface nsITabParent;
-native nsDocShellLoadInfoPtr(nsDocShellLoadInfo*);
+native nsDocShellLoadStatePtr(nsDocShellLoadState*);
 
 [uuid(d162f9c4-19d5-4723-931f-f1e51bfa9f68)]
 
 interface nsPIWindowWatcher : nsISupports
 {
   /** A window has been created. Add it to our list.
       @param aWindow the window to add
       @param aChrome the corresponding chrome window. The DOM window
@@ -61,18 +61,18 @@ interface nsPIWindowWatcher : nsISupport
              specified URL.
       @param aArgs Window argument
       @param aIsPopupSpam true if the window is a popup spam window; used for
                           popup blocker internals.
       @param aForceNoOpener If true, force noopener behavior.  This means not
                             looking for existing windows with the given name,
                             not setting an opener on the newly opened window,
                             and returning null from this method.
-      @param aLoadInfo if aNavigate is true, this allows the caller to pass in
-                       an nsIDocShellLoadInfo to use for the navigation.
+      @param aLoadState if aNavigate is true, this allows the caller to pass in
+                        an nsIDocShellLoadState to use for the navigation.
                        Callers can pass in null if they want the windowwatcher
                        to just construct a loadinfo itself.  If aNavigate is
                        false, this argument is ignored.
 
       @return the new window
 
       @note This method may examine the JS context stack for purposes of
             determining the security context to use for the search for a given
@@ -85,17 +85,17 @@ interface nsPIWindowWatcher : nsISupport
   mozIDOMWindowProxy openWindow2(in mozIDOMWindowProxy aParent, in string aUrl,
                                  in string aName, in string aFeatures,
                                  in boolean aCalledFromScript,
                                  in boolean aDialog,
                                  in boolean aNavigate,
                                  in nsISupports aArgs,
                                  in boolean aIsPopupSpam,
                                  in boolean aForceNoOpener,
-                                 in nsDocShellLoadInfoPtr aLoadInfo);
+                                 in nsDocShellLoadStatePtr aLoadState);
 
   /**
    * Opens a new window so that the window that aOpeningTab belongs to
    * is set as the parent window. The newly opened window will also
    * inherit load context information from aOpeningTab.
    *
    * @param aOpeningTab
    *        The nsITabParent that is requesting the new window be opened.
--- a/toolkit/components/windowwatcher/nsWindowWatcher.cpp
+++ b/toolkit/components/windowwatcher/nsWindowWatcher.cpp
@@ -17,17 +17,17 @@
 #include "plstr.h"
 
 #include "nsDocShell.h"
 #include "nsGlobalWindow.h"
 #include "nsHashPropertyBag.h"
 #include "nsIBaseWindow.h"
 #include "nsIBrowserDOMWindow.h"
 #include "nsIDocShell.h"
-#include "nsDocShellLoadInfo.h"
+#include "nsDocShellLoadState.h"
 #include "nsIDocShellTreeItem.h"
 #include "nsIDocShellTreeOwner.h"
 #include "nsIDocumentLoader.h"
 #include "nsIDocument.h"
 #include "nsIDOMWindow.h"
 #include "nsIDOMChromeWindow.h"
 #include "nsIPrompt.h"
 #include "nsIScriptObjectPrincipal.h"
@@ -320,17 +320,17 @@ nsWindowWatcher::OpenWindow(mozIDOMWindo
   }
   bool dialog = (argc != 0);
 
   return OpenWindowInternal(aParent, aUrl, aName, aFeatures,
                             /* calledFromJS = */ false, dialog,
                             /* navigate = */ true, argv,
                             /* aIsPopupSpam = */ false,
                             /* aForceNoOpener = */ false,
-                            /* aLoadInfo = */ nullptr,
+                            /* aLoadState = */ nullptr,
                             aResult);
 }
 
 struct SizeSpec
 {
   SizeSpec()
     : mLeft(0)
     , mTop(0)
@@ -386,17 +386,17 @@ nsWindowWatcher::OpenWindow2(mozIDOMWind
                              const char* aName,
                              const char* aFeatures,
                              bool aCalledFromScript,
                              bool aDialog,
                              bool aNavigate,
                              nsISupports* aArguments,
                              bool aIsPopupSpam,
                              bool aForceNoOpener,
-                             nsDocShellLoadInfo* aLoadInfo,
+                             nsDocShellLoadState* aLoadState,
                              mozIDOMWindowProxy** aResult)
 {
   nsCOMPtr<nsIArray> argv = ConvertArgsToArray(aArguments);
 
   uint32_t argc = 0;
   if (argv) {
     argv->GetLength(&argc);
   }
@@ -407,17 +407,17 @@ nsWindowWatcher::OpenWindow2(mozIDOMWind
   bool dialog = aDialog;
   if (!aCalledFromScript) {
     dialog = argc > 0;
   }
 
   return OpenWindowInternal(aParent, aUrl, aName, aFeatures,
                             aCalledFromScript, dialog,
                             aNavigate, argv, aIsPopupSpam,
-                            aForceNoOpener, aLoadInfo, aResult);
+                            aForceNoOpener, aLoadState, aResult);
 }
 
 // This static function checks if the aDocShell uses an UserContextId equal to
 // the userContextId of subjectPrincipal, if not null.
 static bool
 CheckUserContextCompatibility(nsIDocShell* aDocShell)
 {
   MOZ_ASSERT(aDocShell);
@@ -632,17 +632,17 @@ nsWindowWatcher::OpenWindowInternal(mozI
                                     const char* aName,
                                     const char* aFeatures,
                                     bool aCalledFromJS,
                                     bool aDialog,
                                     bool aNavigate,
                                     nsIArray* aArgv,
                                     bool aIsPopupSpam,
                                     bool aForceNoOpener,
-                                    nsDocShellLoadInfo* aLoadInfo,
+                                    nsDocShellLoadState* aLoadState,
                                     mozIDOMWindowProxy** aResult)
 {
   nsresult rv = NS_OK;
   bool isNewToplevelWindow = false;
   bool windowIsNew = false;
   bool windowNeedsName = false;
   bool windowIsModal = false;
   bool uriToLoadIsChrome = false;
@@ -816,17 +816,17 @@ nsWindowWatcher::OpenWindowInternal(mozI
       }
 
       if (provider) {
         nsCOMPtr<mozIDOMWindowProxy> newWindow;
         rv = provider->ProvideWindow(aParent, chromeFlags, aCalledFromJS,
                                      sizeSpec.PositionSpecified(),
                                      sizeSpec.SizeSpecified(),
                                      uriToLoad, name, features, aForceNoOpener,
-                                     aLoadInfo, &windowIsNew,
+                                     aLoadState, &windowIsNew,
                                      getter_AddRefs(newWindow));
 
         if (NS_SUCCEEDED(rv)) {
           GetWindowTreeItem(newWindow, getter_AddRefs(newDocShellItem));
           if (windowIsNew && newDocShellItem) {
             // Make sure to stop any loads happening in this window that the
             // window provider might have started.  Otherwise if our caller
             // manipulates the window it just opened and then the load
@@ -1113,38 +1113,38 @@ nsWindowWatcher::OpenWindowInternal(mozI
   } else if (windowIsNew) {
     nsCOMPtr<nsILoadContext> childContext = do_QueryInterface(newDocShellItem);
     if (childContext) {
       childContext->SetPrivateBrowsing(isPrivateBrowsingWindow);
       childContext->SetRemoteTabs(isRemoteWindow);
     }
   }
 
-  RefPtr<nsDocShellLoadInfo> loadInfo = aLoadInfo;
-  if (uriToLoad && aNavigate && !loadInfo) {
-    loadInfo = new nsDocShellLoadInfo();
+  RefPtr<nsDocShellLoadState> loadState = aLoadState;
+  if (uriToLoad && aNavigate && !loadState) {
+    loadState = new nsDocShellLoadState();
 
     if (subjectPrincipal) {
-      loadInfo->SetTriggeringPrincipal(subjectPrincipal);
+      loadState->SetTriggeringPrincipal(subjectPrincipal);
     }
 
     /* use the URL from the *extant* document, if any. The usual accessor
        GetDocument will synchronously create an about:blank document if
        it has no better answer, and we only care about a real document.
        Also using GetDocument to force document creation seems to
        screw up focus in the hidden window; see bug 36016.
     */
     nsCOMPtr<nsIDocument> doc = GetEntryDocument();
     if (!doc && parentWindow) {
       doc = parentWindow->GetExtantDoc();
     }
     if (doc) {
       // Set the referrer
-      loadInfo->SetReferrer(doc->GetDocumentURI());
-      loadInfo->SetReferrerPolicy(doc->GetReferrerPolicy());
+      loadState->SetReferrer(doc->GetDocumentURI());
+      loadState->SetReferrerPolicy(doc->GetReferrerPolicy());
     }
   }
 
   if (isNewToplevelWindow) {
     // Notify observers that the window is open and ready.
     // The window has not yet started to load a document.
     nsCOMPtr<nsIObserverService> obsSvc =
       mozilla::services::GetObserverService();
@@ -1176,23 +1176,23 @@ nsWindowWatcher::OpenWindowInternal(mozI
       props->SetPropertyAsInterface(NS_LITERAL_STRING("createdTabDocShell"), newDocShellItem);
 
       obsSvc->NotifyObservers(static_cast<nsIPropertyBag2*>(props),
                               "webNavigation-createdNavigationTarget-from-js", nullptr);
     }
   }
 
   if (uriToLoad && aNavigate) {
-    newDocShell->LoadURI(
-      uriToLoad,
-      loadInfo,
-      windowIsNew ?
+    loadState->SetURI(uriToLoad);
+    loadState->SetLoadFlags(windowIsNew ?
         static_cast<uint32_t>(nsIWebNavigation::LOAD_FLAGS_FIRST_LOAD) :
-        static_cast<uint32_t>(nsIWebNavigation::LOAD_FLAGS_NONE),
-      true);
+                            static_cast<uint32_t>(nsIWebNavigation::LOAD_FLAGS_NONE));
+    loadState->SetFirstParty(true);
+    // Should this pay attention to errors returned by LoadURI?
+    newDocShell->LoadURI(loadState);
   }
 
   // Copy the current session storage for the current domain. Don't perform the
   // copy if we're forcing noopener, however.
   if (!aForceNoOpener && subjectPrincipal && parentDocShell) {
     nsCOMPtr<nsIDOMStorageManager> parentStorageManager =
       do_QueryInterface(parentDocShell);
     nsCOMPtr<nsIDOMStorageManager> newStorageManager =
--- a/toolkit/components/windowwatcher/nsWindowWatcher.h
+++ b/toolkit/components/windowwatcher/nsWindowWatcher.h
@@ -83,17 +83,17 @@ protected:
                               const char* aName,
                               const char* aFeatures,
                               bool aCalledFromJS,
                               bool aDialog,
                               bool aNavigate,
                               nsIArray* aArgv,
                               bool aIsPopupSpam,
                               bool aForceNoOpener,
-                              nsDocShellLoadInfo* aLoadInfo,
+                              nsDocShellLoadState* aLoadState,
                               mozIDOMWindowProxy** aResult);
 
   static nsresult URIfromURL(const char* aURL,
                              mozIDOMWindowProxy* aParent,
                              nsIURI** aURI);
 
   static uint32_t CalculateChromeFlagsForChild(const nsACString& aFeaturesStr);
 
--- a/xpfe/appshell/nsContentTreeOwner.cpp
+++ b/xpfe/appshell/nsContentTreeOwner.cpp
@@ -28,17 +28,17 @@
 #include "nsIWebNavigation.h"
 #include "nsDocShellCID.h"
 #include "nsIExternalURLHandlerService.h"
 #include "nsIMIMEInfo.h"
 #include "nsIWidget.h"
 #include "nsWindowWatcher.h"
 #include "mozilla/BrowserElementParent.h"
 #include "mozilla/NullPrincipal.h"
-#include "nsDocShellLoadInfo.h"
+#include "nsDocShellLoadState.h"
 
 #include "nsIScriptObjectPrincipal.h"
 #include "nsIURI.h"
 #include "nsIDocument.h"
 #if defined(XP_MACOSX)
 #include "nsThreadUtils.h"
 #endif
 
@@ -761,17 +761,17 @@ nsContentTreeOwner::ProvideWindow(mozIDO
                                   uint32_t aChromeFlags,
                                   bool aCalledFromJS,
                                   bool aPositionSpecified,
                                   bool aSizeSpecified,
                                   nsIURI* aURI,
                                   const nsAString& aName,
                                   const nsACString& aFeatures,
                                   bool aForceNoOpener,
-                                  nsDocShellLoadInfo* aLoadInfo,
+                                  nsDocShellLoadState* aLoadState,
                                   bool* aWindowIsNew,
                                   mozIDOMWindowProxy** aReturn)
 {
   NS_ENSURE_ARG_POINTER(aParent);
 
   auto* parent = nsPIDOMWindowOuter::From(aParent);
 
   *aReturn = nullptr;