Bug 1348050 - Part 5: Mark channel as urgent-start for loading frame/iframe. r?baku, r?mayhemer draft
authorTom Tung <shes050117@gmail.com>
Tue, 02 May 2017 09:15:42 +0800
changeset 573903 3c899bdb730764fbcb3114d4c0fe4f678b4bd79e
parent 573902 257fd83a9d628c83534799acec36cd662b49a184
child 573904 a1dac52985413951df6153048c3da437c4dd6bb4
push id57530
push userttung@mozilla.com
push dateMon, 08 May 2017 03:47:16 +0000
reviewersbaku, mayhemer
bugs1348050
milestone55.0a1
Bug 1348050 - Part 5: Mark channel as urgent-start for loading frame/iframe. r?baku, r?mayhemer This part is mainly to set channel as urgent-start for loading frame/iframe. Since we create few runnables between the place to get src(FrameLoader) and the palce to create channel(DocShell), I chose to store the flag on FrameLoader and pass it to DocShell. MozReview-Commit-ID: 4bxTkATxeG5
docshell/base/nsDocShell.cpp
docshell/base/nsDocShell.h
docshell/base/nsIDocShell.idl
docshell/shistory/nsSHistory.cpp
dom/base/Location.cpp
dom/base/nsFrameLoader.cpp
dom/base/nsFrameLoader.h
dom/workers/ServiceWorkerWindowClient.cpp
toolkit/components/windowwatcher/nsWindowWatcher.cpp
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -1249,17 +1249,18 @@ nsDocShell::ConvertLoadTypeToDocShellLoa
 
   return docShellLoadType;
 }
 
 NS_IMETHODIMP
 nsDocShell::LoadURI(nsIURI* aURI,
                     nsIDocShellLoadInfo* aLoadInfo,
                     uint32_t aLoadFlags,
-                    bool aFirstParty)
+                    bool aFirstParty,
+                    bool aUseUrgentStartForChannel)
 {
   NS_PRECONDITION(aLoadInfo || (aLoadFlags & EXTRA_LOAD_FLAGS) == 0,
                   "Unexpected flags");
   NS_PRECONDITION((aLoadFlags & 0xf) == 0, "Should not have these flags set");
 
   // 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.
@@ -1583,16 +1584,17 @@ nsDocShell::LoadURI(nsIURI* aURI,
                       headersStream,
                       loadType,
                       nullptr, // No SHEntry
                       aFirstParty,
                       srcdoc,
                       sourceDocShell,
                       baseURI,
                       false,
+                      aUseUrgentStartForChannel,
                       nullptr,  // No nsIDocShell
                       nullptr); // No nsIRequest
 }
 
 NS_IMETHODIMP
 nsDocShell::LoadStream(nsIInputStream* aStream, nsIURI* aURI,
                        const nsACString& aContentType,
                        const nsACString& aContentCharset,
@@ -4881,17 +4883,18 @@ nsDocShell::LoadURIWithOptions(const cha
 
   if (fixupInfo) {
     nsAutoString searchProvider, keyword;
     fixupInfo->GetKeywordProviderName(searchProvider);
     fixupInfo->GetKeywordAsSent(keyword);
     MaybeNotifyKeywordSearchLoading(searchProvider, keyword);
   }
 
-  rv = LoadURI(uri, loadInfo, extraFlags, true);
+  rv = LoadURI(uri, loadInfo, extraFlags, true,
+               /* aUseUrgentStartForChannel */ false);
 
   // Save URI string in case it's needed later when
   // sending to search engine service in EndPageLoad()
   mOriginalUriString = uriString;
 
   return rv;
 }
 
@@ -5419,17 +5422,17 @@ nsDocShell::LoadErrorPage(nsIURI* aURI, 
   NS_ENSURE_SUCCESS(rv, rv);
 
   return InternalLoad(errorPageURI, nullptr, false, nullptr,
                       mozilla::net::RP_Unset,
                       nsContentUtils::GetSystemPrincipal(), nullptr,
                       INTERNAL_LOAD_FLAGS_NONE, EmptyString(),
                       nullptr, NullString(), nullptr, nullptr, LOAD_ERROR_PAGE,
                       nullptr, true, NullString(), this, nullptr, false,
-                      nullptr, nullptr);
+                      /* aUseUrgentStartForChannel */ false, nullptr, nullptr);
 }
 
 NS_IMETHODIMP
 nsDocShell::Reload(uint32_t aReloadFlags)
 {
   if (!IsNavigationAllowed()) {
     return NS_OK; // JS may not handle returning of an error code
   }
@@ -5517,16 +5520,17 @@ nsDocShell::Reload(uint32_t aReloadFlags
                       nullptr,         // No headers data
                       loadType,        // Load type
                       nullptr,         // No SHEntry
                       true,
                       srcdoc,          // srcdoc argument for iframe
                       this,            // For reloads we are the source
                       baseURI,
                       false,
+                      false,           // No urgent-start for channel
                       nullptr,         // No nsIDocShell
                       nullptr);        // No nsIRequest
   }
 
   return rv;
 }
 
 NS_IMETHODIMP
@@ -6855,17 +6859,18 @@ nsDocShell::ForceRefreshURI(nsIURI* aURI
   } else {
     loadInfo->SetLoadType(nsIDocShellLoadInfo::loadRefresh);
   }
 
   /*
    * LoadURI(...) will cancel all refresh timers... This causes the
    * Timer and its refreshData instance to be released...
    */
-  LoadURI(aURI, loadInfo, nsIWebNavigation::LOAD_FLAGS_NONE, true);
+  LoadURI(aURI, loadInfo, nsIWebNavigation::LOAD_FLAGS_NONE, true,
+          /* aUseUrgentStartForChannel */ false);
 
   return NS_OK;
 }
 
 nsresult
 nsDocShell::SetupRefreshURIFromHeader(nsIURI* aBaseURI,
                                       nsIPrincipal* aPrincipal,
                                       const nsACString& aHeader)
@@ -9682,17 +9687,18 @@ public:
                     nsIURI* aOriginalURI, bool aLoadReplace,
                     nsIURI* aReferrer, uint32_t aReferrerPolicy,
                     nsIPrincipal* aTriggeringPrincipal,
                     nsIPrincipal* aPrincipalToInherit, uint32_t aFlags,
                     const char* aTypeHint, nsIInputStream* aPostData,
                     nsIInputStream* aHeadersData, uint32_t aLoadType,
                     nsISHEntry* aSHEntry, bool aFirstParty,
                     const nsAString& aSrcdoc, nsIDocShell* aSourceDocShell,
-                    nsIURI* aBaseURI, bool aCheckForPrerender)
+                    nsIURI* aBaseURI, bool aCheckForPrerender,
+                    bool aUseUrgentStartForChannel)
     : mSrcdoc(aSrcdoc)
     , mDocShell(aDocShell)
     , mURI(aURI)
     , mOriginalURI(aOriginalURI)
     , mLoadReplace(aLoadReplace)
     , mReferrer(aReferrer)
     , mReferrerPolicy(aReferrerPolicy)
     , mTriggeringPrincipal(aTriggeringPrincipal)
@@ -9701,16 +9707,17 @@ public:
     , mHeadersData(aHeadersData)
     , mSHEntry(aSHEntry)
     , mFlags(aFlags)
     , mLoadType(aLoadType)
     , mFirstParty(aFirstParty)
     , mSourceDocShell(aSourceDocShell)
     , mBaseURI(aBaseURI)
     , mCheckForPrerender(aCheckForPrerender)
+    , mUseUrgentStartForChannel(aUseUrgentStartForChannel)
   {
     // Make sure to keep null things null as needed
     if (aTypeHint) {
       mTypeHint = aTypeHint;
     }
   }
 
   NS_IMETHOD
@@ -9720,17 +9727,18 @@ public:
                                    mLoadReplace,
                                    mReferrer,
                                    mReferrerPolicy,
                                    mTriggeringPrincipal, mPrincipalToInherit,
                                    mFlags, EmptyString(), mTypeHint.get(),
                                    NullString(), mPostData, mHeadersData,
                                    mLoadType, mSHEntry, mFirstParty,
                                    mSrcdoc, mSourceDocShell, mBaseURI,
-                                   mCheckForPrerender, nullptr, nullptr);
+                                   mCheckForPrerender,
+                                   mUseUrgentStartForChannel, nullptr, nullptr);
   }
 
 private:
   // Use IDL strings so .get() returns null by default
   nsXPIDLString mWindowTarget;
   nsXPIDLCString mTypeHint;
   nsString mSrcdoc;
 
@@ -9746,16 +9754,17 @@ private:
   nsCOMPtr<nsIInputStream> mHeadersData;
   nsCOMPtr<nsISHEntry> mSHEntry;
   uint32_t mFlags;
   uint32_t mLoadType;
   bool mFirstParty;
   nsCOMPtr<nsIDocShell> mSourceDocShell;
   nsCOMPtr<nsIURI> mBaseURI;
   bool mCheckForPrerender;
+  bool mUseUrgentStartForChannel;
 };
 
 /**
  * Returns true if we started an asynchronous load (i.e., from the network), but
  * the document we're loading there hasn't yet become this docshell's active
  * document.
  *
  * When JustStartedNetworkLoad is true, you should be careful about modifying
@@ -9796,16 +9805,17 @@ nsDocShell::InternalLoad(nsIURI* aURI,
                          nsIInputStream* aHeadersData,
                          uint32_t aLoadType,
                          nsISHEntry* aSHEntry,
                          bool aFirstParty,
                          const nsAString& aSrcdoc,
                          nsIDocShell* aSourceDocShell,
                          nsIURI* aBaseURI,
                          bool aCheckForPrerender,
+                         bool aUseUrgentStartForChannel,
                          nsIDocShell** aDocShell,
                          nsIRequest** aRequest)
 {
   MOZ_ASSERT(aTriggeringPrincipal, "need a valid TriggeringPrincipal");
 
   nsresult rv = NS_OK;
   mOriginalUriString.Truncate();
 
@@ -10174,16 +10184,17 @@ nsDocShell::InternalLoad(nsIURI* aURI,
                                         aHeadersData,
                                         aLoadType,
                                         aSHEntry,
                                         aFirstParty,
                                         aSrcdoc,
                                         aSourceDocShell,
                                         aBaseURI,
                                         aCheckForPrerender,
+                                        aUseUrgentStartForChannel,
                                         aDocShell,
                                         aRequest);
       if (rv == NS_ERROR_NO_CONTENT) {
         // XXXbz except we never reach this code!
         if (isNewWindow) {
           //
           // At this point, a new window has been created, but the
           // URI did not have any data associated with it...
@@ -10257,17 +10268,18 @@ nsDocShell::InternalLoad(nsIURI* aURI,
 
       // Do this asynchronously
       nsCOMPtr<nsIRunnable> ev =
         new InternalLoadEvent(this, aURI, aOriginalURI, aLoadReplace,
                               aReferrer, aReferrerPolicy,
                               aTriggeringPrincipal, principalToInherit,
                               aFlags, aTypeHint, aPostData, aHeadersData,
                               aLoadType, aSHEntry, aFirstParty, aSrcdoc,
-                              aSourceDocShell, aBaseURI, false);
+                              aSourceDocShell, aBaseURI, false,
+                              aUseUrgentStartForChannel);
       return DispatchToTabGroup("nsDocShell::InternalLoadEvent",
                                 TaskCategory::Other, ev.forget());
     }
 
     // Just ignore this load attempt
     return NS_OK;
   }
 
@@ -10641,17 +10653,18 @@ nsDocShell::InternalLoad(nsIURI* aURI,
 
   if (browserChrome3 && aCheckForPrerender) {
     nsCOMPtr<nsIRunnable> ev =
       new InternalLoadEvent(this, aURI, aOriginalURI, aLoadReplace,
                             aReferrer, aReferrerPolicy,
                             aTriggeringPrincipal, principalToInherit,
                             aFlags, aTypeHint, aPostData, aHeadersData,
                             aLoadType, aSHEntry, aFirstParty, aSrcdoc,
-                            aSourceDocShell, aBaseURI, false);
+                            aSourceDocShell, aBaseURI, false,
+                            /* aUseUrgentStartForChannel */ false);
     // We don't need any success handler since in that case
     // OnPartialSHistoryDeactive would be called, and it would ensure
     // docshell loads about:blank.
     bool shouldSwitch = false;
     rv = browserChrome3->ShouldSwitchToPrerenderedDocument(
       aURI, mCurrentURI, nullptr, ev, &shouldSwitch);
     if (NS_SUCCEEDED(rv) && shouldSwitch) {
       return NS_OK;
@@ -10805,17 +10818,17 @@ nsDocShell::InternalLoad(nsIURI* aURI,
                  !(aFlags & INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER),
                  aReferrerPolicy,
                  aTriggeringPrincipal, principalToInherit, aTypeHint,
                  aFileName, aPostData, aHeadersData,
                  aFirstParty, aDocShell, getter_AddRefs(req),
                  (aFlags & INTERNAL_LOAD_FLAGS_FIRST_LOAD) != 0,
                  (aFlags & INTERNAL_LOAD_FLAGS_BYPASS_CLASSIFIER) != 0,
                  (aFlags & INTERNAL_LOAD_FLAGS_FORCE_ALLOW_COOKIES) != 0,
-                 srcdoc, aBaseURI, contentType);
+                 srcdoc, aBaseURI, contentType, aUseUrgentStartForChannel);
   if (req && aRequest) {
     NS_ADDREF(*aRequest = req);
   }
 
   if (NS_FAILED(rv)) {
     nsCOMPtr<nsIChannel> chan(do_QueryInterface(req));
     if (DisplayLoadError(rv, aURI, nullptr, chan) &&
         (aFlags & LOAD_FLAGS_ERROR_LOAD_CHANGES_RV) != 0) {
@@ -10893,17 +10906,18 @@ nsDocShell::DoURILoad(nsIURI* aURI,
                       bool aFirstParty,
                       nsIDocShell** aDocShell,
                       nsIRequest** aRequest,
                       bool aIsNewWindowTarget,
                       bool aBypassClassifier,
                       bool aForceAllowCookies,
                       const nsAString& aSrcdoc,
                       nsIURI* aBaseURI,
-                      nsContentPolicyType aContentPolicyType)
+                      nsContentPolicyType aContentPolicyType,
+                      bool aUseUrgentStartForChannel)
 {
   // Double-check that we're still around to load this URI.
   if (mIsBeingDestroyed) {
     // Return NS_OK despite not doing anything to avoid throwing exceptions from
     // nsLocation::SetHref if the unload handler of the existing page tears us
     // down.
     return NS_OK;
   }
@@ -11323,16 +11337,27 @@ nsDocShell::DoURILoad(nsIURI* aURI,
       rv = AddHeadersToChannel(aHeadersData, httpChannel);
     }
     // Set the referrer explicitly
     if (aReferrerURI && aSendReferrer) {
       // Referrer is currenly only set for link clicks here.
       rv = httpChannel->SetReferrerWithPolicy(aReferrerURI, aReferrerPolicy);
       MOZ_ASSERT(NS_SUCCEEDED(rv));
     }
+
+    // Mark the http channel as UrgentStart for top level document loading
+    // in active tab.
+    if (aUseUrgentStartForChannel ||
+        (isTopLevelDoc &&
+         (mIsActive || (mLoadType & (LOAD_CMD_NORMAL | LOAD_CMD_HISTORY))))) {
+      nsCOMPtr<nsIClassOfService> cos(do_QueryInterface(channel));
+      if (cos) {
+        cos->AddClassFlags(nsIClassOfService::UrgentStart);
+      }
+    }
   }
 
   nsCOMPtr<nsIScriptChannel> scriptChannel = do_QueryInterface(channel);
   if (scriptChannel) {
     // Allow execution against our context if the principals match
     scriptChannel->SetExecutionPolicy(nsIScriptChannel::EXECUTE_NORMAL);
   }
 
@@ -11352,27 +11377,16 @@ nsDocShell::DoURILoad(nsIURI* aURI,
     if (IsFrame() && win) {
       nsCOMPtr<Element> frameElement = win->GetFrameElementInternal();
       if (frameElement) {
         timedChannel->SetInitiatorType(frameElement->LocalName());
       }
     }
   }
 
-  // Mark the http channel as UrgentStart for top level document loading
-  // in active tab.
-  if (mIsActive || (mLoadType & (LOAD_CMD_NORMAL | LOAD_CMD_HISTORY))) {
-    if (httpChannel && isTopLevelDoc) {
-      nsCOMPtr<nsIClassOfService> cos(do_QueryInterface(channel));
-      if (cos) {
-        cos->AddClassFlags(nsIClassOfService::UrgentStart);
-      }
-    }
-  }
-
   rv = DoChannelLoad(channel, uriLoader, aBypassClassifier);
 
   //
   // If the channel load failed, we failed and nsIWebProgress just ain't
   // gonna happen.
   //
   if (NS_SUCCEEDED(rv)) {
     if (aDocShell) {
@@ -12718,16 +12732,17 @@ nsDocShell::LoadHistoryEntry(nsISHEntry*
                     nullptr,            // No headers stream
                     aLoadType,          // Load type
                     aEntry,             // SHEntry
                     true,
                     srcdoc,
                     nullptr,            // Source docshell, see comment above
                     baseURI,
                     false,
+                    false,              // No urgent-start for channel
                     nullptr,            // No nsIDocShell
                     nullptr);           // No nsIRequest
   return rv;
 }
 
 NS_IMETHODIMP
 nsDocShell::GetShouldSaveLayoutState(bool* aShould)
 {
@@ -14270,16 +14285,17 @@ nsDocShell::OnLinkClickSync(nsIContent* 
                              aHeadersDataStream,        // Headers stream
                              LOAD_LINK,                 // Load type
                              nullptr,                   // No SHEntry
                              true,                      // first party site
                              NullString(),              // No srcdoc
                              this,                      // We are the source
                              nullptr,                   // baseURI not needed
                              true,                      // Check for prerendered doc
+                             true,                      // urgent-start
                              aDocShell,                 // DocShell out-param
                              aRequest);                 // Request out-param
   if (NS_SUCCEEDED(rv)) {
     DispatchPings(this, aContent, aURI, referer, refererPolicy);
   }
   return rv;
 }
 
--- a/docshell/base/nsDocShell.h
+++ b/docshell/base/nsDocShell.h
@@ -383,17 +383,18 @@ protected:
                      bool aFirstParty,
                      nsIDocShell** aDocShell,
                      nsIRequest** aRequest,
                      bool aIsNewWindowTarget,
                      bool aBypassClassifier,
                      bool aForceAllowCookies,
                      const nsAString& aSrcdoc,
                      nsIURI* aBaseURI,
-                     nsContentPolicyType aContentPolicyType);
+                     nsContentPolicyType aContentPolicyType,
+                     bool aUseUrgentStartForChannel);
   nsresult AddHeadersToChannel(nsIInputStream* aHeadersData,
                                nsIChannel* aChannel);
   nsresult DoChannelLoad(nsIChannel* aChannel,
                          nsIURILoader* aURILoader,
                          bool aBypassClassifier);
 
   nsresult ScrollToAnchor(bool aCurHasRef,
                           bool aNewHasRef,
--- a/docshell/base/nsIDocShell.idl
+++ b/docshell/base/nsIDocShell.idl
@@ -63,21 +63,28 @@ interface nsIDocShell : nsIDocShellTreeI
    *                     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 aUrgentStartForChannel
+   *                   - The flag to mark the channel as urgent-start
+   *                     when it is initiated by user interaction.
+   *                     The urgent-start classification will tell the
+   *                     network requests scheduler to perform it with
+   *                     the highest priority.
    */
   [noscript]void loadURI(in nsIURI uri,
                          in nsIDocShellLoadInfo loadInfo,
                          in unsigned long aLoadFlags,
-                         in boolean firstParty);
+                         in boolean firstParty,
+                         in boolean aUseUrgentStartForChannel);
 
   /**
    * Loads a given stream. This will give priority to loading the requested
    * stream in the object implementing this interface. If it can't be loaded
    * here however, the URL dispatched will go through its normal process of
    * content loading.
    *
    * @param aStream         - The input stream that provides access to the data
@@ -166,16 +173,22 @@ interface nsIDocShell : nsIDocShellTreeI
    * @param aSHEntry             - Active Session History entry (if loading from SH)
    * @param aSrcdoc                When INTERNAL_LOAD_FLAGS_IS_SRCDOC is set, the
    *                               contents of this parameter will be loaded instead
    *                               of aURI.
    * @param aSourceDocShell      - The source browsing context for the navigation.
    * @param aBaseURI             - The base URI to be used for the load.  Set in
    *                               srcdoc loads as it cannot otherwise be inferred
    *                               in certain situations such as view-source.
+   * @param aUrgentStartForChannel
+   *                             - The flag to mark the channel as urgent-start
+   *                               when it is initiated by user interaction.
+   *                               The urgent-start classification will tell the
+   *                               network requests scheduler to perform it with
+   *                               the highest priority.
    */
   [noscript]void internalLoad(in nsIURI aURI,
                               in nsIURI aOriginalURI,
                               in boolean aLoadReplace,
                               in nsIURI aReferrer,
                               in unsigned long aReferrerPolicy,
                               in nsIPrincipal aTriggeringPrincipal,
                               in nsIPrincipal aPrincipalToInherit,
@@ -187,16 +200,17 @@ interface nsIDocShell : nsIDocShellTreeI
                               in nsIInputStream aHeadersStream,
                               in unsigned long aLoadFlags,
                               in nsISHEntry aSHEntry,
                               in boolean aFirstParty,
                               in AString aSrcdoc,
                               in nsIDocShell aSourceDocShell,
                               in nsIURI aBaseURI,
                               in boolean aCheckForPrerender,
+                              in boolean aUseUrgentStartForChannel,
                               out nsIDocShell aDocShell,
                               out nsIRequest aRequest);
 
   /**
    * Do either a history.pushState() or history.replaceState() operation,
    * depending on the value of aReplace.
    */
   [implicit_jscontext]
--- a/docshell/shistory/nsSHistory.cpp
+++ b/docshell/shistory/nsSHistory.cpp
@@ -1915,17 +1915,18 @@ nsSHistory::InitiateLoad(nsISHEntry* aFr
   bool loadReplace;
   aFrameEntry->GetLoadReplace(&loadReplace);
   loadInfo->SetLoadReplace(loadReplace);
 
   nsCOMPtr<nsIURI> nextURI;
   aFrameEntry->GetURI(getter_AddRefs(nextURI));
   // Time   to initiate a document load
   return aFrameDS->LoadURI(nextURI, loadInfo,
-                           nsIWebNavigation::LOAD_FLAGS_NONE, false);
+                           nsIWebNavigation::LOAD_FLAGS_NONE, false,
+                           /* aUseUrgentStartForChannel */ false);
 
 }
 
 NS_IMETHODIMP
 nsSHistory::SetRootDocShell(nsIDocShell* aDocShell)
 {
   mRootDocShell = aDocShell;
 
--- a/dom/base/Location.cpp
+++ b/dom/base/Location.cpp
@@ -281,17 +281,18 @@ Location::SetURI(nsIURI* aURI, bool aRep
     // 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());
     }
 
     return docShell->LoadURI(aURI, loadInfo,
-                             nsIWebNavigation::LOAD_FLAGS_NONE, true);
+                             nsIWebNavigation::LOAD_FLAGS_NONE, true,
+                             /* aUseUrgentStartForChannel */ false);
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 Location::GetHash(nsAString& aHash)
 {
--- a/dom/base/nsFrameLoader.cpp
+++ b/dom/base/nsFrameLoader.cpp
@@ -174,16 +174,17 @@ nsFrameLoader::nsFrameLoader(Element* aO
   , mHideCalled(false)
   , mNetworkCreated(aNetworkCreated)
   , mRemoteBrowserShown(false)
   , mRemoteFrame(false)
   , mClipSubdocument(true)
   , mClampScrollPosition(true)
   , mObservingOwnerContent(false)
   , mVisible(true)
+  , mUseUrgentStartForChannel(false)
 {
   mRemoteFrame = ShouldUseRemoteProcess();
   MOZ_ASSERT(!mRemoteFrame || !aOpener,
              "Cannot pass aOpener for a remote frame!");
 }
 
 nsFrameLoader::~nsFrameLoader()
 {
@@ -249,16 +250,18 @@ nsFrameLoader::LoadFrame()
       // then we will not use 'about:blank' as fallback but return early without
       // starting a load if no 'src' attribute is given (or it's empty).
       if (mOwnerContent->IsXULElement() &&
           mOwnerContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::nodefaultsrc,
                                      nsGkAtoms::_true, eCaseMatters)) {
         return NS_OK;
       }
       src.AssignLiteral("about:blank");
+    } else {
+      mUseUrgentStartForChannel = EventStateManager::IsHandlingUserInput();
     }
   }
 
   nsIDocument* doc = mOwnerContent->OwnerDoc();
   if (doc->IsStaticDocument()) {
     return NS_OK;
   }
 
@@ -867,17 +870,21 @@ nsFrameLoader::ReallyStartLoadingInterna
     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);
+  rv = mDocShell->LoadURI(uriToLoad,
+                          loadInfo,
+                          flags,
+                          /* aFirstParty */ false,
+                          mUseUrgentStartForChannel);
   mNeedsAsyncDestroy = tmpState;
   mURIToLoad = nullptr;
   NS_ENSURE_SUCCESS(rv, rv);
 
   return NS_OK;
 }
 
 nsresult
--- a/dom/base/nsFrameLoader.h
+++ b/dom/base/nsFrameLoader.h
@@ -375,11 +375,13 @@ private:
   bool mClampScrollPosition : 1;
   bool mObservingOwnerContent : 1;
 
   // Backs nsIFrameLoader::{Get,Set}Visible.  Visibility state here relates to
   // whether this frameloader's <iframe mozbrowser> is setVisible(true)'ed, and
   // doesn't necessarily correlate with docshell/document visibility.
   bool mVisible : 1;
   bool mFreshProcess : 1;
+
+  bool mUseUrgentStartForChannel : 1;
 };
 
 #endif
--- a/dom/workers/ServiceWorkerWindowClient.cpp
+++ b/dom/workers/ServiceWorkerWindowClient.cpp
@@ -497,17 +497,18 @@ private:
       return NS_ERROR_TYPE_ERR;
     }
 
     loadInfo->SetTriggeringPrincipal(aPrincipal);
     loadInfo->SetReferrerPolicy(doc->GetReferrerPolicy());
     loadInfo->SetLoadType(nsIDocShellLoadInfo::loadStopContent);
     loadInfo->SetSourceDocShell(docShell);
     rv =
-      docShell->LoadURI(aUrl, loadInfo, nsIWebNavigation::LOAD_FLAGS_NONE, true);
+      docShell->LoadURI(aUrl, loadInfo, nsIWebNavigation::LOAD_FLAGS_NONE, true,
+                        /* aUseUrgentStartForChannel */ false);
 
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return NS_ERROR_TYPE_ERR;
     }
 
     *aWindow = window;
     return NS_OK;
   }
--- a/toolkit/components/windowwatcher/nsWindowWatcher.cpp
+++ b/toolkit/components/windowwatcher/nsWindowWatcher.cpp
@@ -1240,17 +1240,18 @@ nsWindowWatcher::OpenWindowInternal(mozI
 
   if (uriToLoad && aNavigate) {
     newDocShell->LoadURI(
       uriToLoad,
       loadInfo,
       windowIsNew ?
         static_cast<uint32_t>(nsIWebNavigation::LOAD_FLAGS_FIRST_LOAD) :
         static_cast<uint32_t>(nsIWebNavigation::LOAD_FLAGS_NONE),
-      true);
+      true,
+      /* aUseUrgentStartForChannel */ false);
   }
 
   // Copy the current session storage for the current domain.
   if (subjectPrincipal && parentDocShell) {
     nsCOMPtr<nsIDOMStorageManager> parentStorageManager =
       do_QueryInterface(parentDocShell);
     nsCOMPtr<nsIDOMStorageManager> newStorageManager =
       do_QueryInterface(newDocShell);