Browse Source

docshell backports

Ian Neal 7 months ago
parent
commit
45f6a6f5f0

+ 59 - 0
mozilla-release/patches/1345433-1-59a1.patch

@@ -0,0 +1,59 @@
+# HG changeset patch
+# User Thomas Nguyen <tnguyen@mozilla.com>
+# Date 1508753668 -28800
+# Node ID 1294e490afc2d16596baa7497dd4c758864f9afc
+# Parent  f57e0b8c5b994f8ef62b81af5ab0b29f5c6ca0c9
+Bug 1345433 - Bring back assertion that history entries need a valid triggeringPrincipal r=JanH,smaug
+
+MozReview-Commit-ID: 9GfGIxkqfhM
+
+diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp
+--- a/docshell/base/nsDocShell.cpp
++++ b/docshell/base/nsDocShell.cpp
+@@ -12917,18 +12917,20 @@ nsDocShell::LoadHistoryEntry(nsISHEntry*
+   if (isSrcdoc) {
+     aEntry->GetSrcdocData(srcdoc);
+     aEntry->GetBaseURI(getter_AddRefs(baseURI));
+     flags |= INTERNAL_LOAD_FLAGS_IS_SRCDOC;
+   } else {
+     srcdoc = VoidString();
+   }
+ 
++  // If there is no valid triggeringPrincipal, we deny the load
++  MOZ_ASSERT(triggeringPrincipal, "need a valid triggeringPrincipal to load from history");
+   if (!triggeringPrincipal) {
+-    triggeringPrincipal = nsContentUtils::GetSystemPrincipal();
++    return NS_ERROR_FAILURE;
+   }
+ 
+   // Passing nullptr as aSourceDocShell gives the same behaviour as before
+   // aSourceDocShell was introduced. According to spec we should be passing
+   // the source browsing context that was used when the history entry was
+   // first created. bug 947716 has been created to address this issue.
+   Maybe<nsCOMPtr<nsIURI>> emplacedResultPrincipalURI;
+   emplacedResultPrincipalURI.emplace(Move(resultPrincipalURI));
+diff --git a/docshell/shistory/nsSHEntry.cpp b/docshell/shistory/nsSHEntry.cpp
+--- a/docshell/shistory/nsSHEntry.cpp
++++ b/docshell/shistory/nsSHEntry.cpp
+@@ -545,16 +545,21 @@ nsSHEntry::GetTriggeringPrincipal(nsIPri
+ {
+   NS_IF_ADDREF(*aTriggeringPrincipal = mShared->mTriggeringPrincipal);
+   return NS_OK;
+ }
+ 
+ NS_IMETHODIMP
+ nsSHEntry::SetTriggeringPrincipal(nsIPrincipal* aTriggeringPrincipal)
+ {
++  MOZ_ASSERT(aTriggeringPrincipal, "need a valid triggeringPrincipal");
++  if (!aTriggeringPrincipal) {
++    return NS_ERROR_FAILURE;
++  }
++
+   mShared->mTriggeringPrincipal = aTriggeringPrincipal;
+   return NS_OK;
+ }
+ 
+ NS_IMETHODIMP
+ nsSHEntry::GetPrincipalToInherit(nsIPrincipal** aPrincipalToInherit)
+ {
+   NS_IF_ADDREF(*aPrincipalToInherit = mShared->mPrincipalToInherit);

+ 156 - 0
mozilla-release/patches/1345433-2-59a1.patch

@@ -0,0 +1,156 @@
+# HG changeset patch
+# User Thomas Nguyen <tnguyen@mozilla.com>
+# Date 1508753740 -28800
+# Node ID 166fb0b613592e18893c0d825dd5332c6185b2ce
+# Parent  e33e08f4af4595cd4bc35a74954414b836fc6a03
+Bug 1345433 - Ensure tests load pass valid triggeringPrincipal. r=ckerschb,JanH
+
+MozReview-Commit-ID: LWcP7drDPwL
+
+diff --git a/browser/components/extensions/test/browser/browser_ext_tabs_discarded.js b/browser/components/extensions/test/browser/browser_ext_tabs_discarded.js
+--- a/browser/components/extensions/test/browser/browser_ext_tabs_discarded.js
++++ b/browser/components/extensions/test/browser/browser_ext_tabs_discarded.js
+@@ -1,14 +1,17 @@
+ /* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
+ /* vim: set sts=2 sw=2 et tw=80: */
+ /* global gBrowser SessionStore */
+ "use strict";
+ 
+-let lazyTabState = {entries: [{url: "http://example.com/", title: "Example Domain"}]};
++const {Utils} = Cu.import("resource://gre/modules/sessionstore/Utils.jsm", {});
++const triggeringPrincipal_base64 = Utils.SERIALIZED_SYSTEMPRINCIPAL;
++
++let lazyTabState = {entries: [{url: "http://example.com/", triggeringPrincipal_base64, title: "Example Domain"}]};
+ 
+ add_task(async function test_discarded() {
+   let extension = ExtensionTestUtils.loadExtension({
+     manifest: {
+       "permissions": ["tabs"],
+     },
+ 
+     background: async function() {
+diff --git a/browser/components/extensions/test/browser/browser_ext_tabs_lazy.js b/browser/components/extensions/test/browser/browser_ext_tabs_lazy.js
+--- a/browser/components/extensions/test/browser/browser_ext_tabs_lazy.js
++++ b/browser/components/extensions/test/browser/browser_ext_tabs_lazy.js
+@@ -1,15 +1,18 @@
+ "use strict";
+ 
++const {Utils} = Cu.import("resource://gre/modules/sessionstore/Utils.jsm", {});
++const triggeringPrincipal_base64 = Utils.SERIALIZED_SYSTEMPRINCIPAL;
++
+ const SESSION = {
+   windows: [{
+     tabs: [
+-      {entries: [{url: "about:blank"}]},
+-      {entries: [{url: "https://example.com/"}]},
++      {entries: [{url: "about:blank", triggeringPrincipal_base64}]},
++      {entries: [{url: "https://example.com/", triggeringPrincipal_base64}]},
+     ],
+   }],
+ };
+ 
+ add_task(async function() {
+   SessionStore.setBrowserState(JSON.stringify(SESSION));
+   const tab = gBrowser.tabs[1];
+ 
+diff --git a/browser/components/sessionstore/test/browser_906076_lazy_tabs.js b/browser/components/sessionstore/test/browser_906076_lazy_tabs.js
+--- a/browser/components/sessionstore/test/browser_906076_lazy_tabs.js
++++ b/browser/components/sessionstore/test/browser_906076_lazy_tabs.js
+@@ -1,32 +1,32 @@
+ /* Any copyright is dedicated to the Public Domain.
+    http://creativecommons.org/publicdomain/zero/1.0/ */
+ 
+ const TEST_STATE = {
+   windows: [{
+     tabs: [
+-      { entries: [{ url: "http://example.com" }] },
+-      { entries: [{ url: "http://example.com" }] },
+-      { entries: [{ url: "http://example.com" }] },
+-      { entries: [{ url: "http://example.com" }] },
+-      { entries: [{ url: "http://example.com" }] },
+-      { entries: [{ url: "http://example.com" }] },
+-      { entries: [{ url: "http://example.com" }] },
+-      { entries: [{ url: "http://example.com" }] },
+-      { entries: [{ url: "http://example.com" }] },
+-      { entries: [{ url: "http://example.com" }] },
++      { entries: [{ url: "http://example.com", triggeringPrincipal_base64 }] },
++      { entries: [{ url: "http://example.com", triggeringPrincipal_base64 }] },
++      { entries: [{ url: "http://example.com", triggeringPrincipal_base64 }] },
++      { entries: [{ url: "http://example.com", triggeringPrincipal_base64 }] },
++      { entries: [{ url: "http://example.com", triggeringPrincipal_base64 }] },
++      { entries: [{ url: "http://example.com", triggeringPrincipal_base64 }] },
++      { entries: [{ url: "http://example.com", triggeringPrincipal_base64 }] },
++      { entries: [{ url: "http://example.com", triggeringPrincipal_base64 }] },
++      { entries: [{ url: "http://example.com", triggeringPrincipal_base64 }] },
++      { entries: [{ url: "http://example.com", triggeringPrincipal_base64 }] },
+     ]
+   }]
+ };
+ 
+ const TEST_STATE_2 = {
+   windows: [{
+     tabs: [
+-      { entries: [{ url: "about:robots" }]
++      { entries: [{ url: "about:robots", triggeringPrincipal_base64 }]
+       },
+       { entries: [],
+         userTypedValue: "http://example.com",
+         userTypedClear: 1
+       }
+     ]
+   }]
+ };
+diff --git a/browser/components/sessionstore/test/browser_tab_label_during_restore.js b/browser/components/sessionstore/test/browser_tab_label_during_restore.js
+--- a/browser/components/sessionstore/test/browser_tab_label_during_restore.js
++++ b/browser/components/sessionstore/test/browser_tab_label_during_restore.js
+@@ -35,20 +35,20 @@ add_task(async function() {
+     };
+   }
+ 
+   info("setting test browser state");
+   let browserLoadedPromise = BrowserTestUtils.firstBrowserLoaded(window, false);
+   await promiseBrowserState({
+     windows: [{
+       tabs: [
+-        { entries: [{ url: REMOTE_URL }] },
+-        { entries: [{ url: ABOUT_ROBOTS_URI }] },
+-        { entries: [{ url: REMOTE_URL }] },
+-        { entries: [{ url: NO_TITLE_URL }] },
++        { entries: [{ url: REMOTE_URL, triggeringPrincipal_base64 }] },
++        { entries: [{ url: ABOUT_ROBOTS_URI, triggeringPrincipal_base64 }] },
++        { entries: [{ url: REMOTE_URL, triggeringPrincipal_base64 }] },
++        { entries: [{ url: NO_TITLE_URL, triggeringPrincipal_base64 }] },
+       ]
+     }]
+   });
+   let [tab1, tab2, tab3, tab4] = gBrowser.tabs;
+   is(gBrowser.selectedTab, tab1, "first tab is selected");
+ 
+   await browserLoadedPromise;
+   const REMOTE_TITLE = tab1.linkedBrowser.contentTitle;
+diff --git a/devtools/client/scratchpad/test/browser_scratchpad_sessions.js b/devtools/client/scratchpad/test/browser_scratchpad_sessions.js
+--- a/devtools/client/scratchpad/test/browser_scratchpad_sessions.js
++++ b/devtools/client/scratchpad/test/browser_scratchpad_sessions.js
+@@ -1,20 +1,20 @@
+  /* Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/ */
+ "use strict";
+ 
+ const {Utils} = ChromeUtils.import("resource://gre/modules/sessionstore/Utils.jsm", {});
+-const triggeringPrincipalBase64 = Utils.SERIALIZED_SYSTEMPRINCIPAL;
++const triggeringPrincipal_base64 = Utils.SERIALIZED_SYSTEMPRINCIPAL;
+ const ss = Cc["@mozilla.org/browser/sessionstore;1"].getService(Ci.nsISessionStore);
+ 
+ const testState = {
+   windows: [{
+     tabs: [
+-      { entries: [{ url: "about:blank", triggeringPrincipalBase64 }] },
++      { entries: [{ url: "about:blank", triggeringPrincipal_base64 }] },
+     ]
+   }],
+   scratchpads: [
+     { text: "text1", executionContext: 1 },
+     { text: "", executionContext: 2, filename: "test.js" }
+   ]
+ };
+ 

+ 657 - 0
mozilla-release/patches/1406161-1-59a1.patch

@@ -0,0 +1,657 @@
+# HG changeset patch
+# User Samael Wang <freesamael@gmail.com>
+# Date 1513368846 21600
+# Node ID 3165c7f9db20917c367ee15fb0c17776087714d2
+# Parent  3ac010bc76c8ae203f88a2d8111708efdb4a95a8
+Bug 1406161 - Part 1: Reorder #include, #define, forward declarations, global & static variables. r=smaug
+
+MozReview-Commit-ID: 9DKL1zuLboL
+
+diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp
+--- a/docshell/base/nsDocShell.cpp
++++ b/docshell/base/nsDocShell.cpp
+@@ -3,299 +3,277 @@
+ /* 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 "nsDocShell.h"
+ 
+ #include <algorithm>
+ 
++#ifdef XP_WIN
++#include <process.h>
++#define getpid _getpid
++#else
++#include <unistd.h> // for getpid()
++#endif
++
+ #include "mozilla/ArrayUtils.h"
+ #include "mozilla/Attributes.h"
+ #include "mozilla/AutoRestore.h"
+ #include "mozilla/BasePrincipal.h"
+ #include "mozilla/Casting.h"
+-#include "mozilla/dom/ClientChannelHelper.h"
+-#include "mozilla/dom/ClientHandle.h"
+-#include "mozilla/dom/ClientInfo.h"
+-#include "mozilla/dom/ClientManager.h"
+-#include "mozilla/dom/ClientSource.h"
+-#include "mozilla/dom/ContentChild.h"
+-#include "mozilla/dom/Element.h"
+-#include "mozilla/dom/HTMLAnchorElement.h"
+-#include "mozilla/dom/TabChild.h"
+-#include "mozilla/dom/ProfileTimelineMarkerBinding.h"
+-#include "mozilla/dom/ScreenOrientation.h"
+-#include "mozilla/dom/ToJSValue.h"
+-#include "mozilla/dom/PermissionMessageUtils.h"
+-#include "mozilla/dom/workers/ServiceWorkerManager.h"
++#include "mozilla/Encoding.h"
+ #include "mozilla/EventStateManager.h"
++#include "mozilla/HTMLEditor.h"
+ #include "mozilla/LoadInfo.h"
+-#include "mozilla/HTMLEditor.h"
++#include "mozilla/Logging.h"
+ #include "mozilla/Preferences.h"
+ #include "mozilla/ResultExtensions.h"
+ #include "mozilla/Services.h"
+ #include "mozilla/StartupTimeline.h"
+ #include "mozilla/Telemetry.h"
+ #include "mozilla/Unused.h"
+-#include "Navigator.h"
+-#include "URIUtils.h"
++
++#include "mozilla/dom/ClientChannelHelper.h"
++#include "mozilla/dom/ClientHandle.h"
++#include "mozilla/dom/ClientInfo.h"
++#include "mozilla/dom/ClientManager.h"
++#include "mozilla/dom/ClientSource.h"
++#include "mozilla/dom/ContentChild.h"
+ #include "mozilla/dom/DocGroup.h"
++#include "mozilla/dom/Element.h"
++#include "mozilla/dom/HTMLAnchorElement.h"
++#include "mozilla/dom/PerformanceNavigation.h"
++#include "mozilla/dom/PermissionMessageUtils.h"
++#include "mozilla/dom/ProfileTimelineMarkerBinding.h"
++#include "mozilla/dom/ScreenOrientation.h"
++#include "mozilla/dom/ScriptSettings.h"
++#include "mozilla/dom/TabChild.h"
+ #include "mozilla/dom/TabGroup.h"
+-
++#include "mozilla/dom/ToJSValue.h"
++
++#include "mozilla/dom/workers/ServiceWorkerManager.h"
++
++#include "mozilla/net/ReferrerPolicy.h"
++
++#include "nsIApplicationCacheChannel.h"
++#include "nsIApplicationCacheContainer.h"
++#include "nsIAppShell.h"
++#include "nsIAsyncVerifyRedirectCallback.h"
++#include "nsIAuthPrompt.h"
++#include "nsIAuthPrompt2.h"
++#include "nsICachingChannel.h"
++#include "nsICaptivePortalService.h"
++#include "nsIChannel.h"
++#include "nsIChannelEventSink.h"
++#include "nsIClassOfService.h"
++#include "nsICommandManager.h"
++#include "nsIConsoleReportCollector.h"
+ #include "nsIContent.h"
+ #include "nsIContentInlines.h"
++#include "nsIContentSecurityPolicy.h"
++#include "nsIContentViewer.h"
++#include "nsIController.h"
++#include "nsICookieService.h"
++#include "nsIDocShellTreeItem.h"
++#include "nsIDocShellTreeOwner.h"
+ #include "nsIDocument.h"
++#include "nsIDocumentLoaderFactory.h"
+ #include "nsIDOMDocument.h"
+ #include "nsIDOMElement.h"
++#include "nsIDOMNode.h"
++#include "nsIDOMStorage.h"
++#include "nsIDOMWindow.h"
++#include "nsIEditingSession.h"
++#include "nsIExternalProtocolService.h"
++#include "nsIFormPOSTActionChannel.h"
++#include "nsIFrame.h"
++#include "nsIGlobalHistory2.h"
++#include "nsIGlobalObject.h"
++#include "nsIHttpChannel.h"
++#include "nsIHttpChannelInternal.h"
++#include "nsIIDNService.h"
++#include "nsIInputStreamChannel.h"
++#include "nsIInterfaceRequestorUtils.h"
++#include "nsIJARChannel.h"
++#include "nsILayoutHistoryState.h"
++#include "nsILoadInfo.h"
++#include "nsIMultiPartChannel.h"
++#include "nsINestedURI.h"
++#include "nsINetworkPredictor.h"
++#include "nsINode.h"
++#include "nsINSSErrorsService.h"
++#include "nsIObserverService.h"
++#include "nsIOService.h"
++#include "nsIPrincipal.h"
++#include "nsIPrivacyTransitionObserver.h"
++#include "nsIPrompt.h"
++#include "nsIPromptFactory.h"
++#include "nsIReflowObserver.h"
++#include "nsIScriptChannel.h"
++#include "nsIScriptError.h"
++#include "nsIScriptObjectPrincipal.h"
++#include "nsIScriptSecurityManager.h"
++#include "nsIScrollableFrame.h"
++#include "nsIScrollObserver.h"
++#include "nsISecureBrowserUI.h"
++#include "nsISecurityUITelemetry.h"
++#include "nsISeekableStream.h"
++#include "nsISelectionDisplay.h"
++#include "nsISHContainer.h"
++#include "nsISHEntry.h"
++#include "nsISHistory.h"
++#include "nsISHistoryInternal.h"
++#include "nsISiteSecurityService.h"
++#include "nsISocketProvider.h"
++#include "nsIStringBundle.h"
++#include "nsIStructuredCloneContainer.h"
++#include "nsISupportsPrimitives.h"
++#include "nsITabChild.h"
++#include "nsITextToSubURI.h"
++#include "nsITimedChannel.h"
++#include "nsITimer.h"
++#include "nsITransportSecurityInfo.h"
++#include "nsIUploadChannel.h"
++#include "nsIUploadChannel2.h"
++#include "nsIURIFixup.h"
++#include "nsIURILoader.h"
++#include "nsIURL.h"
++#include "nsIViewSourceChannel.h"
++#include "nsIWebBrowserChrome.h"
++#include "nsIWebBrowserChrome3.h"
++#include "nsIWebBrowserChromeFocus.h"
++#include "nsIWebBrowserFind.h"
++#include "nsIWebProgress.h"
++#include "nsIWidget.h"
++#include "nsIWindowWatcher.h"
++#include "nsIWritablePropertyBag2.h"
++#include "nsIWyciwygChannel.h"
++
++#include "nsPICommandUpdater.h"
++#include "nsPIDOMWindow.h"
++#include "nsPILoadGroupInternal.h"
++#include "nsPIWindowRoot.h"
++
++#include "IHistory.h"
++
++#include "mozIThirdPartyUtil.h"
+ 
+ #include "nsArray.h"
+ #include "nsArrayUtils.h"
++#include "nsAutoPtr.h"
++#include "nsCDefaultURIFixup.h"
++#include "nsCExternalHandlerService.h"
++#include "nsContentDLF.h"
++#include "nsContentPolicyUtils.h" // NS_CheckContentLoadPolicy(...)
+ #include "nsContentSecurityManager.h"
+-#include "nsICaptivePortalService.h"
+-#include "nsIDOMStorage.h"
+-#include "nsIContentViewer.h"
+-#include "nsIDocumentLoaderFactory.h"
++#include "nsContentUtils.h"
+ #include "nsCURILoader.h"
+-#include "nsContentDLF.h"
+ #include "nsDocShellCID.h"
++#include "nsDocShellEditorData.h"
++#include "nsDocShellEnumerator.h"
++#include "nsDocShellLoadInfo.h"
++#include "nsDocShellLoadTypes.h"
++#include "nsDocShellTransferableHooks.h"
+ #include "nsDOMCID.h"
++#include "nsDOMNavigationTiming.h"
++#include "nsDSURIContentListener.h"
++#include "nsError.h"
++#include "nsEscape.h"
++#include "nsFocusManager.h"
++#include "nsGlobalWindow.h"
++#include "nsJSEnvironment.h"
+ #include "nsNetCID.h"
+ #include "nsNetUtil.h"
+-#include "mozilla/net/ReferrerPolicy.h"
+-#include "nsRect.h"
+-#include "prenv.h"
+-#include "nsIDOMWindow.h"
+-#include "nsIGlobalObject.h"
+-#include "nsIViewSourceChannel.h"
+-#include "nsIWebBrowserChrome.h"
++#include "nsObjectLoadingContent.h"
+ #include "nsPoint.h"
+-#include "nsIObserverService.h"
+-#include "nsIPrompt.h"
+-#include "nsIAuthPrompt.h"
+-#include "nsIAuthPrompt2.h"
+-#include "nsIChannelEventSink.h"
+-#include "nsIAsyncVerifyRedirectCallback.h"
+-#include "nsIScriptSecurityManager.h"
+-#include "nsIScriptObjectPrincipal.h"
+-#include "nsIScrollableFrame.h"
+-#include "nsContentPolicyUtils.h" // NS_CheckContentLoadPolicy(...)
+-#include "nsISeekableStream.h"
+-#include "nsAutoPtr.h"
+ #include "nsQueryObject.h"
+-#include "nsIWritablePropertyBag2.h"
+-#include "nsIAppShell.h"
+-#include "nsWidgetsCID.h"
+-#include "nsIInterfaceRequestorUtils.h"
++#include "nsRect.h"
++#include "nsSandboxFlags.h"
++#include "nsSHistory.h"
++#include "nsStreamUtils.h"
++#include "nsStringStream.h"
++#include "nsStructuredCloneContainer.h"
++#include "nsSubDocumentFrame.h"
+ #include "nsView.h"
+ #include "nsViewManager.h"
+-#include "nsIScriptChannel.h"
+-#include "nsITimedChannel.h"
+-#include "nsIPrivacyTransitionObserver.h"
+-#include "nsIReflowObserver.h"
+-#include "nsIScrollObserver.h"
+-#include "nsIDocShellTreeItem.h"
+-#include "nsIChannel.h"
+-#include "IHistory.h"
+ #include "nsViewSourceHandler.h"
+ #include "nsWhitespaceTokenizer.h"
+-#include "nsICookieService.h"
+-#include "nsIConsoleReportCollector.h"
+-#include "nsObjectLoadingContent.h"
+-#include "nsStringStream.h"
+-
+-// we want to explore making the document own the load group
+-// so we can associate the document URI with the load group.
+-// until this point, we have an evil hack:
+-#include "nsIHttpChannelInternal.h"
+-#include "nsPILoadGroupInternal.h"
+-
+-// Local Includes
+-#include "nsDocShellLoadInfo.h"
+-#include "nsCDefaultURIFixup.h"
+-#include "nsDocShellEnumerator.h"
+-#include "nsSHistory.h"
+-#include "nsDocShellEditorData.h"
++#include "nsWidgetsCID.h"
++#include "nsXULAppAPI.h"
++
+ #include "GeckoProfiler.h"
++#include "Navigator.h"
++#include "NullPrincipal.h"
++#include "prenv.h"
++#include "URIUtils.h"
++
+ #include "timeline/JavascriptTimelineMarker.h"
+ 
+-// Helper Classes
+-#include "nsError.h"
+-#include "nsEscape.h"
+-
+-// Interfaces Needed
+-#include "nsIFormPOSTActionChannel.h"
+-#include "nsIUploadChannel.h"
+-#include "nsIUploadChannel2.h"
+-#include "nsIWebProgress.h"
+-#include "nsILayoutHistoryState.h"
+-#include "nsITimer.h"
+-#include "nsISHistoryInternal.h"
+-#include "nsIPrincipal.h"
+-#include "NullPrincipal.h"
+-#include "nsISHEntry.h"
+-#include "nsIWindowWatcher.h"
+-#include "nsIPromptFactory.h"
+-#include "nsITransportSecurityInfo.h"
+-#include "nsINode.h"
+-#include "nsINSSErrorsService.h"
+-#include "nsIApplicationCacheChannel.h"
+-#include "nsIApplicationCacheContainer.h"
+-#include "nsStreamUtils.h"
+-#include "nsIController.h"
+-#include "nsPICommandUpdater.h"
+-#include "nsIWebBrowserChrome3.h"
+-#include "nsITabChild.h"
+-#include "nsISiteSecurityService.h"
+-#include "nsStructuredCloneContainer.h"
+-#include "nsIStructuredCloneContainer.h"
+-#include "nsISupportsPrimitives.h"
+ #ifdef MOZ_PLACES
+ #include "nsIFaviconService.h"
+ #include "mozIPlacesPendingOperation.h"
+ #include "mozIAsyncFavicons.h"
+ #endif
+-#include "nsINetworkPredictor.h"
+-
+-// Editor-related
+-#include "nsIEditingSession.h"
+-
+-#include "nsPIDOMWindow.h"
+-#include "nsGlobalWindow.h"
+-#include "nsPIWindowRoot.h"
+-#include "nsICachingChannel.h"
+-#include "nsIMultiPartChannel.h"
+-#include "nsIWyciwygChannel.h"
+-
+-// For reporting errors with the console service.
+-// These can go away if error reporting is propagated up past nsDocShell.
+-#include "nsIScriptError.h"
+-
+-// used to dispatch urls to default protocol handlers
+-#include "nsCExternalHandlerService.h"
+-#include "nsIExternalProtocolService.h"
+-
+-#include "nsFocusManager.h"
+-
+-#include "nsITextToSubURI.h"
+-
+-#include "nsIJARChannel.h"
+-
+-#include "mozilla/Logging.h"
+-
+-#include "nsISelectionDisplay.h"
+-
+-#include "nsIGlobalHistory2.h"
+-
+-#include "nsIFrame.h"
+-#include "nsSubDocumentFrame.h"
+-
+-// for embedding
+-#include "nsIWebBrowserChromeFocus.h"
+ 
+ #if NS_PRINT_PREVIEW
+ #include "nsIDocumentViewerPrint.h"
+ #include "nsIWebBrowserPrint.h"
+ #endif
+ 
+-#include "nsContentUtils.h"
+-#include "nsIContentSecurityPolicy.h"
+-#include "nsILoadInfo.h"
+-#include "nsSandboxFlags.h"
+-#include "nsXULAppAPI.h"
+-#include "nsDOMNavigationTiming.h"
+-#include "nsISecurityUITelemetry.h"
+-#include "nsDSURIContentListener.h"
+-#include "nsDocShellLoadTypes.h"
+-#include "nsDocShellTransferableHooks.h"
+-#include "nsICommandManager.h"
+-#include "nsIDOMNode.h"
+-#include "nsIClassOfService.h"
+-#include "nsIDocShellTreeOwner.h"
+-#include "nsIHttpChannel.h"
+-#include "nsIIDNService.h"
+-#include "nsIInputStreamChannel.h"
+-#include "nsINestedURI.h"
+-#include "nsIOService.h"
+-#include "nsISHContainer.h"
+-#include "nsISHistory.h"
+-#include "nsISecureBrowserUI.h"
+-#include "nsISocketProvider.h"
+-#include "nsIStringBundle.h"
+-#include "nsIURIFixup.h"
+-#include "nsIURILoader.h"
+-#include "nsIURL.h"
+-#include "nsIWebBrowserFind.h"
+-#include "nsIWidget.h"
+-#include "mozilla/dom/PerformanceNavigation.h"
+-#include "mozilla/dom/ScriptSettings.h"
+-#include "mozilla/Encoding.h"
+-#include "nsJSEnvironment.h"
+-
+ #ifdef MOZ_TOOLKIT_SEARCH
+ #include "nsIBrowserSearchService.h"
+ #endif
+ 
+-#include "mozIThirdPartyUtil.h"
+-
+-static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID);
+-
+-#if defined(DEBUG_bryner) || defined(DEBUG_chb)
+-//#define DEBUG_DOCSHELL_FOCUS
+-#define DEBUG_PAGE_CACHE
+-#endif
+-
+-#ifdef XP_WIN
+-#include <process.h>
+-#define getpid _getpid
+-#else
+-#include <unistd.h> // for getpid()
+-#endif
+-
+ using namespace mozilla;
+ using namespace mozilla::dom;
+ using mozilla::dom::workers::ServiceWorkerManager;
+ 
++// Threshold value in ms for META refresh based redirects
++#define REFRESH_REDIRECT_TIMER 15000
++
++// Hint for native dispatch of events on how long to delay after
++// all documents have loaded in milliseconds before favoring normal
++// native event dispatch priorites over performance
++// Can be overridden with docshell.event_starvation_delay_hint pref.
++#define NS_EVENT_STARVATION_DELAY_HINT 2000
++
++static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID);
++
+ // True means sUseErrorPages has been added to
+ // preferences var cache.
+ static bool gAddedPreferencesVarCache = false;
+ 
+-bool nsDocShell::sUseErrorPages = false;
+-
+ // Number of documents currently loading
+ static int32_t gNumberOfDocumentsLoading = 0;
+ 
+ // Global count of existing docshells.
+ static int32_t gDocShellCount = 0;
+ 
+ // Global count of docshells with the private attribute set
+ static uint32_t gNumberOfPrivateDocShells = 0;
+ 
+-// Global reference to the URI fixup service.
+-nsIURIFixup* nsDocShell::sURIFixup = 0;
+-
+ // True means we validate window targets to prevent frameset
+ // spoofing. Initialize this to a non-bolean value so we know to check
+ // the pref on the creation of the first docshell.
+ static uint32_t gValidateOrigin = 0xffffffff;
+ 
+-// Hint for native dispatch of events on how long to delay after
+-// all documents have loaded in milliseconds before favoring normal
+-// native event dispatch priorites over performance
+-// Can be overridden with docshell.event_starvation_delay_hint pref.
+-#define NS_EVENT_STARVATION_DELAY_HINT 2000
+-
+ #ifdef DEBUG
+ static mozilla::LazyLogModule gDocShellLog("nsDocShell");
+ #endif
+ static mozilla::LazyLogModule gDocShellLeakLog("nsDocShellLeak");;
+ 
+ const char kBrandBundleURL[]      = "chrome://branding/locale/brand.properties";
+ const char kAppstringsBundleURL[] = "chrome://global/locale/appstrings.properties";
+ 
++bool nsDocShell::sUseErrorPages = false;
++
++// Global reference to the URI fixup service.
++nsIURIFixup* nsDocShell::sURIFixup = nullptr;
++
+ static void
+ FavorPerformanceHint(bool aPerfOverStarvation)
+ {
+   nsCOMPtr<nsIAppShell> appShell = do_GetService(kAppShellCID);
+   if (appShell) {
+     appShell->FavorPerformanceHint(
+       aPerfOverStarvation,
+       Preferences::GetUint("docshell.event_starvation_delay_hint",
+diff --git a/docshell/base/nsDocShell.h b/docshell/base/nsDocShell.h
+--- a/docshell/base/nsDocShell.h
++++ b/docshell/base/nsDocShell.h
+@@ -2,111 +2,113 @@
+ /* 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 nsDocShell_h__
+ #define nsDocShell_h__
+ 
+-#include "nsITimer.h"
+-#include "nsContentPolicyUtils.h"
+-#include "nsIDocShell.h"
+-#include "nsIDocShellTreeItem.h"
+-#include "nsIBaseWindow.h"
+-#include "nsINetworkInterceptController.h"
+-#include "nsIScrollable.h"
+-#include "nsITextScroll.h"
+-#include "nsIContentViewerContainer.h"
+-#include "nsIDOMStorageManager.h"
+-#include "nsDocLoader.h"
+ #include "mozilla/BasePrincipal.h"
++#include "mozilla/LinkedList.h"
+ #include "mozilla/Maybe.h"
+ #include "mozilla/Move.h"
++#include "mozilla/TimeStamp.h"
+ #include "mozilla/UniquePtr.h"
+ #include "mozilla/WeakPtr.h"
+-#include "mozilla/TimeStamp.h"
+-#include "GeckoProfiler.h"
++
+ #include "mozilla/dom/ProfileTimelineMarkerBinding.h"
+-#include "mozilla/LinkedList.h"
+-#include "jsapi.h"
+ 
+-// Helper Classes
++#include "nsIAuthPromptProvider.h"
++#include "nsIBaseWindow.h"
++#include "nsIClipboardCommands.h"
++#include "nsIContentViewerContainer.h"
++#include "nsIDeprecationWarner.h"
++#include "nsIDocCharset.h"
++#include "nsIDocShell.h"
++#include "nsIDocShellLoadInfo.h"
++#include "nsIDocShellTreeItem.h"
++#include "nsIDOMStorageManager.h"
++#include "nsIInterfaceRequestor.h"
++#include "nsILinkHandler.h"
++#include "nsILoadContext.h"
++#include "nsINamed.h"
++#include "nsINetworkInterceptController.h"
++#include "nsIRefreshURI.h"
++#include "nsIScrollable.h"
++#include "nsITabParent.h"
++#include "nsITextScroll.h"
++#include "nsITimer.h"
++#include "nsIWebNavigation.h"
++#include "nsIWebPageDescriptor.h"
++#include "nsIWebProgressListener.h"
++#include "nsIWebShellServices.h"
++
++#include "nsAutoPtr.h"
+ #include "nsCOMPtr.h"
++#include "nsContentPolicyUtils.h"
++#include "nsContentUtils.h"
++#include "nsCRT.h"
++#include "nsDocLoader.h"
+ #include "nsPoint.h" // mCurrent/mDefaultScrollbarPreferences
++#include "nsRect.h"
+ #include "nsString.h"
+-#include "nsAutoPtr.h"
+ #include "nsThreadUtils.h"
+-#include "nsContentUtils.h"
++
++#include "GeckoProfiler.h"
++#include "jsapi.h"
++#include "prtime.h"
++#include "Units.h"
++
+ #include "timeline/ObservedDocShell.h"
+ #include "timeline/TimelineConsumers.h"
+ #include "timeline/TimelineMarker.h"
+ 
+-// Threshold value in ms for META refresh based redirects
+-#define REFRESH_REDIRECT_TIMER 15000
+-
+ // Interfaces Needed
+-#include "nsIDocCharset.h"
+-#include "nsIInterfaceRequestor.h"
+-#include "nsINamed.h"
+-#include "nsIRefreshURI.h"
+-#include "nsIWebNavigation.h"
+-#include "nsIWebPageDescriptor.h"
+-#include "nsIWebProgressListener.h"
+-#include "nsIDocShellLoadInfo.h"
+-#include "nsIAuthPromptProvider.h"
+-#include "nsILoadContext.h"
+-#include "nsIWebShellServices.h"
+-#include "nsILinkHandler.h"
+-#include "nsIClipboardCommands.h"
+-#include "nsITabParent.h"
+-#include "nsCRT.h"
+-#include "prtime.h"
+-#include "nsRect.h"
+-#include "Units.h"
+-#include "nsIDeprecationWarner.h"
+ 
+ namespace mozilla {
+ class Encoding;
+ class HTMLEditor;
+ enum class TaskCategory;
+ namespace dom {
+ class ClientInfo;
+ class ClientSource;
+ class EventTarget;
+ typedef uint32_t ScreenOrientationInternal;
+ } // namespace dom
+ } // namespace mozilla
+ 
+-class nsDocShell;
+-class nsDOMNavigationTiming;
+-class nsGlobalWindow;
+-class nsIController;
+-class nsIScrollableFrame;
+-class OnLinkClickEvent;
+-class nsDSURIContentListener;
+-class nsDocShellEditorData;
+ class nsIClipboardDragDropHookList;
+ class nsICommandManager;
+ class nsIContentViewer;
++class nsIController;
++class nsIDocShellTreeOwner;
+ class nsIDocument;
+ class nsIDOMNode;
+-class nsIDocShellTreeOwner;
+ class nsIGlobalHistory2;
+ class nsIHttpChannel;
+ class nsIMutableArray;
+ class nsIPrompt;
++class nsIScrollableFrame;
++class nsISecureBrowserUI;
+ class nsISHistory;
+-class nsISecureBrowserUI;
+ class nsIStringBundle;
+ class nsIURIFixup;
+ class nsIURILoader;
+ class nsIWebBrowserFind;
+ class nsIWidget;
++
++class nsDocShell;
++class nsDocShellEditorData;
++class nsDOMNavigationTiming;
++class nsDSURIContentListener;
++class nsGlobalWindow;
++
+ class FramingChecker;
++class OnLinkClickEvent;
+ 
+ /* internally used ViewMode types */
+ enum ViewMode
+ {
+   viewNormal = 0x0,
+   viewSource = 0x1
+ };
+ 

+ 1404 - 0
mozilla-release/patches/1406161-2-59a1.patch

@@ -0,0 +1,1404 @@
+# HG changeset patch
+# User Samael Wang <freesamael@gmail.com>
+# Date 1513379383 21600
+# Node ID 33cb29987d2093b92a84dac9fb9bb9907811a3a8
+# Parent  e247144f1933cf5aed9b9d858e1f45ec3325f072
+Bug 1406161 - Part 2: Reorder docshell members and remove unnecessary `virtual` or `NS_IMETHOD` keywords. r=smaug
+
+MozReview-Commit-ID: KuEchFzFu7E
+
+diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp
+--- a/docshell/base/nsDocShell.cpp
++++ b/docshell/base/nsDocShell.cpp
+@@ -742,33 +742,46 @@ DecreasePrivateDocShellCount()
+     if (obsvc) {
+       obsvc->NotifyObservers(nullptr, "last-pb-context-exited", nullptr);
+     }
+   }
+ }
+ 
+ nsDocShell::nsDocShell()
+   : nsDocLoader()
++  , mForcedCharset(nullptr)
++  , mParentCharset(nullptr)
++  , mTreeOwner(nullptr)
+   , mDefaultScrollbarPref(Scrollbar_Auto, Scrollbar_Auto)
+-  , mReferrerPolicy(0)
+-  , mFailedLoadType(0)
+-  , mTreeOwner(nullptr)
+   , mCharsetReloadState(eCharsetReloadInit)
+-  , mChildOffset(0)
+-  , mBusyFlags(BUSY_FLAGS_NONE)
+-  , mAppType(nsIDocShell::APP_TYPE_UNKNOWN)
+-  , mLoadType(0)
++  , mOrientationLock(eScreenOrientation_None)
++  , mParentCharsetSource(0)
+   , mMarginWidth(-1)
+   , mMarginHeight(-1)
+   , mItemType(typeContent)
+   , mPreviousTransIndex(-1)
+   , mLoadedTransIndex(-1)
++  , mChildOffset(0)
+   , mSandboxFlags(0)
+-  , mOrientationLock(eScreenOrientation_None)
++  , mBusyFlags(BUSY_FLAGS_NONE)
++  , mAppType(nsIDocShell::APP_TYPE_UNKNOWN)
++  , mLoadType(0)
++  , mDefaultLoadFlags(nsIRequest::LOAD_NORMAL)
++  , mReferrerPolicy(0)
++  , mFailedLoadType(0)
++  , mFrameType(FRAME_TYPE_REGULAR)
++  , mPrivateBrowsingId(0)
++  , mDisplayMode(nsIDocShell::DISPLAY_MODE_BROWSER)
++  , mJSRunToCompletionDepth(0)
++  , mTouchEventsOverride(nsIDocShell::TOUCHEVENTS_OVERRIDE_NONE)
+   , mFullscreenAllowed(CHECK_ATTRIBUTES)
++  , mCreatingDocument(false)
++#ifdef DEBUG
++  , mInEnsureScriptEnv(false)
++#endif
+   , mCreated(false)
+   , mAllowSubframes(true)
+   , mAllowPlugins(true)
+   , mAllowJavascript(true)
+   , mAllowMetaRedirects(true)
+   , mAllowImages(true)
+   , mAllowMedia(true)
+   , mAllowDNSPrefetch(true)
+@@ -798,29 +811,16 @@ nsDocShell::nsDocShell()
+   , mIsExecutingOnLoadHandler(false)
+   , mIsPrintingOrPP(false)
+   , mSavingOldViewer(false)
+   , mDynamicallyCreated(false)
+   , mAffectPrivateSessionLifetime(true)
+   , mInvisible(false)
+   , mHasLoadedNonBlankURI(false)
+   , mBlankTiming(false)
+-  , mCreatingDocument(false)
+-#ifdef DEBUG
+-  , mInEnsureScriptEnv(false)
+-#endif
+-  , mDefaultLoadFlags(nsIRequest::LOAD_NORMAL)
+-  , mFrameType(FRAME_TYPE_REGULAR)
+-  , mPrivateBrowsingId(0)
+-  , mDisplayMode(nsIDocShell::DISPLAY_MODE_BROWSER)
+-  , mForcedCharset(nullptr)
+-  , mParentCharset(nullptr)
+-  , mParentCharsetSource(0)
+-  , mJSRunToCompletionDepth(0)
+-  , mTouchEventsOverride(nsIDocShell::TOUCHEVENTS_OVERRIDE_NONE)
+ {
+   AssertOriginAttributesMatchPrivateBrowsing();
+ 
+   nsContentUtils::GenerateUUIDInPlace(mHistoryID);
+ 
+   if (gDocShellCount++ == 0) {
+     NS_ASSERTION(sURIFixup == nullptr,
+                  "Huh, sURIFixup not null in first nsDocShell ctor!");
+@@ -5444,17 +5444,17 @@ nsDocShell::DisplayLoadError(nsresult aE
+     prompter->Alert(nullptr, messageStr.get());
+   }
+ 
+   return NS_OK;
+ }
+ 
+ #define PREF_SAFEBROWSING_ALLOWOVERRIDE "browser.safebrowsing.allowOverride"
+ 
+-NS_IMETHODIMP
++nsresult
+ nsDocShell::LoadErrorPage(nsIURI* aURI, const char16_t* aURL,
+                           const char* aErrorPage,
+                           const char* aErrorType,
+                           const char16_t* aDescription,
+                           const char* aCSSClass,
+                           nsIChannel* aFailedChannel)
+ {
+ #if defined(DEBUG)
+@@ -13609,17 +13609,17 @@ nsDocShell::ConfirmRepost(bool* aRepost)
+   if (NS_FAILED(rv)) {
+     return rv;
+   }
+ 
+   *aRepost = (buttonPressed == 0);
+   return NS_OK;
+ }
+ 
+-NS_IMETHODIMP
++nsresult
+ nsDocShell::GetPromptAndStringBundle(nsIPrompt** aPrompt,
+                                      nsIStringBundle** aStringBundle)
+ {
+   NS_ENSURE_SUCCESS(GetInterface(NS_GET_IID(nsIPrompt), (void**)aPrompt),
+                     NS_ERROR_FAILURE);
+ 
+   nsCOMPtr<nsIStringBundleService> stringBundleService =
+     mozilla::services::GetStringBundleService();
+@@ -13664,17 +13664,17 @@ nsIScrollableFrame*
+ nsDocShell::GetRootScrollFrame()
+ {
+   nsCOMPtr<nsIPresShell> shell = GetPresShell();
+   NS_ENSURE_TRUE(shell, nullptr);
+ 
+   return shell->GetRootScrollFrameAsScrollable();
+ }
+ 
+-NS_IMETHODIMP
++nsresult
+ nsDocShell::EnsureScriptEnvironment()
+ {
+   if (mScriptGlobal) {
+     return NS_OK;
+   }
+ 
+   if (mIsBeingDestroyed) {
+     return NS_ERROR_NOT_AVAILABLE;
+@@ -13703,17 +13703,17 @@ nsDocShell::EnsureScriptEnvironment()
+   MOZ_ASSERT(mScriptGlobal);
+ 
+   mScriptGlobal->SetDocShell(this);
+ 
+   // Ensure the script object is set up to run script.
+   return mScriptGlobal->EnsureScriptEnvironment();
+ }
+ 
+-NS_IMETHODIMP
++nsresult
+ nsDocShell::EnsureEditorData()
+ {
+   bool openDocHasDetachedEditor = mOSHE && mOSHE->HasDetachedEditor();
+   if (!mEditorData && !mIsBeingDestroyed && !openDocHasDetachedEditor) {
+     // We shouldn't recreate the editor data if it already exists, or
+     // we're shutting down, or we already have a detached editor data
+     // stored in the session history. We should only have one editordata
+     // per docshell.
+@@ -13728,17 +13728,17 @@ nsDocShell::EnsureTransferableHookData()
+ {
+   if (!mTransferableHookData) {
+     mTransferableHookData = new nsTransferableHookData();
+   }
+ 
+   return NS_OK;
+ }
+ 
+-NS_IMETHODIMP
++nsresult
+ nsDocShell::EnsureFind()
+ {
+   nsresult rv;
+   if (!mFind) {
+     mFind = do_CreateInstance("@mozilla.org/embedcomp/find;1", &rv);
+     if (NS_FAILED(rv)) {
+       return rv;
+     }
+diff --git a/docshell/base/nsDocShell.h b/docshell/base/nsDocShell.h
+--- a/docshell/base/nsDocShell.h
++++ b/docshell/base/nsDocShell.h
+@@ -131,17 +131,17 @@ public:
+ 
+   RefPtr<nsDocShell> mDocShell;
+   nsCOMPtr<nsIURI> mURI;
+   nsCOMPtr<nsIPrincipal> mPrincipal;
+   int32_t mDelay;
+   bool mRepeat;
+   bool mMetaRefresh;
+ 
+-protected:
++private:
+   virtual ~nsRefreshTimer();
+ };
+ 
+ enum eCharsetReloadState
+ {
+   eCharsetReloadInit,
+   eCharsetReloadRequested,
+   eCharsetReloadStopOrigional
+@@ -164,30 +164,48 @@ class nsDocShell final
+   , public nsIWebShellServices
+   , public nsILinkHandler
+   , public nsIClipboardCommands
+   , public nsIDOMStorageManager
+   , public nsINetworkInterceptController
+   , public nsIDeprecationWarner
+   , public mozilla::SupportsWeakPtr<nsDocShell>
+ {
+-  friend class nsDSURIContentListener;
+-  friend class FramingChecker;
+-  using Encoding = mozilla::Encoding;
++public:
++  // Event type dispatched by RestorePresentation
++  class RestorePresentationEvent : public mozilla::Runnable
++  {
++  public:
++    NS_DECL_NSIRUNNABLE
++    explicit RestorePresentationEvent(nsDocShell* aDs)
++      : mozilla::Runnable("nsDocShell::RestorePresentationEvent")
++      , mDocShell(aDs)
++    {
++    }
++    void Revoke() { mDocShell = nullptr; }
++  private:
++    RefPtr<nsDocShell> mDocShell;
++  };
+ 
+-public:
++  class InterfaceRequestorProxy : public nsIInterfaceRequestor
++  {
++  public:
++    explicit InterfaceRequestorProxy(nsIInterfaceRequestor* aRequestor);
++    NS_DECL_THREADSAFE_ISUPPORTS
++    NS_DECL_NSIINTERFACEREQUESTOR
++
++  private:
++    virtual ~InterfaceRequestorProxy();
++    InterfaceRequestorProxy() {}
++    nsWeakPtr mWeakPtr;
++  };
++
+   MOZ_DECLARE_WEAKREFERENCE_TYPENAME(nsDocShell)
+-
+-  nsDocShell();
+-
+-  virtual nsresult Init() override;
+-
+   NS_DECL_ISUPPORTS_INHERITED
+   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsDocShell, nsDocLoader)
+-
+   NS_DECL_NSIDOCSHELL
+   NS_DECL_NSIDOCSHELLTREEITEM
+   NS_DECL_NSIWEBNAVIGATION
+   NS_DECL_NSIBASEWINDOW
+   NS_DECL_NSISCROLLABLE
+   NS_DECL_NSITEXTSCROLL
+   NS_DECL_NSIDOCCHARSET
+   NS_DECL_NSIINTERFACEREQUESTOR
+@@ -195,29 +213,33 @@ public:
+   NS_DECL_NSIREFRESHURI
+   NS_DECL_NSICONTENTVIEWERCONTAINER
+   NS_DECL_NSIWEBPAGEDESCRIPTOR
+   NS_DECL_NSIAUTHPROMPTPROVIDER
+   NS_DECL_NSICLIPBOARDCOMMANDS
+   NS_DECL_NSIWEBSHELLSERVICES
+   NS_DECL_NSINETWORKINTERCEPTCONTROLLER
+   NS_DECL_NSIDEPRECATIONWARNER
++
+   NS_FORWARD_SAFE_NSIDOMSTORAGEMANAGER(TopSessionStorageManager())
+ 
++  // Need to implement (and forward) nsISecurityEventSink, because
++  // nsIWebProgressListener has methods with identical names...
++  NS_FORWARD_NSISECURITYEVENTSINK(nsDocLoader::)
++
++  nsDocShell();
++  virtual nsresult Init() override;
++
+   NS_IMETHOD Stop() override
+   {
+     // Need this here because otherwise nsIWebNavigation::Stop
+     // overrides the docloader's Stop()
+     return nsDocLoader::Stop();
+   }
+ 
+-  // Need to implement (and forward) nsISecurityEventSink, because
+-  // nsIWebProgressListener has methods with identical names...
+-  NS_FORWARD_NSISECURITYEVENTSINK(nsDocLoader::)
+-
+   // nsILinkHandler
+   NS_IMETHOD OnLinkClick(nsIContent* aContent,
+                          nsIURI* aURI,
+                          const char16_t* aTargetSpec,
+                          const nsAString& aFileName,
+                          nsIInputStream* aPostDataStream,
+                          int64_t aPostDataStreamLength,
+                          nsIInputStream* aHeadersDataStream,
+@@ -251,64 +273,64 @@ public:
+   NS_IMETHOD GetNestedFrameId(uint64_t*) override;
+   NS_IMETHOD GetIsContent(bool*) override;
+   NS_IMETHOD GetUsePrivateBrowsing(bool*) override;
+   NS_IMETHOD SetUsePrivateBrowsing(bool) override;
+   NS_IMETHOD SetPrivateBrowsing(bool) override;
+   NS_IMETHOD GetUseRemoteTabs(bool*) override;
+   NS_IMETHOD SetRemoteTabs(bool) override;
+   NS_IMETHOD GetScriptableOriginAttributes(JS::MutableHandle<JS::Value>) override;
++  NS_IMETHOD_(void) GetOriginAttributes(mozilla::OriginAttributes& aAttrs) override;
+ 
+   // Restores a cached presentation from history (mLSHE).
+   // This method swaps out the content viewer and simulates loads for
+   // subframes. It then simulates the completion of the toplevel load.
+   nsresult RestoreFromHistory();
+ 
+   // Perform a URI load from a refresh timer. This is just like the
+   // ForceRefreshURI method on nsIRefreshURI, but makes sure to take
+   // the timer involved out of mRefreshURIList if it's there.
+   // aTimer must not be null.
+   nsresult ForceRefreshURIFromTimer(nsIURI* aURI, nsIPrincipal* aPrincipal,
+                                     int32_t aDelay,
+                                     bool aMetaRefresh, nsITimer* aTimer);
+ 
+-  friend class OnLinkClickEvent;
+-
+-  static bool SandboxFlagsImplyCookies(const uint32_t &aSandboxFlags);
+-
+   // We need dummy OnLocationChange in some cases to update the UI without
+   // updating security info.
+   void FireDummyOnLocationChange()
+   {
+     FireOnLocationChange(this, nullptr, mCurrentURI,
+                          LOCATION_CHANGE_SAME_DOCUMENT);
+   }
+ 
+   nsresult HistoryTransactionRemoved(int32_t aIndex);
+ 
+   // Notify Scroll observers when an async panning/zooming transform
+   // has started being applied
+   void NotifyAsyncPanZoomStarted();
++
+   // Notify Scroll observers when an async panning/zooming transform
+   // is no longer applied
+   void NotifyAsyncPanZoomStopped();
+ 
+   void SetInFrameSwap(bool aInSwap)
+   {
+     mInFrameSwap = aInSwap;
+   }
+   bool InFrameSwap();
+ 
+-  const Encoding* GetForcedCharset() { return mForcedCharset; }
++  const mozilla::Encoding* GetForcedCharset() { return mForcedCharset; }
+ 
+   mozilla::HTMLEditor* GetHTMLEditorInternal();
+   nsresult SetHTMLEditorInternal(mozilla::HTMLEditor* aHTMLEditor);
+ 
+   nsDOMNavigationTiming* GetNavigationTiming() const;
+ 
++  nsresult SetOriginAttributes(const mozilla::OriginAttributes& aAttrs);
++
+   /**
+    * Get the list of ancestor principals for this docshell.  The list is meant
+    * to be the list of principals of the documents this docshell is "nested
+    * through" in the sense of
+    * <https://html.spec.whatwg.org/multipage/browsers.html#browsing-context-nested-through>.
+    * In practice, it is defined as follows:
+    *
+    * If this is an <iframe mozbrowser> or a toplevel content docshell
+@@ -356,31 +378,38 @@ public:
+    *
+    * This method steals the data from the passed-in array.
+    */
+   void SetAncestorOuterWindowIDs(nsTArray<uint64_t>&& aAncestorOuterWindowIDs)
+   {
+     mAncestorOuterWindowIDs = mozilla::Move(aAncestorOuterWindowIDs);
+   }
+ 
+-private:
+-  bool CanSetOriginAttributes();
+-
+-public:
+-  const mozilla::OriginAttributes&
+-  GetOriginAttributes()
++  const mozilla::OriginAttributes& GetOriginAttributes()
+   {
+     return mOriginAttributes;
+   }
+ 
+-  nsresult SetOriginAttributes(const mozilla::OriginAttributes& aAttrs);
++  static bool SandboxFlagsImplyCookies(const uint32_t &aSandboxFlags);
++
++  // Tell the favicon service that aNewURI has the same favicon as aOldURI.
++  static void CopyFavicon(nsIURI* aOldURI,
++                          nsIURI* aNewURI,
++                          nsIPrincipal* aLoadingPrincipal,
++                          bool aInPrivateBrowsing);
+ 
+-private:
+-  // An observed docshell wrapper is created when recording markers is enabled.
+-  mozilla::UniquePtr<mozilla::ObservedDocShell> mObserved;
++  static nsDocShell* Cast(nsIDocShell* aDocShell)
++  {
++    return static_cast<nsDocShell*>(aDocShell);
++  }
++
++private: // member functions
++  friend class nsDSURIContentListener;
++  friend class FramingChecker;
++  friend class OnLinkClickEvent;
+ 
+   // It is necessary to allow adding a timeline marker wherever a docshell
+   // instance is available. This operation happens frequently and needs to
+   // be very fast, so instead of using a Map or having to search for some
+   // docshell-specific markers storage, a pointer to an `ObservedDocShell` is
+   // is stored on docshells directly.
+   friend void mozilla::TimelineConsumers::AddConsumer(nsDocShell*);
+   friend void mozilla::TimelineConsumers::RemoveConsumer(nsDocShell*);
+@@ -389,60 +418,170 @@ private:
+   friend void mozilla::TimelineConsumers::AddMarkerForDocShell(
+     nsDocShell*, const char*, const TimeStamp&, MarkerTracingType,
+     MarkerStackRequest);
+   friend void mozilla::TimelineConsumers::AddMarkerForDocShell(
+     nsDocShell*, UniquePtr<AbstractTimelineMarker>&&);
+   friend void mozilla::TimelineConsumers::PopMarkers(nsDocShell*,
+     JSContext*, nsTArray<dom::ProfileTimelineMarker>&);
+ 
+-public:
+-  // Tell the favicon service that aNewURI has the same favicon as aOldURI.
+-  static void CopyFavicon(nsIURI* aOldURI,
+-                          nsIURI* aNewURI,
+-                          nsIPrincipal* aLoadingPrincipal,
+-                          bool aInPrivateBrowsing);
++  // Callback prototype for WalkHistoryEntries.
++  // aEntry is the child history entry, aShell is its corresponding docshell,
++  // aChildIndex is the child's index in its parent entry, and aData is
++  // the opaque pointer passed to WalkHistoryEntries.
++  typedef nsresult(*WalkHistoryEntriesFunc)(nsISHEntry* aEntry,
++                                            nsDocShell* aShell,
++                                            int32_t aChildIndex,
++                                            void* aData);
++
++  // Clone a session history tree for subframe navigation.
++  // The tree rooted at |aSrcEntry| will be cloned into |aDestEntry|, except
++  // for the entry with id |aCloneID|, which will be replaced with
++  // |aReplaceEntry|. |aSrcShell| is a (possibly null) docshell which
++  // corresponds to |aSrcEntry| via its mLSHE or mOHE pointers, and will
++  // have that pointer updated to point to the cloned history entry.
++  // If aCloneChildren is true then the children of the entry with id
++  // |aCloneID| will be cloned into |aReplaceEntry|.
++  static nsresult CloneAndReplace(nsISHEntry* aSrcEntry,
++                                  nsDocShell* aSrcShell,
++                                  uint32_t aCloneID,
++                                  nsISHEntry* aReplaceEntry,
++                                  bool aCloneChildren,
++                                  nsISHEntry** aDestEntry);
+ 
+-  static nsDocShell* Cast(nsIDocShell* aDocShell)
++  // Child-walking callback for CloneAndReplace
++  static nsresult CloneAndReplaceChild(nsISHEntry* aEntry, nsDocShell* aShell,
++                                       int32_t aChildIndex, void* aData);
++
++
++  // Child-walking callback for SetHistoryEntry
++  static nsresult SetChildHistoryEntry(nsISHEntry* aEntry, nsDocShell* aShell,
++                                       int32_t aEntryIndex, void* aData);
++
++  // For each child of aRootEntry, find the corresponding docshell which is
++  // a child of aRootShell, and call aCallback. The opaque pointer aData
++  // is passed to the callback.
++  static nsresult WalkHistoryEntries(nsISHEntry* aRootEntry,
++                                     nsDocShell* aRootShell,
++                                     WalkHistoryEntriesFunc aCallback,
++                                     void* aData);
++
++  // Security checks to prevent frameset spoofing. See comments at
++  // implementation sites.
++  static bool CanAccessItem(nsIDocShellTreeItem* aTargetItem,
++                            nsIDocShellTreeItem* aAccessingItem,
++                            bool aConsiderOpener = true);
++  static bool ValidateOrigin(nsIDocShellTreeItem* aOriginTreeItem,
++                             nsIDocShellTreeItem* aTargetTreeItem);
++
++  static inline uint32_t PRTimeToSeconds(PRTime aTimeUsec)
+   {
+-    return static_cast<nsDocShell*>(aDocShell);
++    PRTime usecPerSec = PR_USEC_PER_SEC;
++    return uint32_t(aTimeUsec /= usecPerSec);
+   }
+ 
+-protected:
++  static const nsCString FrameTypeToString(uint32_t aFrameType)
++  {
++    switch (aFrameType) {
++      case FRAME_TYPE_BROWSER:
++        return NS_LITERAL_CSTRING("browser");
++      case FRAME_TYPE_REGULAR:
++        return NS_LITERAL_CSTRING("regular");
++      default:
++        NS_ERROR("Unknown frame type");
++        return EmptyCString();
++    }
++  }
++
+   virtual ~nsDocShell();
++
++  //
++  // nsDocLoader
++  //
++
+   virtual void DestroyChildren() override;
+ 
++  // Overridden from nsDocLoader, this provides more information than the
++  // normal OnStateChange with flags STATE_REDIRECTING
++  virtual void OnRedirectStateChange(nsIChannel* aOldChannel,
++                                     nsIChannel* aNewChannel,
++                                     uint32_t aRedirectFlags,
++                                     uint32_t aStateFlags) override;
++
++  // Override the parent setter from nsDocLoader
++  virtual nsresult SetDocLoaderParent(nsDocLoader* aLoader) override;
++
++  //
+   // Content Viewer Management
++  //
++
+   nsresult EnsureContentViewer();
++
+   // aPrincipal can be passed in if the caller wants. If null is
+   // passed in, the about:blank principal will end up being used.
+   nsresult CreateAboutBlankContentViewer(nsIPrincipal* aPrincipal,
+                                          nsIURI* aBaseURI,
+                                          bool aTryToSaveOldPresentation = true,
+                                          bool aCheckPermitUnload = true);
++
+   nsresult CreateContentViewer(const nsACString& aContentType,
+                                nsIRequest* aRequest,
+                                nsIStreamListener** aContentHandler);
++
+   nsresult NewContentViewerObj(const nsACString& aContentType,
+                                nsIRequest* aRequest, nsILoadGroup* aLoadGroup,
+                                nsIStreamListener** aContentHandler,
+                                nsIContentViewer** aViewer);
++
+   nsresult SetupNewViewer(nsIContentViewer* aNewViewer);
+ 
+-  void SetupReferrerFromChannel(nsIChannel* aChannel);
++  //
++  // Session History
++  //
++
++  bool ShouldAddToSessionHistory(nsIURI* aURI, nsIChannel* aChannel);
+ 
+-  nsresult GetEldestPresContext(nsPresContext** aPresContext);
++  // Either aChannel or aOwner must be null. If aChannel is
++  // present, the owner should be gotten from it.
++  // If aCloneChildren is true, then our current session history's
++  // children will be cloned onto the new entry. This should be
++  // used when we aren't actually changing the document while adding
++  // the new session history entry.
++
++  nsresult AddToSessionHistory(nsIURI* aURI, nsIChannel* aChannel,
++                               nsIPrincipal* aTriggeringPrincipal,
++                               nsIPrincipal* aPrincipalToInherit,
++                               bool aCloneChildren,
++                               nsISHEntry** aNewEntry);
++
++  nsresult AddChildSHEntryToParent(nsISHEntry* aNewEntry, int32_t aChildOffset,
++                                   bool aCloneChildren);
+ 
+-  // Get the principal that we'll set on the channel if we're inheriting. If
+-  // aConsiderCurrentDocument is true, we try to use the current document if
+-  // at all possible. If that fails, we fall back on the parent document.
+-  // If that fails too, we force creation of a content viewer and use the
+-  // resulting principal. If aConsiderCurrentDocument is false, we just look
+-  // at the parent.
+-  nsIPrincipal* GetInheritedPrincipal(bool aConsiderCurrentDocument);
++  nsresult AddChildSHEntryInternal(nsISHEntry* aCloneRef, nsISHEntry* aNewEntry,
++                                   int32_t aChildOffset, uint32_t aLoadType,
++                                   bool aCloneChildren);
++
++  // Determine whether this docshell corresponds to the given history entry,
++  // via having a pointer to it in mOSHE or mLSHE.
++  bool HasHistoryEntry(nsISHEntry* aEntry) const
++  {
++    return aEntry && (aEntry == mOSHE || aEntry == mLSHE);
++  }
++
++  // Update any pointers (mOSHE or mLSHE) to aOldEntry to point to aNewEntry
++  void SwapHistoryEntries(nsISHEntry* aOldEntry, nsISHEntry* aNewEntry);
++
++  // Call this method to swap in a new history entry to m[OL]SHE, rather than
++  // setting it directly. This completes the navigation in all docshells
++  // in the case of a subframe navigation.
++  void SetHistoryEntry(nsCOMPtr<nsISHEntry>* aPtr, nsISHEntry* aEntry);
++
++  //
++  // URI Load
++  //
+ 
+   // Actually open a channel and perform a URI load. Callers need to pass a
+   // non-null aTriggeringPrincipal which initiated the URI load. Please note
+   // that aTriggeringPrincipal will be used for performing security checks.
+   // If the argument aURI is provided by the web, then please do not pass a
+   // SystemPrincipal as the triggeringPrincipal. If principalToInherit is
+   // null, then no inheritance of any sort will happen and the load will
+   // get a principal based on the URI being loaded.
+@@ -472,18 +611,20 @@ protected:
+                      nsIDocShell** aDocShell,
+                      nsIRequest** aRequest,
+                      bool aIsNewWindowTarget,
+                      bool aBypassClassifier,
+                      bool aForceAllowCookies,
+                      const nsAString& aSrcdoc,
+                      nsIURI* aBaseURI,
+                      nsContentPolicyType aContentPolicyType);
++
+   nsresult AddHeadersToChannel(nsIInputStream* aHeadersData,
+                                nsIChannel* aChannel);
++
+   nsresult DoChannelLoad(nsIChannel* aChannel,
+                          nsIURILoader* aURILoader,
+                          bool aBypassClassifier);
+ 
+   nsresult ScrollToAnchor(bool aCurHasRef,
+                           bool aNewHasRef,
+                           nsACString& aNewHash,
+                           uint32_t aLoadType);
+@@ -509,107 +650,52 @@ protected:
+   bool OnNewURI(nsIURI* aURI, nsIChannel* aChannel,
+                 nsIPrincipal* aTriggeringPrincipal,
+                 nsIPrincipal* aPrincipalToInherit,
+                 uint32_t aLoadType,
+                 bool aFireOnLocationChange,
+                 bool aAddToGlobalHistory,
+                 bool aCloneSHChildren);
+ 
+-  void SetReferrerURI(nsIURI* aURI);
+-  void SetReferrerPolicy(uint32_t aReferrerPolicy);
++  // Helper method that is called when a new document (including any
++  // sub-documents - ie. frames) has been completely loaded.
++  nsresult EndPageLoad(nsIWebProgress* aProgress,
++                       nsIChannel* aChannel,
++                       nsresult aResult);
+ 
+-  // Session History
+-  bool ShouldAddToSessionHistory(nsIURI* aURI, nsIChannel* aChannel);
+-  // Either aChannel or aOwner must be null. If aChannel is
+-  // present, the owner should be gotten from it.
+-  // If aCloneChildren is true, then our current session history's
+-  // children will be cloned onto the new entry. This should be
+-  // used when we aren't actually changing the document while adding
+-  // the new session history entry.
+-  nsresult AddToSessionHistory(nsIURI* aURI, nsIChannel* aChannel,
+-                               nsIPrincipal* aTriggeringPrincipal,
+-                               nsIPrincipal* aPrincipalToInherit,
+-                               bool aCloneChildren,
+-                               nsISHEntry** aNewEntry);
+-  nsresult AddChildSHEntryToParent(nsISHEntry* aNewEntry, int32_t aChildOffset,
+-                                   bool aCloneChildren);
+-
+-  nsresult AddChildSHEntryInternal(nsISHEntry* aCloneRef, nsISHEntry* aNewEntry,
+-                                   int32_t aChildOffset, uint32_t aLoadType,
+-                                   bool aCloneChildren);
+-
+-  nsresult LoadHistoryEntry(nsISHEntry* aEntry, uint32_t aLoadType);
+-  nsresult PersistLayoutHistoryState();
+ 
+-  // Clone a session history tree for subframe navigation.
+-  // The tree rooted at |aSrcEntry| will be cloned into |aDestEntry|, except
+-  // for the entry with id |aCloneID|, which will be replaced with
+-  // |aReplaceEntry|. |aSrcShell| is a (possibly null) docshell which
+-  // corresponds to |aSrcEntry| via its mLSHE or mOHE pointers, and will
+-  // have that pointer updated to point to the cloned history entry.
+-  // If aCloneChildren is true then the children of the entry with id
+-  // |aCloneID| will be cloned into |aReplaceEntry|.
+-  static nsresult CloneAndReplace(nsISHEntry* aSrcEntry,
+-                                  nsDocShell* aSrcShell,
+-                                  uint32_t aCloneID,
+-                                  nsISHEntry* aReplaceEntry,
+-                                  bool aCloneChildren,
+-                                  nsISHEntry** aDestEntry);
++  nsresult LoadErrorPage(nsIURI* aURI, const char16_t* aURL,
++                           const char* aErrorPage,
++                           const char* aErrorType,
++                           const char16_t* aDescription,
++                           const char* aCSSClass,
++                           nsIChannel* aFailedChannel);
+ 
+-  // Child-walking callback for CloneAndReplace
+-  static nsresult CloneAndReplaceChild(nsISHEntry* aEntry, nsDocShell* aShell,
+-                                       int32_t aChildIndex, void* aData);
+-
+-  nsresult GetRootSessionHistory(nsISHistory** aReturn);
+-  nsresult GetHttpChannel(nsIChannel* aChannel, nsIHttpChannel** aReturn);
+-  bool ShouldDiscardLayoutState(nsIHttpChannel* aChannel);
+-
+-  // Determine whether this docshell corresponds to the given history entry,
+-  // via having a pointer to it in mOSHE or mLSHE.
+-  bool HasHistoryEntry(nsISHEntry* aEntry) const
++  bool DisplayLoadError(nsresult aError, nsIURI* aURI, const char16_t* aURL,
++                        nsIChannel* aFailedChannel)
+   {
+-    return aEntry && (aEntry == mOSHE || aEntry == mLSHE);
++    bool didDisplayLoadError = false;
++    DisplayLoadError(aError, aURI, aURL, aFailedChannel, &didDisplayLoadError);
++    return didDisplayLoadError;
+   }
+ 
+-  // Update any pointers (mOSHE or mLSHE) to aOldEntry to point to aNewEntry
+-  void SwapHistoryEntries(nsISHEntry* aOldEntry, nsISHEntry* aNewEntry);
+-
+-  // Call this method to swap in a new history entry to m[OL]SHE, rather than
+-  // setting it directly. This completes the navigation in all docshells
+-  // in the case of a subframe navigation.
+-  void SetHistoryEntry(nsCOMPtr<nsISHEntry>* aPtr, nsISHEntry* aEntry);
+-
+-  // Child-walking callback for SetHistoryEntry
+-  static nsresult SetChildHistoryEntry(nsISHEntry* aEntry, nsDocShell* aShell,
+-                                       int32_t aEntryIndex, void* aData);
++  //
++  // Uncategorized
++  //
+ 
+-  // Callback prototype for WalkHistoryEntries.
+-  // aEntry is the child history entry, aShell is its corresponding docshell,
+-  // aChildIndex is the child's index in its parent entry, and aData is
+-  // the opaque pointer passed to WalkHistoryEntries.
+-  typedef nsresult(*WalkHistoryEntriesFunc)(nsISHEntry* aEntry,
+-                                            nsDocShell* aShell,
+-                                            int32_t aChildIndex,
+-                                            void* aData);
++  // Get the principal that we'll set on the channel if we're inheriting. If
++  // aConsiderCurrentDocument is true, we try to use the current document if
++  // at all possible. If that fails, we fall back on the parent document.
++  // If that fails too, we force creation of a content viewer and use the
++  // resulting principal. If aConsiderCurrentDocument is false, we just look
++  // at the parent.
++  nsIPrincipal* GetInheritedPrincipal(bool aConsiderCurrentDocument);
+ 
+-  // For each child of aRootEntry, find the corresponding docshell which is
+-  // a child of aRootShell, and call aCallback. The opaque pointer aData
+-  // is passed to the callback.
+-  static nsresult WalkHistoryEntries(nsISHEntry* aRootEntry,
+-                                     nsDocShell* aRootShell,
+-                                     WalkHistoryEntriesFunc aCallback,
+-                                     void* aData);
+-
+-  // overridden from nsDocLoader, this provides more information than the
+-  // normal OnStateChange with flags STATE_REDIRECTING
+-  virtual void OnRedirectStateChange(nsIChannel* aOldChannel,
+-                                     nsIChannel* aNewChannel,
+-                                     uint32_t aRedirectFlags,
+-                                     uint32_t aStateFlags) override;
++  nsresult CreatePrincipalFromReferrer(nsIURI* aReferrer,
++                                       nsIPrincipal** aResult);
+ 
+   /**
+    * Helper function that determines if channel is an HTTP POST.
+    *
+    * @param aChannel
+    *        The channel to test
+    *
+    * @return True iff channel is an HTTP post.
+@@ -676,76 +762,21 @@ protected:
+    *        For HTTP channels, the response code (0 otherwise).
+    */
+   void AddURIVisit(nsIURI* aURI,
+                    nsIURI* aReferrerURI,
+                    nsIURI* aPreviousURI,
+                    uint32_t aChannelRedirectFlags,
+                    uint32_t aResponseStatus = 0);
+ 
+-  // Helper Routines
+-  nsresult ConfirmRepost(bool* aRepost);
+-  NS_IMETHOD GetPromptAndStringBundle(nsIPrompt** aPrompt,
+-                                      nsIStringBundle** aStringBundle);
+-  NS_IMETHOD GetChildOffset(nsIDOMNode* aChild, nsIDOMNode* aParent,
+-                            int32_t* aOffset);
+-  nsIScrollableFrame* GetRootScrollFrame();
+-  NS_IMETHOD EnsureScriptEnvironment();
+-  NS_IMETHOD EnsureEditorData();
+-  nsresult EnsureTransferableHookData();
+-  NS_IMETHOD EnsureFind();
+-  nsresult RefreshURIFromQueue();
+-  NS_IMETHOD LoadErrorPage(nsIURI* aURI, const char16_t* aURL,
+-                           const char* aErrorPage,
+-                           const char* aErrorType,
+-                           const char16_t* aDescription,
+-                           const char* aCSSClass,
+-                           nsIChannel* aFailedChannel);
+-  bool IsPrintingOrPP(bool aDisplayErrorDialog = true);
+-  bool IsNavigationAllowed(bool aDisplayPrintErrorDialog = true,
+-                           bool aCheckIfUnloadFired = true);
+-
+-  nsresult SetBaseUrlForWyciwyg(nsIContentViewer* aContentViewer);
+-
+-  static inline uint32_t PRTimeToSeconds(PRTime aTimeUsec)
+-  {
+-    PRTime usecPerSec = PR_USEC_PER_SEC;
+-    return uint32_t(aTimeUsec /= usecPerSec);
+-  }
+-
+-  inline bool UseErrorPages()
+-  {
+-    return (mObserveErrorPages ? sUseErrorPages : mUseErrorPages);
+-  }
+-
+-  bool IsFrame();
+-
+-  //
+-  // Helper method that is called when a new document (including any
+-  // sub-documents - ie. frames) has been completely loaded.
+-  //
+-  virtual nsresult EndPageLoad(nsIWebProgress* aProgress,
+-                               nsIChannel* aChannel,
+-                               nsresult aResult);
+-
+   // Sets the current document's current state object to the given SHEntry's
+   // state object. The current state object is eventually given to the page
+   // in the PopState event.
+   nsresult SetDocCurrentStateObj(nsISHEntry* aShEntry);
+ 
+-  nsresult CheckLoadingPermissions();
+-
+-  // Security checks to prevent frameset spoofing. See comments at
+-  // implementation sites.
+-  static bool CanAccessItem(nsIDocShellTreeItem* aTargetItem,
+-                            nsIDocShellTreeItem* aAccessingItem,
+-                            bool aConsiderOpener = true);
+-  static bool ValidateOrigin(nsIDocShellTreeItem* aOriginTreeItem,
+-                             nsIDocShellTreeItem* aTargetTreeItem);
+-
+   // Returns true if would have called FireOnLocationChange,
+   // but did not because aFireOnLocationChange was false on entry.
+   // In this case it is the caller's responsibility to ensure
+   // FireOnLocationChange is called.
+   // In all other cases false is returned.
+   bool SetCurrentURI(nsIURI* aURI, nsIRequest* aRequest,
+                      bool aFireOnLocationChange,
+                      uint32_t aLocationFlags);
+@@ -805,32 +836,19 @@ protected:
+   void DoGetPositionAndSize(int32_t* aX, int32_t* aY, int32_t* aWidth,
+                             int32_t* aHeight);
+ 
+   // Call this when a URI load is handed to us (via OnLinkClick or
+   // InternalLoad). This makes sure that we're not inside unload, or that if
+   // we are it's still OK to load this URI.
+   bool IsOKToLoadURI(nsIURI* aURI);
+ 
+-  void ReattachEditorToWindow(nsISHEntry* aSHEntry);
+-
+-  nsCOMPtr<nsIDOMStorageManager> mSessionStorageManager;
+-  nsIDOMStorageManager* TopSessionStorageManager();
+-
+   // helpers for executing commands
+   nsresult GetControllerForCommand(const char* aCommand,
+                                    nsIController** aResult);
+-  nsresult EnsureCommandHandler();
+-
+-  nsIChannel* GetCurrentDocChannel();
+-
+-  bool ShouldBlockLoadingForBackButton();
+-
+-  // Convenience method for getting our parent docshell. Can return null
+-  already_AddRefed<nsDocShell> GetParentDocshell();
+ 
+   // Possibly create a ClientSource object to represent an initial about:blank
+   // window that has not been allocated yet.  Normally we try not to create
+   // this about:blank window until something calls GetDocument().  We still need
+   // the ClientSource to exist for this conceptual window, though.
+   //
+   // The ClientSource is created with the given principal if specified.  If
+   // the principal is not provided we will attempt to inherit it when we
+@@ -842,120 +860,163 @@ protected:
+   void MaybeCreateInitialClientSource(nsIPrincipal* aPrincipal = nullptr);
+ 
+   // Return the ClientInfo for the initial about:blank window, if it exists
+   // or we have speculatively created a ClientSource in
+   // MaybeCreateInitialClientSource().  This can return a ClientInfo object
+   // even if GetExtantDoc() returns nullptr.
+   mozilla::Maybe<mozilla::dom::ClientInfo> GetInitialClientInfo() const;
+ 
+-protected:
+-  nsresult GetCurScrollPos(int32_t aScrollOrientation, int32_t* aCurPos);
+-  nsresult SetCurScrollPosEx(int32_t aCurHorizontalPos,
+-                             int32_t aCurVerticalPos);
+-
+-  // Override the parent setter from nsDocLoader
+-  virtual nsresult SetDocLoaderParent(nsDocLoader* aLoader) override;
+-
+-  void ClearFrameHistory(nsISHEntry* aEntry);
+-
+   /**
+    * Initializes mTiming if it isn't yet.
+    * After calling this, mTiming is non-null. This method returns true if the
+    * initialization of the Timing can be reset (basically this is true if a new
+    * Timing object is created).
+    * In case the loading is aborted, MaybeResetInitTiming() can be called
+    * passing the return value of MaybeInitTiming(): if it's possible to reset
+    * the Timing, this method will do it.
+    */
+   MOZ_MUST_USE bool MaybeInitTiming();
+   void MaybeResetInitTiming(bool aReset);
+ 
+-  bool DisplayLoadError(nsresult aError, nsIURI* aURI, const char16_t* aURL,
+-                        nsIChannel* aFailedChannel)
++  // Separate function to do the actual name (i.e. not _top, _self etc.)
++  // searching for FindItemWithName.
++  nsresult DoFindItemWithName(const nsAString& aName,
++                              nsIDocShellTreeItem* aRequestor,
++                              nsIDocShellTreeItem* aOriginalRequestor,
++                              bool aSkipTabGroup,
++                              nsIDocShellTreeItem** aResult);
++
++  // Convenience method for getting our parent docshell. Can return null
++  already_AddRefed<nsDocShell> GetParentDocshell();
++
++  // Helper assertion to enforce that mInPrivateBrowsing is in sync with
++  // OriginAttributes.mPrivateBrowsingId
++  void AssertOriginAttributesMatchPrivateBrowsing();
++
++  // Notify consumers of a search being loaded through the observer service:
++  void MaybeNotifyKeywordSearchLoading(const nsString& aProvider,
++                                       const nsString& aKeyword);
++
++  // Internal implementation of nsIDocShell::FirePageHideNotification.
++  // If aSkipCheckingDynEntries is true, it will not try to remove dynamic
++  // subframe entries. This is to avoid redundant RemoveDynEntries calls in all
++  // children docshells.
++  void FirePageHideNotificationInternal(bool aIsUnload,
++                                        bool aSkipCheckingDynEntries);
++
++  // Dispatch a runnable to the TabGroup associated to this docshell.
++  nsresult DispatchToTabGroup(mozilla::TaskCategory aCategory,
++                              already_AddRefed<nsIRunnable>&& aRunnable);
++
++  NS_IMETHOD GetChildOffset(nsIDOMNode* aChild, nsIDOMNode* aParent,
++                            int32_t* aOffset);
++
++  void SetupReferrerFromChannel(nsIChannel* aChannel);
++  void SetReferrerURI(nsIURI* aURI);
++  void SetReferrerPolicy(uint32_t aReferrerPolicy);
++  void ReattachEditorToWindow(nsISHEntry* aSHEntry);
++  void RecomputeCanExecuteScripts();
++  void ClearFrameHistory(nsISHEntry* aEntry);
++  void UpdateGlobalHistoryTitle(nsIURI* aURI);
++  bool IsFrame();
++  bool CanSetOriginAttributes();
++  bool ShouldBlockLoadingForBackButton();
++  bool ShouldDiscardLayoutState(nsIHttpChannel* aChannel);
++  bool HasUnloadedParent();
++  bool JustStartedNetworkLoad();
++  bool IsPrintingOrPP(bool aDisplayErrorDialog = true);
++  bool IsNavigationAllowed(bool aDisplayPrintErrorDialog = true,
++                           bool aCheckIfUnloadFired = true);
++  uint32_t GetInheritedFrameType();
++  nsIScrollableFrame* GetRootScrollFrame();
++  nsIDOMStorageManager* TopSessionStorageManager();
++  nsIChannel* GetCurrentDocChannel();
++  nsresult EnsureScriptEnvironment();
++  nsresult EnsureEditorData();
++  nsresult EnsureTransferableHookData();
++  nsresult EnsureFind();
++  nsresult EnsureCommandHandler();
++  nsresult RefreshURIFromQueue();
++  nsresult GetEldestPresContext(nsPresContext** aPresContext);
++  nsresult CheckLoadingPermissions();
++  nsresult PersistLayoutHistoryState();
++  nsresult LoadHistoryEntry(nsISHEntry* aEntry, uint32_t aLoadType);
++  nsresult SetBaseUrlForWyciwyg(nsIContentViewer* aContentViewer);
++  nsresult GetRootSessionHistory(nsISHistory** aReturn);
++  nsresult GetHttpChannel(nsIChannel* aChannel, nsIHttpChannel** aReturn);
++  nsresult ConfirmRepost(bool* aRepost);
++  nsresult GetPromptAndStringBundle(nsIPrompt** aPrompt,
++                                    nsIStringBundle** aStringBundle);
++  nsresult GetCurScrollPos(int32_t aScrollOrientation, int32_t* aCurPos);
++  nsresult SetCurScrollPosEx(int32_t aCurHorizontalPos,
++                             int32_t aCurVerticalPos);
++
++  inline bool UseErrorPages()
+   {
+-    bool didDisplayLoadError = false;
+-    DisplayLoadError(aError, aURI, aURL, aFailedChannel, &didDisplayLoadError);
+-    return didDisplayLoadError;
++    return (mObserveErrorPages ? sUseErrorPages : mUseErrorPages);
+   }
+ 
+-public:
+-  // Event type dispatched by RestorePresentation
+-  class RestorePresentationEvent : public mozilla::Runnable
+-  {
+-  public:
+-    NS_DECL_NSIRUNNABLE
+-    explicit RestorePresentationEvent(nsDocShell* aDs)
+-      : mozilla::Runnable("nsDocShell::RestorePresentationEvent")
+-      , mDocShell(aDs)
+-    {
+-    }
+-    void Revoke() { mDocShell = nullptr; }
+-  private:
+-    RefPtr<nsDocShell> mDocShell;
+-  };
++private: // data members
++  static nsIURIFixup* sURIFixup;
+ 
+-protected:
+-  bool JustStartedNetworkLoad();
++  // 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
++  static unsigned long gNumberOfDocShells;
++#endif /* DEBUG */
+ 
+-  nsresult CreatePrincipalFromReferrer(nsIURI* aReferrer,
+-                                       nsIPrincipal** aResult);
+-
+-  static const nsCString FrameTypeToString(uint32_t aFrameType)
+-  {
+-    switch (aFrameType) {
+-      case FRAME_TYPE_BROWSER:
+-        return NS_LITERAL_CSTRING("browser");
+-      case FRAME_TYPE_REGULAR:
+-        return NS_LITERAL_CSTRING("regular");
+-      default:
+-        NS_ERROR("Unknown frame type");
+-        return EmptyCString();
+-    }
+-  }
+-
+-  uint32_t GetInheritedFrameType();
+-
+-  bool HasUnloadedParent();
+-
+-  void UpdateGlobalHistoryTitle(nsIURI* aURI);
+-
+-  NS_IMETHOD_(void) GetOriginAttributes(mozilla::OriginAttributes& aAttrs) override;
++  nsID mHistoryID;
++  nsString mName;
++  nsString mTitle;
++  nsString mCustomUserAgent;
++  nsCString mOriginalUriString;
++  nsWeakPtr mOnePermittedSandboxedNavigator;
++  nsWeakPtr mOpener;
++  nsTObserverArray<nsWeakPtr> mPrivacyObservers;
++  nsTObserverArray<nsWeakPtr> mReflowObservers;
++  nsTObserverArray<nsWeakPtr> mScrollObservers;
++  mozilla::OriginAttributes mOriginAttributes;
++  mozilla::UniquePtr<mozilla::dom::ClientSource> mInitialClientSource;
++  RefPtr<nsDOMNavigationTiming> mTiming;
++  RefPtr<nsDSURIContentListener> mContentListener;
++  RefPtr<nsGlobalWindow> mScriptGlobal;
++  nsCOMPtr<nsIPrincipal> mParentCharsetPrincipal;
++  nsCOMPtr<nsIMutableArray> mRefreshURIList;
++  nsCOMPtr<nsIMutableArray> mSavedRefreshURIList;
++  nsCOMPtr<nsIDOMStorageManager> mSessionStorageManager;
++  nsCOMPtr<nsIContentViewer> mContentViewer;
++  nsCOMPtr<nsIWidget> mParentWidget;
++  nsCOMPtr<nsISHistory> mSessionHistory;
++  nsCOMPtr<nsIGlobalHistory2> mGlobalHistory;
++  nsCOMPtr<nsIWebBrowserFind> mFind;
++  nsCOMPtr<nsICommandManager> mCommandManager;
+ 
+   // Dimensions of the docshell
+   nsIntRect mBounds;
+-  nsString mName;
+-  nsString mTitle;
+-  nsString mCustomUserAgent;
+ 
+   /**
+    * Content-Type Hint of the most-recently initiated load. Used for
+    * session history entries.
+    */
+   nsCString mContentTypeHint;
+-  nsIntPoint mDefaultScrollbarPref; // persistent across doc loads
+ 
+-  nsCOMPtr<nsIMutableArray> mRefreshURIList;
+-  nsCOMPtr<nsIMutableArray> mSavedRefreshURIList;
+-  RefPtr<nsDSURIContentListener> mContentListener;
+-  nsCOMPtr<nsIContentViewer> mContentViewer;
+-  nsCOMPtr<nsIWidget> mParentWidget;
++  // An observed docshell wrapper is created when recording markers is enabled.
++  mozilla::UniquePtr<mozilla::ObservedDocShell> mObserved;
+ 
+   // mCurrentURI should be marked immutable on set if possible.
+   nsCOMPtr<nsIURI> mCurrentURI;
+   nsCOMPtr<nsIURI> mReferrerURI;
+-  uint32_t mReferrerPolicy;
+-  RefPtr<nsGlobalWindow> mScriptGlobal;
+-  nsCOMPtr<nsISHistory> mSessionHistory;
+-  nsCOMPtr<nsIGlobalHistory2> mGlobalHistory;
+-  nsCOMPtr<nsIWebBrowserFind> mFind;
+-  nsCOMPtr<nsICommandManager> mCommandManager;
++
+   // Reference to the SHEntry for this docshell until the page is destroyed.
+   // Somebody give me better name
+   nsCOMPtr<nsISHEntry> mOSHE;
++
+   // Reference to the SHEntry for this docshell until the page is loaded
+   // Somebody give me better name.
+   // If mLSHE is non-null, non-pushState subframe loads don't create separate
+   // root history entries. That is, frames loaded during the parent page
+   // load don't generate history entries the way frame navigation after the
+   // parent has loaded does. (This isn't the only purpose of mLSHE.)
+   nsCOMPtr<nsISHEntry> mLSHE;
+ 
+@@ -975,64 +1036,107 @@ protected:
+ 
+   // The URI we're currently loading. This is only relevant during the
+   // firing of a pagehide/unload. The caller of FirePageHideNotification()
+   // is responsible for setting it and unsetting it. It may be null if the
+   // pagehide/unload is happening for some reason other than just loading a
+   // new URI.
+   nsCOMPtr<nsIURI> mLoadingURI;
+ 
++  // Our list of ancestor principals.
++  nsTArray<nsCOMPtr<nsIPrincipal>> mAncestorPrincipals;
++
++  // Our list of ancestor outerWindowIDs.
++  nsTArray<uint64_t> mAncestorOuterWindowIDs;
++
+   // Set in LoadErrorPage from the method argument and used later
+   // in CreateContentViewer. We have to delay an shistory entry creation
+   // for which these objects are needed.
+   nsCOMPtr<nsIURI> mFailedURI;
+   nsCOMPtr<nsIChannel> mFailedChannel;
+-  uint32_t mFailedLoadType;
+ 
+   // Set in DoURILoad when either the LOAD_RELOAD_ALLOW_MIXED_CONTENT flag or
+   // the LOAD_NORMAL_ALLOW_MIXED_CONTENT flag is set.
+   // Checked in nsMixedContentBlocker, to see if the channels match.
+   nsCOMPtr<nsIChannel> mMixedContentChannel;
+ 
++  const mozilla::Encoding* mForcedCharset;
++  const mozilla::Encoding* mParentCharset;
++
+   // WEAK REFERENCES BELOW HERE.
+   // Note these are intentionally not addrefd. Doing so will create a cycle.
+   // For that reasons don't use nsCOMPtr.
+ 
+-  nsIDocShellTreeOwner* mTreeOwner;  // Weak Reference
++  nsIDocShellTreeOwner* mTreeOwner; // Weak Reference
+ 
+   nsCOMPtr<mozilla::dom::EventTarget> mChromeEventHandler;
+ 
++  nsIntPoint mDefaultScrollbarPref; // persistent across doc loads
++
+   eCharsetReloadState mCharsetReloadState;
+ 
+-  // Offset in the parent's child list.
+-  // -1 if the docshell is added dynamically to the parent shell.
+-  int32_t mChildOffset;
+-  uint32_t mBusyFlags;
+-  uint32_t mAppType;
+-  uint32_t mLoadType;
++  // The orientation lock as described by
++  // https://w3c.github.io/screen-orientation/
++  mozilla::dom::ScreenOrientationInternal mOrientationLock;
+ 
++  int32_t mParentCharsetSource;
+   int32_t mMarginWidth;
+   int32_t mMarginHeight;
+ 
+   // This can either be a content docshell or a chrome docshell. After
+   // Create() is called, the type is not expected to change.
+   int32_t mItemType;
+ 
+   // Index into the SHTransaction list, indicating the previous and current
+   // transaction at the time that this DocShell begins to load. Consequently
+   // root docshell's indices can differ from child docshells'.
+   int32_t mPreviousTransIndex;
+   int32_t mLoadedTransIndex;
+ 
++  // Offset in the parent's child list.
++  // -1 if the docshell is added dynamically to the parent shell.
++  int32_t mChildOffset;
++
+   uint32_t mSandboxFlags;
+-  nsWeakPtr mOnePermittedSandboxedNavigator;
++  uint32_t mBusyFlags;
++  uint32_t mAppType;
++  uint32_t mLoadType;
++  uint32_t mDefaultLoadFlags;
++  uint32_t mReferrerPolicy;
++  uint32_t mFailedLoadType;
++
++  // Are we a regular frame, a browser frame, or an app frame?
++  uint32_t mFrameType;
+ 
+-  // The orientation lock as described by
+-  // https://w3c.github.io/screen-orientation/
+-  mozilla::dom::ScreenOrientationInternal mOrientationLock;
++  // This represents the state of private browsing in the docshell.
++  // Currently treated as a binary value: 1 - in private mode, 0 - not private mode
++  // On content docshells mPrivateBrowsingId == mOriginAttributes.mPrivateBrowsingId
++  // On chrome docshells this value will be set, but not have the corresponding
++  // origin attribute set.
++  uint32_t mPrivateBrowsingId;
++
++  // This represents the CSS display-mode we are currently using.
++  // It can be any of the following values from nsIDocShell.idl:
++  //
++  // DISPLAY_MODE_BROWSER = 0
++  // DISPLAY_MODE_MINIMAL_UI = 1
++  // DISPLAY_MODE_STANDALONE = 2
++  // DISPLAY_MODE_FULLSCREEN = 3
++  //
++  // This is mostly used for media queries. The integer values above
++  // match those used in nsStyleConsts.h
++  uint32_t mDisplayMode;
++
++  // A depth count of how many times NotifyRunToCompletionStart
++  // has been called without a matching NotifyRunToCompletionStop.
++  uint32_t mJSRunToCompletionDepth;
++
++  // Whether or not touch events are overridden. Possible values are defined
++  // as constants in the nsIDocShell.idl file.
++  uint32_t mTouchEventsOverride;
+ 
+   // mFullscreenAllowed stores how we determine whether fullscreen is allowed
+   // when GetFullscreenAllowed() is called. Fullscreen is allowed in a
+   // docshell when all containing iframes have the allowfullscreen
+   // attribute set to true. When mFullscreenAllowed is CHECK_ATTRIBUTES
+   // we check this docshell's containing frame for the allowfullscreen
+   // attribute, and recurse onto the parent docshell to ensure all containing
+   // frames also have the allowfullscreen attribute. If we find an ancestor
+@@ -1044,18 +1148,22 @@ protected:
+   enum FullscreenAllowedState : uint8_t
+   {
+     CHECK_ATTRIBUTES,
+     PARENT_ALLOWS,
+     PARENT_PROHIBITS
+   };
+   FullscreenAllowedState mFullscreenAllowed;
+ 
+-  // Cached value of the "browser.xul.error_pages.enabled" preference.
+-  static bool sUseErrorPages;
++  // The following two fields cannot be declared as bit fields
++  // because of uses with AutoRestore.
++  bool mCreatingDocument; // (should be) debugging only
++#ifdef DEBUG
++  bool mInEnsureScriptEnv;
++#endif
+ 
+   bool mCreated : 1;
+   bool mAllowSubframes : 1;
+   bool mAllowPlugins : 1;
+   bool mAllowJavascript : 1;
+   bool mAllowMetaRedirects : 1;
+   bool mAllowImages : 1;
+   bool mAllowMedia : 1;
+@@ -1078,17 +1186,16 @@ protected:
+   bool mWindowDraggingAllowed : 1;
+   bool mInFrameSwap : 1;
+   bool mInheritPrivateBrowsingId : 1;
+ 
+   // Because scriptability depends on the mAllowJavascript values of our
+   // ancestors, we cache the effective scriptability and recompute it when
+   // it might have changed;
+   bool mCanExecuteScripts : 1;
+-  void RecomputeCanExecuteScripts();
+ 
+   // This boolean is set to true right before we fire pagehide and generally
+   // unset when we embed a new content viewer. While it's true no navigation
+   // is allowed in this docshell.
+   bool mFiredUnloadEvent : 1;
+ 
+   // this flag is for bug #21358. a docshell may load many urls
+   // which don't result in new documents being created (i.e. a new
+@@ -1114,120 +1221,11 @@ protected:
+   bool mAffectPrivateSessionLifetime : 1;
+   bool mInvisible : 1;
+   bool mHasLoadedNonBlankURI : 1;
+ 
+   // This flag means that mTiming has been initialized but nulled out.
+   // We will check the innerWin's timing before creating a new one
+   // in MaybeInitTiming()
+   bool mBlankTiming : 1;
+-
+-  // The following two fields cannot be declared as bit fields
+-  // because of uses with AutoRestore.
+-  bool mCreatingDocument; // (should be) debugging only
+-#ifdef DEBUG
+-  bool mInEnsureScriptEnv;
+-#endif
+-
+-  nsID mHistoryID;
+-  uint32_t mDefaultLoadFlags;
+-
+-  static nsIURIFixup* sURIFixup;
+-
+-  RefPtr<nsDOMNavigationTiming> mTiming;
+-
+-  // Are we a regular frame, a browser frame, or an app frame?
+-  uint32_t mFrameType;
+-
+-  // This represents the state of private browsing in the docshell.
+-  // Currently treated as a binary value: 1 - in private mode, 0 - not private mode
+-  // On content docshells mPrivateBrowsingId == mOriginAttributes.mPrivateBrowsingId
+-  // On chrome docshells this value will be set, but not have the corresponding
+-  // origin attribute set.
+-  uint32_t mPrivateBrowsingId;
+-
+-  // This represents the CSS display-mode we are currently using.
+-  // It can be any of the following values from nsIDocShell.idl:
+-  //
+-  // DISPLAY_MODE_BROWSER = 0
+-  // DISPLAY_MODE_MINIMAL_UI = 1
+-  // DISPLAY_MODE_STANDALONE = 2
+-  // DISPLAY_MODE_FULLSCREEN = 3
+-  //
+-  // This is mostly used for media queries. The integer values above
+-  // match those used in nsStyleConsts.h
+-  uint32_t mDisplayMode;
+-
+-private:
+-  const Encoding* mForcedCharset;
+-  const Encoding* mParentCharset;
+-  int32_t mParentCharsetSource;
+-  nsCOMPtr<nsIPrincipal> mParentCharsetPrincipal;
+-  nsTObserverArray<nsWeakPtr> mPrivacyObservers;
+-  nsTObserverArray<nsWeakPtr> mReflowObservers;
+-  nsTObserverArray<nsWeakPtr> mScrollObservers;
+-  nsCString mOriginalUriString;
+-  nsWeakPtr mOpener;
+-  mozilla::OriginAttributes mOriginAttributes;
+-
+-  mozilla::UniquePtr<mozilla::dom::ClientSource> mInitialClientSource;
+-
+-  // A depth count of how many times NotifyRunToCompletionStart
+-  // has been called without a matching NotifyRunToCompletionStop.
+-  uint32_t mJSRunToCompletionDepth;
+-
+-  // Whether or not touch events are overridden. Possible values are defined
+-  // as constants in the nsIDocShell.idl file.
+-  uint32_t mTouchEventsOverride;
+-
+-  // Our list of ancestor principals.
+-  nsTArray<nsCOMPtr<nsIPrincipal>> mAncestorPrincipals;
+-  // Our list of ancestor outerWindowIDs.
+-  nsTArray<uint64_t> mAncestorOuterWindowIDs;
+-
+-  // Separate function to do the actual name (i.e. not _top, _self etc.)
+-  // searching for FindItemWithName.
+-  nsresult DoFindItemWithName(const nsAString& aName,
+-                              nsIDocShellTreeItem* aRequestor,
+-                              nsIDocShellTreeItem* aOriginalRequestor,
+-                              bool aSkipTabGroup,
+-                              nsIDocShellTreeItem** aResult);
+-
+-  // Helper assertion to enforce that mInPrivateBrowsing is in sync with
+-  // OriginAttributes.mPrivateBrowsingId
+-  void AssertOriginAttributesMatchPrivateBrowsing();
+-
+-  // Notify consumers of a search being loaded through the observer service:
+-  void MaybeNotifyKeywordSearchLoading(const nsString& aProvider,
+-                                       const nsString& aKeyword);
+-
+-  // Internal implementation of nsIDocShell::FirePageHideNotification.
+-  // If aSkipCheckingDynEntries is true, it will not try to remove dynamic
+-  // subframe entries. This is to avoid redundant RemoveDynEntries calls in all
+-  // children docshells.
+-  void FirePageHideNotificationInternal(bool aIsUnload,
+-                                        bool aSkipCheckingDynEntries);
+-
+-  // Dispatch a runnable to the TabGroup associated to this docshell.
+-  nsresult DispatchToTabGroup(mozilla::TaskCategory aCategory,
+-                              already_AddRefed<nsIRunnable>&& aRunnable);
+-
+-#ifdef DEBUG
+-  // We're counting the number of |nsDocShells| to help find leaks
+-  static unsigned long gNumberOfDocShells;
+-#endif /* DEBUG */
+-
+-public:
+-  class InterfaceRequestorProxy : public nsIInterfaceRequestor
+-  {
+-  public:
+-    explicit InterfaceRequestorProxy(nsIInterfaceRequestor* aRequestor);
+-    NS_DECL_THREADSAFE_ISUPPORTS
+-    NS_DECL_NSIINTERFACEREQUESTOR
+-
+-  protected:
+-    virtual ~InterfaceRequestorProxy();
+-    InterfaceRequestorProxy() {}
+-    nsWeakPtr mWeakPtr;
+-  };
+ };
+ 
+ #endif /* nsDocShell_h__ */

+ 80 - 0
mozilla-release/patches/1406161-3-59a1.patch

@@ -0,0 +1,80 @@
+# HG changeset patch
+# User Samael Wang <freesamael@gmail.com>
+# Date 1513379702 21600
+# Node ID 82763191a3c00fe1edb2670ec6b399fb3003e8a7
+# Parent  df345df156805b38899c3b7bf8a30cc7e9ba6dbe
+Bug 1406161 - Part 3: Remove a dead member function. r=smaug
+
+MozReview-Commit-ID: LYNUZhvnAdm
+
+diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp
+--- a/docshell/base/nsDocShell.cpp
++++ b/docshell/base/nsDocShell.cpp
+@@ -13627,44 +13627,16 @@ nsDocShell::GetPromptAndStringBundle(nsI
+ 
+   NS_ENSURE_SUCCESS(
+     stringBundleService->CreateBundle(kAppstringsBundleURL, aStringBundle),
+     NS_ERROR_FAILURE);
+ 
+   return NS_OK;
+ }
+ 
+-NS_IMETHODIMP
+-nsDocShell::GetChildOffset(nsIDOMNode* aChild, nsIDOMNode* aParent,
+-                           int32_t* aOffset)
+-{
+-  NS_ENSURE_ARG_POINTER(aChild || aParent);
+-
+-  nsCOMPtr<nsIDOMNodeList> childNodes;
+-  NS_ENSURE_SUCCESS(aParent->GetChildNodes(getter_AddRefs(childNodes)),
+-                    NS_ERROR_FAILURE);
+-  NS_ENSURE_TRUE(childNodes, NS_ERROR_FAILURE);
+-
+-  int32_t i = 0;
+-
+-  for (; true; i++) {
+-    nsCOMPtr<nsIDOMNode> childNode;
+-    NS_ENSURE_SUCCESS(childNodes->Item(i, getter_AddRefs(childNode)),
+-                      NS_ERROR_FAILURE);
+-    NS_ENSURE_TRUE(childNode, NS_ERROR_FAILURE);
+-
+-    if (childNode.get() == aChild) {
+-      *aOffset = i;
+-      return NS_OK;
+-    }
+-  }
+-
+-  return NS_ERROR_FAILURE;
+-}
+-
+ nsIScrollableFrame*
+ nsDocShell::GetRootScrollFrame()
+ {
+   nsCOMPtr<nsIPresShell> shell = GetPresShell();
+   NS_ENSURE_TRUE(shell, nullptr);
+ 
+   return shell->GetRootScrollFrameAsScrollable();
+ }
+diff --git a/docshell/base/nsDocShell.h b/docshell/base/nsDocShell.h
+--- a/docshell/base/nsDocShell.h
++++ b/docshell/base/nsDocShell.h
+@@ -902,19 +902,16 @@ private: // member functions
+   // children docshells.
+   void FirePageHideNotificationInternal(bool aIsUnload,
+                                         bool aSkipCheckingDynEntries);
+ 
+   // Dispatch a runnable to the TabGroup associated to this docshell.
+   nsresult DispatchToTabGroup(mozilla::TaskCategory aCategory,
+                               already_AddRefed<nsIRunnable>&& aRunnable);
+ 
+-  NS_IMETHOD GetChildOffset(nsIDOMNode* aChild, nsIDOMNode* aParent,
+-                            int32_t* aOffset);
+-
+   void SetupReferrerFromChannel(nsIChannel* aChannel);
+   void SetReferrerURI(nsIURI* aURI);
+   void SetReferrerPolicy(uint32_t aReferrerPolicy);
+   void ReattachEditorToWindow(nsISHEntry* aSHEntry);
+   void RecomputeCanExecuteScripts();
+   void ClearFrameHistory(nsISHEntry* aEntry);
+   void UpdateGlobalHistoryTitle(nsIURI* aURI);
+   bool IsFrame();

+ 1237 - 0
mozilla-release/patches/1406161-4-59a1.patch

@@ -0,0 +1,1237 @@
+# HG changeset patch
+# User Samael Wang <freesamael@gmail.com>
+# Date 1513649976 21600
+# Node ID ec9ea72e98ddd81a431cbe344f46acd59f663d5f
+# Parent  c471c4e4e5f8b04ac458e762649b1f94f82e5730
+Bug 1406161 - Part 4: Move nsPingListener and nsRefreshTimer to separate files. r=smaug
+
+MozReview-Commit-ID: 9Z6i9yWoQwj
+
+diff --git a/docshell/base/moz.build b/docshell/base/moz.build
+--- a/docshell/base/moz.build
++++ b/docshell/base/moz.build
+@@ -86,16 +86,18 @@ UNIFIED_SOURCES += [
+     'nsDefaultURIFixup.cpp',
+     'nsDocShell.cpp',
+     'nsDocShellEditorData.cpp',
+     'nsDocShellEnumerator.cpp',
+     'nsDocShellLoadInfo.cpp',
+     'nsDocShellTransferableHooks.cpp',
+     'nsDocShellTreeOwner.cpp',
+     'nsDSURIContentListener.cpp',
++    'nsPingListener.cpp',
++    'nsRefreshTimer.cpp',
+     'nsWebNavigationInfo.cpp',
+     'SerializedLoadContext.cpp',
+ ]
+ 
+ if not CONFIG['MOZ_PLACES']:
+     UNIFIED_SOURCES += ['nsDownloadHistory.cpp']
+ 
+ include('/ipc/chromium/chromium-config.mozbuild')
+diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp
+--- a/docshell/base/nsDocShell.cpp
++++ b/docshell/base/nsDocShell.cpp
+@@ -128,17 +128,16 @@
+ #include "nsIStructuredCloneContainer.h"
+ #include "nsISupportsPrimitives.h"
+ #include "nsITabChild.h"
+ #include "nsITextToSubURI.h"
+ #include "nsITimedChannel.h"
+ #include "nsITimer.h"
+ #include "nsITransportSecurityInfo.h"
+ #include "nsIUploadChannel.h"
+-#include "nsIUploadChannel2.h"
+ #include "nsIURIFixup.h"
+ #include "nsIURILoader.h"
+ #include "nsIURL.h"
+ #include "nsIViewSourceChannel.h"
+ #include "nsIWebBrowserChrome.h"
+ #include "nsIWebBrowserChrome3.h"
+ #include "nsIWebBrowserChromeFocus.h"
+ #include "nsIWebBrowserFind.h"
+@@ -179,23 +178,23 @@
+ #include "nsError.h"
+ #include "nsEscape.h"
+ #include "nsFocusManager.h"
+ #include "nsGlobalWindow.h"
+ #include "nsJSEnvironment.h"
+ #include "nsNetCID.h"
+ #include "nsNetUtil.h"
+ #include "nsObjectLoadingContent.h"
++#include "nsPingListener.h"
+ #include "nsPoint.h"
+ #include "nsQueryObject.h"
+ #include "nsRect.h"
++#include "nsRefreshTimer.h"
+ #include "nsSandboxFlags.h"
+ #include "nsSHistory.h"
+-#include "nsStreamUtils.h"
+-#include "nsStringStream.h"
+ #include "nsStructuredCloneContainer.h"
+ #include "nsSubDocumentFrame.h"
+ #include "nsView.h"
+ #include "nsViewManager.h"
+ #include "nsViewSourceHandler.h"
+ #include "nsWhitespaceTokenizer.h"
+ #include "nsWidgetsCID.h"
+ #include "nsXULAppAPI.h"
+@@ -276,395 +275,16 @@ FavorPerformanceHint(bool aPerfOverStarv
+   if (appShell) {
+     appShell->FavorPerformanceHint(
+       aPerfOverStarvation,
+       Preferences::GetUint("docshell.event_starvation_delay_hint",
+                            NS_EVENT_STARVATION_DELAY_HINT));
+   }
+ }
+ 
+-//*****************************************************************************
+-// <a ping> support
+-//*****************************************************************************
+-
+-#define PREF_PINGS_ENABLED           "browser.send_pings"
+-#define PREF_PINGS_MAX_PER_LINK      "browser.send_pings.max_per_link"
+-#define PREF_PINGS_REQUIRE_SAME_HOST "browser.send_pings.require_same_host"
+-
+-// Check prefs to see if pings are enabled and if so what restrictions might
+-// be applied.
+-//
+-// @param maxPerLink
+-//   This parameter returns the number of pings that are allowed per link click
+-//
+-// @param requireSameHost
+-//   This parameter returns true if pings are restricted to the same host as
+-//   the document in which the click occurs.  If the same host restriction is
+-//   imposed, then we still allow for pings to cross over to different
+-//   protocols and ports for flexibility and because it is not possible to send
+-//   a ping via FTP.
+-//
+-// @returns
+-//   true if pings are enabled and false otherwise.
+-//
+-static bool
+-PingsEnabled(int32_t* aMaxPerLink, bool* aRequireSameHost)
+-{
+-  bool allow = Preferences::GetBool(PREF_PINGS_ENABLED, false);
+-
+-  *aMaxPerLink = 1;
+-  *aRequireSameHost = true;
+-
+-  if (allow) {
+-    Preferences::GetInt(PREF_PINGS_MAX_PER_LINK, aMaxPerLink);
+-    Preferences::GetBool(PREF_PINGS_REQUIRE_SAME_HOST, aRequireSameHost);
+-  }
+-
+-  return allow;
+-}
+-
+-typedef void (*ForEachPingCallback)(void* closure, nsIContent* content,
+-                                    nsIURI* uri, nsIIOService* ios);
+-
+-static bool
+-IsElementAnchor(nsIContent* aContent)
+-{
+-  // Make sure we are dealing with either an <A> or <AREA> element in the HTML
+-  // or XHTML namespace.
+-  return aContent->IsAnyOfHTMLElements(nsGkAtoms::a, nsGkAtoms::area);
+-}
+-
+-static void
+-ForEachPing(nsIContent* aContent, ForEachPingCallback aCallback, void* aClosure)
+-{
+-  // NOTE: Using nsIDOMHTMLAnchorElement::GetPing isn't really worth it here
+-  //       since we'd still need to parse the resulting string.  Instead, we
+-  //       just parse the raw attribute.  It might be nice if the content node
+-  //       implemented an interface that exposed an enumeration of nsIURIs.
+-
+-  // Make sure we are dealing with either an <A> or <AREA> element in the HTML
+-  // or XHTML namespace.
+-  if (!IsElementAnchor(aContent)) {
+-    return;
+-  }
+-
+-  nsAutoString value;
+-  aContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::ping, value);
+-  if (value.IsEmpty()) {
+-    return;
+-  }
+-
+-  nsCOMPtr<nsIIOService> ios = do_GetIOService();
+-  if (!ios) {
+-    return;
+-  }
+-
+-  nsIDocument* doc = aContent->OwnerDoc();
+-  nsAutoCString charset;
+-  doc->GetDocumentCharacterSet()->Name(charset);
+-
+-  nsWhitespaceTokenizer tokenizer(value);
+-
+-  while (tokenizer.hasMoreTokens()) {
+-    nsCOMPtr<nsIURI> uri, baseURI = aContent->GetBaseURI();
+-    ios->NewURI(NS_ConvertUTF16toUTF8(tokenizer.nextToken()),
+-                charset.get(), baseURI, getter_AddRefs(uri));
+-    // if we can't generate a valid URI, then there is nothing to do
+-    if (!uri) {
+-      continue;
+-    }
+-    // Explicitly not allow loading data: URIs
+-    bool isDataScheme =
+-      (NS_SUCCEEDED(uri->SchemeIs("data", &isDataScheme)) && isDataScheme);
+-
+-    if (!isDataScheme) {
+-      aCallback(aClosure, aContent, uri, ios);
+-    }
+-  }
+-}
+-
+-//----------------------------------------------------------------------
+-
+-// We wait this many milliseconds before killing the ping channel...
+-#define PING_TIMEOUT 10000
+-
+-static void
+-OnPingTimeout(nsITimer* aTimer, void* aClosure)
+-{
+-  nsILoadGroup* loadGroup = static_cast<nsILoadGroup*>(aClosure);
+-  if (loadGroup) {
+-    loadGroup->Cancel(NS_ERROR_ABORT);
+-  }
+-}
+-
+-class nsPingListener final
+-  : public nsIStreamListener
+-{
+-public:
+-  NS_DECL_ISUPPORTS
+-  NS_DECL_NSIREQUESTOBSERVER
+-  NS_DECL_NSISTREAMLISTENER
+-
+-  nsPingListener()
+-  {
+-  }
+-
+-  void SetLoadGroup(nsILoadGroup* aLoadGroup) {
+-    mLoadGroup = aLoadGroup;
+-  }
+-
+-  nsresult StartTimeout(DocGroup* aDocGroup);
+-
+-private:
+-  ~nsPingListener();
+-
+-  nsCOMPtr<nsILoadGroup> mLoadGroup;
+-  nsCOMPtr<nsITimer> mTimer;
+-};
+-
+-NS_IMPL_ISUPPORTS(nsPingListener, nsIStreamListener, nsIRequestObserver)
+-
+-nsPingListener::~nsPingListener()
+-{
+-  if (mTimer) {
+-    mTimer->Cancel();
+-    mTimer = nullptr;
+-  }
+-}
+-
+-nsresult
+-nsPingListener::StartTimeout(DocGroup* aDocGroup)
+-{
+-  NS_ENSURE_ARG(aDocGroup);
+-
+-  return NS_NewTimerWithFuncCallback(getter_AddRefs(mTimer),
+-                                     OnPingTimeout,
+-                                     mLoadGroup,
+-                                     PING_TIMEOUT,
+-                                     nsITimer::TYPE_ONE_SHOT,
+-                                     "nsPingListener::StartTimeout",
+-                                     aDocGroup->EventTargetFor(TaskCategory::Network));
+-}
+-
+-NS_IMETHODIMP
+-nsPingListener::OnStartRequest(nsIRequest* aRequest, nsISupports* aContext)
+-{
+-  return NS_OK;
+-}
+-
+-NS_IMETHODIMP
+-nsPingListener::OnDataAvailable(nsIRequest* aRequest, nsISupports* aContext,
+-                                nsIInputStream* aStream, uint64_t aOffset,
+-                                uint32_t aCount)
+-{
+-  uint32_t result;
+-  return aStream->ReadSegments(NS_DiscardSegment, nullptr, aCount, &result);
+-}
+-
+-NS_IMETHODIMP
+-nsPingListener::OnStopRequest(nsIRequest* aRequest, nsISupports* aContext,
+-                              nsresult aStatus)
+-{
+-  mLoadGroup = nullptr;
+-
+-  if (mTimer) {
+-    mTimer->Cancel();
+-    mTimer = nullptr;
+-  }
+-
+-  return NS_OK;
+-}
+-
+-struct MOZ_STACK_CLASS SendPingInfo
+-{
+-  int32_t numPings;
+-  int32_t maxPings;
+-  bool requireSameHost;
+-  nsIURI* target;
+-  nsIURI* referrer;
+-  nsIDocShell* docShell;
+-  uint32_t referrerPolicy;
+-};
+-
+-static void
+-SendPing(void* aClosure, nsIContent* aContent, nsIURI* aURI,
+-         nsIIOService* aIOService)
+-{
+-  SendPingInfo* info = static_cast<SendPingInfo*>(aClosure);
+-  if (info->maxPings > -1 && info->numPings >= info->maxPings) {
+-    return;
+-  }
+-
+-  nsIDocument* doc = aContent->OwnerDoc();
+-
+-  nsCOMPtr<nsIChannel> chan;
+-  NS_NewChannel(getter_AddRefs(chan),
+-                aURI,
+-                doc,
+-                info->requireSameHost
+-                  ? nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_IS_BLOCKED
+-                  : nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
+-                nsIContentPolicy::TYPE_PING,
+-                nullptr, // aLoadGroup
+-                nullptr, // aCallbacks
+-                nsIRequest::LOAD_NORMAL, // aLoadFlags,
+-                aIOService);
+-
+-  if (!chan) {
+-    return;
+-  }
+-
+-  // Don't bother caching the result of this URI load, but do not exempt
+-  // it from Safe Browsing.
+-  chan->SetLoadFlags(nsIRequest::INHIBIT_CACHING | nsIChannel::LOAD_CLASSIFY_URI);
+-
+-  nsCOMPtr<nsIHttpChannel> httpChan = do_QueryInterface(chan);
+-  if (!httpChan) {
+-    return;
+-  }
+-
+-  // This is needed in order for 3rd-party cookie blocking to work.
+-  nsCOMPtr<nsIHttpChannelInternal> httpInternal = do_QueryInterface(httpChan);
+-  nsresult rv;
+-  if (httpInternal) {
+-    rv = httpInternal->SetDocumentURI(doc->GetDocumentURI());
+-    MOZ_ASSERT(NS_SUCCEEDED(rv));
+-  }
+-
+-  rv = httpChan->SetRequestMethod(NS_LITERAL_CSTRING("POST"));
+-  MOZ_ASSERT(NS_SUCCEEDED(rv));
+-
+-  // Remove extraneous request headers (to reduce request size)
+-  rv = httpChan->SetRequestHeader(NS_LITERAL_CSTRING("accept"),
+-                                  EmptyCString(), false);
+-  MOZ_ASSERT(NS_SUCCEEDED(rv));
+-  rv = httpChan->SetRequestHeader(NS_LITERAL_CSTRING("accept-language"),
+-                                  EmptyCString(), false);
+-  MOZ_ASSERT(NS_SUCCEEDED(rv));
+-  rv = httpChan->SetRequestHeader(NS_LITERAL_CSTRING("accept-encoding"),
+-                                  EmptyCString(), false);
+-  MOZ_ASSERT(NS_SUCCEEDED(rv));
+-
+-  // Always send a Ping-To header.
+-  nsAutoCString pingTo;
+-  if (NS_SUCCEEDED(info->target->GetSpec(pingTo))) {
+-    rv = httpChan->SetRequestHeader(NS_LITERAL_CSTRING("Ping-To"), pingTo, false);
+-    MOZ_ASSERT(NS_SUCCEEDED(rv));
+-  }
+-
+-  nsCOMPtr<nsIScriptSecurityManager> sm =
+-    do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID);
+-
+-  if (sm && info->referrer) {
+-    bool referrerIsSecure;
+-    uint32_t flags = nsIProtocolHandler::URI_SAFE_TO_LOAD_IN_SECURE_CONTEXT;
+-    rv = NS_URIChainHasFlags(info->referrer, flags, &referrerIsSecure);
+-
+-    // Default to sending less data if NS_URIChainHasFlags() fails.
+-    referrerIsSecure = NS_FAILED(rv) || referrerIsSecure;
+-
+-    bool sameOrigin =
+-      NS_SUCCEEDED(sm->CheckSameOriginURI(info->referrer, aURI, false));
+-
+-    // If both the address of the document containing the hyperlink being
+-    // audited and "ping URL" have the same origin or the document containing
+-    // the hyperlink being audited was not retrieved over an encrypted
+-    // connection, send a Ping-From header.
+-    if (sameOrigin || !referrerIsSecure) {
+-      nsAutoCString pingFrom;
+-      if (NS_SUCCEEDED(info->referrer->GetSpec(pingFrom))) {
+-        rv = httpChan->SetRequestHeader(NS_LITERAL_CSTRING("Ping-From"),
+-                                        pingFrom, false);
+-        MOZ_ASSERT(NS_SUCCEEDED(rv));
+-      }
+-    }
+-
+-    // If the document containing the hyperlink being audited was not retrieved
+-    // over an encrypted connection and its address does not have the same
+-    // origin as "ping URL", send a referrer.
+-    if (!sameOrigin && !referrerIsSecure) {
+-      rv = httpChan->SetReferrerWithPolicy(info->referrer, info->referrerPolicy);
+-      MOZ_ASSERT(NS_SUCCEEDED(rv));
+-    }
+-  }
+-
+-  nsCOMPtr<nsIUploadChannel2> uploadChan = do_QueryInterface(httpChan);
+-  if (!uploadChan) {
+-    return;
+-  }
+-
+-  NS_NAMED_LITERAL_CSTRING(uploadData, "PING");
+-
+-  nsCOMPtr<nsIInputStream> uploadStream;
+-  rv = NS_NewCStringInputStream(getter_AddRefs(uploadStream), uploadData);
+-  if (NS_WARN_IF(NS_FAILED(rv))) {
+-    return;
+-  }
+-
+-  uploadChan->ExplicitSetUploadStream(uploadStream,
+-                                      NS_LITERAL_CSTRING("text/ping"),
+-                                      uploadData.Length(),
+-                                      NS_LITERAL_CSTRING("POST"), false);
+-
+-  // The channel needs to have a loadgroup associated with it, so that we can
+-  // cancel the channel and any redirected channels it may create.
+-  nsCOMPtr<nsILoadGroup> loadGroup = do_CreateInstance(NS_LOADGROUP_CONTRACTID);
+-  if (!loadGroup) {
+-    return;
+-  }
+-  nsCOMPtr<nsIInterfaceRequestor> callbacks = do_QueryInterface(info->docShell);
+-  loadGroup->SetNotificationCallbacks(callbacks);
+-  chan->SetLoadGroup(loadGroup);
+-
+-  RefPtr<nsPingListener> pingListener = new nsPingListener();
+-  chan->AsyncOpen2(pingListener);
+-
+-  // Even if AsyncOpen failed, we still count this as a successful ping.  It's
+-  // possible that AsyncOpen may have failed after triggering some background
+-  // process that may have written something to the network.
+-  info->numPings++;
+-
+-  // Prevent ping requests from stalling and never being garbage collected...
+-  if (NS_FAILED(pingListener->StartTimeout(doc->GetDocGroup()))) {
+-    // If we failed to setup the timer, then we should just cancel the channel
+-    // because we won't be able to ensure that it goes away in a timely manner.
+-    chan->Cancel(NS_ERROR_ABORT);
+-    return;
+-  }
+-  // if the channel openend successfully, then make the pingListener hold
+-  // a strong reference to the loadgroup which is released in ::OnStopRequest
+-  pingListener->SetLoadGroup(loadGroup);
+-}
+-
+-// Spec: http://whatwg.org/specs/web-apps/current-work/#ping
+-static void
+-DispatchPings(nsIDocShell* aDocShell,
+-              nsIContent* aContent,
+-              nsIURI* aTarget,
+-              nsIURI* aReferrer,
+-              uint32_t aReferrerPolicy)
+-{
+-  SendPingInfo info;
+-
+-  if (!PingsEnabled(&info.maxPings, &info.requireSameHost)) {
+-    return;
+-  }
+-  if (info.maxPings == 0) {
+-    return;
+-  }
+-
+-  info.numPings = 0;
+-  info.target = aTarget;
+-  info.referrer = aReferrer;
+-  info.referrerPolicy = aReferrerPolicy;
+-  info.docShell = aDocShell;
+-
+-  ForEachPing(aContent, SendPing, &info);
+-}
+-
+ static nsDOMNavigationTiming::Type
+ ConvertLoadTypeToNavigationType(uint32_t aLoadType)
+ {
+   // Not initialized, assume it's normal load.
+   if (aLoadType == 0) {
+     aLoadType = LOAD_NORMAL;
+   }
+ 
+@@ -13784,60 +13404,16 @@ NS_IMETHODIMP
+ nsDocShell::SetLayoutHistoryState(nsILayoutHistoryState* aLayoutHistoryState)
+ {
+   if (mOSHE) {
+     mOSHE->SetLayoutHistoryState(aLayoutHistoryState);
+   }
+   return NS_OK;
+ }
+ 
+-nsRefreshTimer::nsRefreshTimer(nsDocShell* aDocShell,
+-                               nsIURI* aURI,
+-                               nsIPrincipal* aPrincipal,
+-                               int32_t aDelay, bool aRepeat, bool aMetaRefresh)
+-  : mDocShell(aDocShell), mURI(aURI), mPrincipal(aPrincipal),
+-    mDelay(aDelay), mRepeat(aRepeat),
+-    mMetaRefresh(aMetaRefresh)
+-{
+-}
+-
+-nsRefreshTimer::~nsRefreshTimer()
+-{
+-}
+-
+-NS_IMPL_ADDREF(nsRefreshTimer)
+-NS_IMPL_RELEASE(nsRefreshTimer)
+-
+-NS_INTERFACE_MAP_BEGIN(nsRefreshTimer)
+-  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsITimerCallback)
+-  NS_INTERFACE_MAP_ENTRY(nsITimerCallback)
+-  NS_INTERFACE_MAP_ENTRY(nsINamed)
+-NS_INTERFACE_MAP_END
+-
+-NS_IMETHODIMP
+-nsRefreshTimer::Notify(nsITimer* aTimer)
+-{
+-  NS_ASSERTION(mDocShell, "DocShell is somehow null");
+-
+-  if (mDocShell && aTimer) {
+-    // Get the delay count to determine load type
+-    uint32_t delay = 0;
+-    aTimer->GetDelay(&delay);
+-    mDocShell->ForceRefreshURIFromTimer(mURI, mPrincipal, delay, mMetaRefresh, aTimer);
+-  }
+-  return NS_OK;
+-}
+-
+-NS_IMETHODIMP
+-nsRefreshTimer::GetName(nsACString& aName)
+-{
+-  aName.AssignLiteral("nsRefreshTimer");
+-  return NS_OK;
+-}
+-
+ nsDocShell::InterfaceRequestorProxy::InterfaceRequestorProxy(
+     nsIInterfaceRequestor* aRequestor)
+ {
+   if (aRequestor) {
+     mWeakPtr = do_GetWeakReference(aRequestor);
+   }
+ }
+ 
+@@ -14339,16 +13915,24 @@ nsDocShell::OnLinkClick(nsIContent* aCon
+   nsCOMPtr<nsIRunnable> ev =
+     new OnLinkClickEvent(this, aContent, aURI, target.get(), aFileName,
+                          aPostDataStream, aPostDataStreamLength,
+                          aHeadersDataStream, noOpenerImplied,
+                          aIsTrusted, aTriggeringPrincipal);
+   return DispatchToTabGroup(TaskCategory::UI, ev.forget());
+ }
+ 
++static bool
++IsElementAnchorOrArea(nsIContent* aContent)
++{
++  // Make sure we are dealing with either an <A> or <AREA> element in the HTML
++  // or XHTML namespace.
++  return aContent->IsAnyOfHTMLElements(nsGkAtoms::a, nsGkAtoms::area);
++}
++
+ NS_IMETHODIMP
+ nsDocShell::OnLinkClickSync(nsIContent* aContent,
+                             nsIURI* aURI,
+                             const char16_t* aTargetSpec,
+                             const nsAString& aFileName,
+                             nsIInputStream* aPostDataStream,
+                             int64_t aPostDataStreamLength,
+                             nsIInputStream* aHeadersDataStream,
+@@ -14397,17 +13981,17 @@ nsDocShell::OnLinkClickSync(nsIContent* 
+         if (NS_SUCCEEDED(rv) && !isExposed) {
+           return extProtService->LoadURI(aURI, this);
+         }
+       }
+     }
+   }
+ 
+   uint32_t flags = INTERNAL_LOAD_FLAGS_NONE;
+-  if (IsElementAnchor(aContent)) {
++  if (IsElementAnchorOrArea(aContent)) {
+     MOZ_ASSERT(aContent->IsHTMLElement());
+     nsAutoString referrer;
+     aContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::rel, referrer);
+     nsWhitespaceTokenizerTemplate<nsContentUtils::IsHTMLWhitespace> tok(referrer);
+     while (tok.hasMoreTokens()) {
+       const nsAString& token = tok.nextToken();
+       if (token.LowerCaseEqualsLiteral("noreferrer")) {
+         flags |= INTERNAL_LOAD_FLAGS_DONT_SEND_REFERRER |
+@@ -14444,17 +14028,17 @@ nsDocShell::OnLinkClickSync(nsIContent* 
+   }
+ 
+   nsCOMPtr<nsIURI> referer = refererDoc->GetDocumentURI();
+   uint32_t refererPolicy = refererDoc->GetReferrerPolicy();
+ 
+   // get referrer attribute from clicked link and parse it
+   // if per element referrer is enabled, the element referrer overrules
+   // the document wide referrer
+-  if (IsElementAnchor(aContent)) {
++  if (IsElementAnchorOrArea(aContent)) {
+     net::ReferrerPolicy refPolEnum = aContent->AsElement()->GetReferrerPolicyAsEnum();
+     if (refPolEnum != net::RP_Unset) {
+       refererPolicy = refPolEnum;
+     }
+   }
+ 
+   // referer could be null here in some odd cases, but that's ok,
+   // we'll just load the link w/o sending a referer in those cases.
+@@ -14513,17 +14097,17 @@ nsDocShell::OnLinkClickSync(nsIContent* 
+                              nullptr,                   // No SHEntry
+                              true,                      // first party site
+                              VoidString(),              // No srcdoc
+                              this,                      // We are the source
+                              nullptr,                   // baseURI not needed
+                              aDocShell,                 // DocShell out-param
+                              aRequest);                 // Request out-param
+   if (NS_SUCCEEDED(rv)) {
+-    DispatchPings(this, aContent, aURI, referer, refererPolicy);
++    nsPingListener::DispatchPings(this, aContent, aURI, referer, refererPolicy);
+   }
+   return rv;
+ }
+ 
+ NS_IMETHODIMP
+ nsDocShell::OnOverLink(nsIContent* aContent,
+                        nsIURI* aURI,
+                        const char16_t* aTargetSpec)
+diff --git a/docshell/base/nsDocShell.h b/docshell/base/nsDocShell.h
+--- a/docshell/base/nsDocShell.h
++++ b/docshell/base/nsDocShell.h
+@@ -25,23 +25,21 @@
+ #include "nsIDocCharset.h"
+ #include "nsIDocShell.h"
+ #include "nsIDocShellLoadInfo.h"
+ #include "nsIDocShellTreeItem.h"
+ #include "nsIDOMStorageManager.h"
+ #include "nsIInterfaceRequestor.h"
+ #include "nsILinkHandler.h"
+ #include "nsILoadContext.h"
+-#include "nsINamed.h"
+ #include "nsINetworkInterceptController.h"
+ #include "nsIRefreshURI.h"
+ #include "nsIScrollable.h"
+ #include "nsITabParent.h"
+ #include "nsITextScroll.h"
+-#include "nsITimer.h"
+ #include "nsIWebNavigation.h"
+ #include "nsIWebPageDescriptor.h"
+ #include "nsIWebProgressListener.h"
+ #include "nsIWebShellServices.h"
+ 
+ #include "nsAutoPtr.h"
+ #include "nsCOMPtr.h"
+ #include "nsContentPolicyUtils.h"
+@@ -107,44 +105,16 @@ class OnLinkClickEvent;
+ 
+ /* internally used ViewMode types */
+ enum ViewMode
+ {
+   viewNormal = 0x0,
+   viewSource = 0x1
+ };
+ 
+-class nsRefreshTimer : public nsITimerCallback
+-                     , public nsINamed
+-{
+-public:
+-  nsRefreshTimer(nsDocShell* aDocShell,
+-                 nsIURI* aURI,
+-                 nsIPrincipal* aPrincipal,
+-                 int32_t aDelay,
+-                 bool aRepeat,
+-                 bool aMetaRefresh);
+-
+-  NS_DECL_THREADSAFE_ISUPPORTS
+-  NS_DECL_NSITIMERCALLBACK
+-  NS_DECL_NSINAMED
+-
+-  int32_t GetDelay() { return mDelay ;}
+-
+-  RefPtr<nsDocShell> mDocShell;
+-  nsCOMPtr<nsIURI> mURI;
+-  nsCOMPtr<nsIPrincipal> mPrincipal;
+-  int32_t mDelay;
+-  bool mRepeat;
+-  bool mMetaRefresh;
+-
+-private:
+-  virtual ~nsRefreshTimer();
+-};
+-
+ enum eCharsetReloadState
+ {
+   eCharsetReloadInit,
+   eCharsetReloadRequested,
+   eCharsetReloadStopOrigional
+ };
+ 
+ class nsDocShell final
+diff --git a/docshell/base/nsPingListener.cpp b/docshell/base/nsPingListener.cpp
+new file mode 100644
+--- /dev/null
++++ b/docshell/base/nsPingListener.cpp
+@@ -0,0 +1,370 @@
++/* -*- 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 "nsPingListener.h"
++
++#include "mozilla/Preferences.h"
++
++#include "mozilla/dom/DocGroup.h"
++
++#include "nsIDocument.h"
++#include "nsIHttpChannelInternal.h"
++#include "nsIInputStream.h"
++#include "nsIProtocolHandler.h"
++#include "nsIUploadChannel2.h"
++
++#include "nsDocument.h"
++#include "nsNetUtil.h"
++#include "nsStreamUtils.h"
++#include "nsStringStream.h"
++#include "nsWhitespaceTokenizer.h"
++
++using namespace mozilla;
++using namespace mozilla::dom;
++
++NS_IMPL_ISUPPORTS(nsPingListener, nsIStreamListener, nsIRequestObserver)
++
++//*****************************************************************************
++// <a ping> support
++//*****************************************************************************
++
++#define PREF_PINGS_ENABLED           "browser.send_pings"
++#define PREF_PINGS_MAX_PER_LINK      "browser.send_pings.max_per_link"
++#define PREF_PINGS_REQUIRE_SAME_HOST "browser.send_pings.require_same_host"
++
++// Check prefs to see if pings are enabled and if so what restrictions might
++// be applied.
++//
++// @param maxPerLink
++//   This parameter returns the number of pings that are allowed per link click
++//
++// @param requireSameHost
++//   This parameter returns true if pings are restricted to the same host as
++//   the document in which the click occurs.  If the same host restriction is
++//   imposed, then we still allow for pings to cross over to different
++//   protocols and ports for flexibility and because it is not possible to send
++//   a ping via FTP.
++//
++// @returns
++//   true if pings are enabled and false otherwise.
++//
++static bool
++PingsEnabled(int32_t* aMaxPerLink, bool* aRequireSameHost)
++{
++  bool allow = Preferences::GetBool(PREF_PINGS_ENABLED, false);
++
++  *aMaxPerLink = 1;
++  *aRequireSameHost = true;
++
++  if (allow) {
++    Preferences::GetInt(PREF_PINGS_MAX_PER_LINK, aMaxPerLink);
++    Preferences::GetBool(PREF_PINGS_REQUIRE_SAME_HOST, aRequireSameHost);
++  }
++
++  return allow;
++}
++
++// We wait this many milliseconds before killing the ping channel...
++#define PING_TIMEOUT 10000
++
++static void
++OnPingTimeout(nsITimer* aTimer, void* aClosure)
++{
++  nsILoadGroup* loadGroup = static_cast<nsILoadGroup*>(aClosure);
++  if (loadGroup) {
++    loadGroup->Cancel(NS_ERROR_ABORT);
++  }
++}
++
++struct MOZ_STACK_CLASS SendPingInfo
++{
++  int32_t numPings;
++  int32_t maxPings;
++  bool requireSameHost;
++  nsIURI* target;
++  nsIURI* referrer;
++  nsIDocShell* docShell;
++  uint32_t referrerPolicy;
++};
++
++static void
++SendPing(void* aClosure, nsIContent* aContent, nsIURI* aURI,
++         nsIIOService* aIOService)
++{
++  SendPingInfo* info = static_cast<SendPingInfo*>(aClosure);
++  if (info->maxPings > -1 && info->numPings >= info->maxPings) {
++    return;
++  }
++
++  nsIDocument* doc = aContent->OwnerDoc();
++
++  nsCOMPtr<nsIChannel> chan;
++  NS_NewChannel(getter_AddRefs(chan),
++                aURI,
++                doc,
++                info->requireSameHost
++                  ? nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_IS_BLOCKED
++                  : nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
++                nsIContentPolicy::TYPE_PING,
++                nullptr, // aLoadGroup
++                nullptr, // aCallbacks
++                nsIRequest::LOAD_NORMAL, // aLoadFlags,
++                aIOService);
++
++  if (!chan) {
++    return;
++  }
++
++  // Don't bother caching the result of this URI load, but do not exempt
++  // it from Safe Browsing.
++  chan->SetLoadFlags(nsIRequest::INHIBIT_CACHING | nsIChannel::LOAD_CLASSIFY_URI);
++
++  nsCOMPtr<nsIHttpChannel> httpChan = do_QueryInterface(chan);
++  if (!httpChan) {
++    return;
++  }
++
++  // This is needed in order for 3rd-party cookie blocking to work.
++  nsCOMPtr<nsIHttpChannelInternal> httpInternal = do_QueryInterface(httpChan);
++  nsresult rv;
++  if (httpInternal) {
++    rv = httpInternal->SetDocumentURI(doc->GetDocumentURI());
++    MOZ_ASSERT(NS_SUCCEEDED(rv));
++  }
++
++  rv = httpChan->SetRequestMethod(NS_LITERAL_CSTRING("POST"));
++  MOZ_ASSERT(NS_SUCCEEDED(rv));
++
++  // Remove extraneous request headers (to reduce request size)
++  rv = httpChan->SetRequestHeader(NS_LITERAL_CSTRING("accept"),
++                                  EmptyCString(), false);
++  MOZ_ASSERT(NS_SUCCEEDED(rv));
++  rv = httpChan->SetRequestHeader(NS_LITERAL_CSTRING("accept-language"),
++                                  EmptyCString(), false);
++  MOZ_ASSERT(NS_SUCCEEDED(rv));
++  rv = httpChan->SetRequestHeader(NS_LITERAL_CSTRING("accept-encoding"),
++                                  EmptyCString(), false);
++  MOZ_ASSERT(NS_SUCCEEDED(rv));
++
++  // Always send a Ping-To header.
++  nsAutoCString pingTo;
++  if (NS_SUCCEEDED(info->target->GetSpec(pingTo))) {
++    rv = httpChan->SetRequestHeader(NS_LITERAL_CSTRING("Ping-To"), pingTo, false);
++    MOZ_ASSERT(NS_SUCCEEDED(rv));
++  }
++
++  nsCOMPtr<nsIScriptSecurityManager> sm =
++    do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID);
++
++  if (sm && info->referrer) {
++    bool referrerIsSecure;
++    uint32_t flags = nsIProtocolHandler::URI_SAFE_TO_LOAD_IN_SECURE_CONTEXT;
++    rv = NS_URIChainHasFlags(info->referrer, flags, &referrerIsSecure);
++
++    // Default to sending less data if NS_URIChainHasFlags() fails.
++    referrerIsSecure = NS_FAILED(rv) || referrerIsSecure;
++
++    bool sameOrigin =
++      NS_SUCCEEDED(sm->CheckSameOriginURI(info->referrer, aURI, false));
++
++    // If both the address of the document containing the hyperlink being
++    // audited and "ping URL" have the same origin or the document containing
++    // the hyperlink being audited was not retrieved over an encrypted
++    // connection, send a Ping-From header.
++    if (sameOrigin || !referrerIsSecure) {
++      nsAutoCString pingFrom;
++      if (NS_SUCCEEDED(info->referrer->GetSpec(pingFrom))) {
++        rv = httpChan->SetRequestHeader(NS_LITERAL_CSTRING("Ping-From"),
++                                        pingFrom, false);
++        MOZ_ASSERT(NS_SUCCEEDED(rv));
++      }
++    }
++
++    // If the document containing the hyperlink being audited was not retrieved
++    // over an encrypted connection and its address does not have the same
++    // origin as "ping URL", send a referrer.
++    if (!sameOrigin && !referrerIsSecure) {
++      rv = httpChan->SetReferrerWithPolicy(info->referrer, info->referrerPolicy);
++      MOZ_ASSERT(NS_SUCCEEDED(rv));
++    }
++  }
++
++  nsCOMPtr<nsIUploadChannel2> uploadChan = do_QueryInterface(httpChan);
++  if (!uploadChan) {
++    return;
++  }
++
++  NS_NAMED_LITERAL_CSTRING(uploadData, "PING");
++
++  nsCOMPtr<nsIInputStream> uploadStream;
++  rv = NS_NewCStringInputStream(getter_AddRefs(uploadStream), uploadData);
++  if (NS_WARN_IF(NS_FAILED(rv))) {
++    return;
++  }
++
++  uploadChan->ExplicitSetUploadStream(uploadStream,
++                                      NS_LITERAL_CSTRING("text/ping"),
++                                      uploadData.Length(),
++                                      NS_LITERAL_CSTRING("POST"), false);
++
++  // The channel needs to have a loadgroup associated with it, so that we can
++  // cancel the channel and any redirected channels it may create.
++  nsCOMPtr<nsILoadGroup> loadGroup = do_CreateInstance(NS_LOADGROUP_CONTRACTID);
++  if (!loadGroup) {
++    return;
++  }
++  nsCOMPtr<nsIInterfaceRequestor> callbacks = do_QueryInterface(info->docShell);
++  loadGroup->SetNotificationCallbacks(callbacks);
++  chan->SetLoadGroup(loadGroup);
++
++  RefPtr<nsPingListener> pingListener = new nsPingListener();
++  chan->AsyncOpen2(pingListener);
++
++  // Even if AsyncOpen failed, we still count this as a successful ping.  It's
++  // possible that AsyncOpen may have failed after triggering some background
++  // process that may have written something to the network.
++  info->numPings++;
++
++  // Prevent ping requests from stalling and never being garbage collected...
++  if (NS_FAILED(pingListener->StartTimeout(doc->GetDocGroup()))) {
++    // If we failed to setup the timer, then we should just cancel the channel
++    // because we won't be able to ensure that it goes away in a timely manner.
++    chan->Cancel(NS_ERROR_ABORT);
++    return;
++  }
++  // if the channel openend successfully, then make the pingListener hold
++  // a strong reference to the loadgroup which is released in ::OnStopRequest
++  pingListener->SetLoadGroup(loadGroup);
++}
++
++typedef void (*ForEachPingCallback)(void* closure, nsIContent* content,
++                                    nsIURI* uri, nsIIOService* ios);
++
++static void
++ForEachPing(nsIContent* aContent, ForEachPingCallback aCallback, void* aClosure)
++{
++  // NOTE: Using nsIDOMHTMLAnchorElement::GetPing isn't really worth it here
++  //       since we'd still need to parse the resulting string.  Instead, we
++  //       just parse the raw attribute.  It might be nice if the content node
++  //       implemented an interface that exposed an enumeration of nsIURIs.
++
++  // Make sure we are dealing with either an <A> or <AREA> element in the HTML
++  // or XHTML namespace.
++  if (!aContent->IsAnyOfHTMLElements(nsGkAtoms::a, nsGkAtoms::area)) {
++    return;
++  }
++
++  nsAutoString value;
++  aContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::ping, value);
++  if (value.IsEmpty()) {
++    return;
++  }
++
++  nsCOMPtr<nsIIOService> ios = do_GetIOService();
++  if (!ios) {
++    return;
++  }
++
++  nsIDocument* doc = aContent->OwnerDoc();
++  nsAutoCString charset;
++  doc->GetDocumentCharacterSet()->Name(charset);
++
++  nsWhitespaceTokenizer tokenizer(value);
++
++  while (tokenizer.hasMoreTokens()) {
++    nsCOMPtr<nsIURI> uri, baseURI = aContent->GetBaseURI();
++    ios->NewURI(NS_ConvertUTF16toUTF8(tokenizer.nextToken()),
++                charset.get(), baseURI, getter_AddRefs(uri));
++    // if we can't generate a valid URI, then there is nothing to do
++    if (!uri) {
++      continue;
++    }
++    // Explicitly not allow loading data: URIs
++    bool isDataScheme =
++      (NS_SUCCEEDED(uri->SchemeIs("data", &isDataScheme)) && isDataScheme);
++
++    if (!isDataScheme) {
++      aCallback(aClosure, aContent, uri, ios);
++    }
++  }
++}
++
++// Spec: http://whatwg.org/specs/web-apps/current-work/#ping
++/*static*/ void
++nsPingListener::DispatchPings(nsIDocShell* aDocShell,
++                              nsIContent* aContent,
++                              nsIURI* aTarget,
++                              nsIURI* aReferrer,
++                              uint32_t aReferrerPolicy)
++{
++  SendPingInfo info;
++
++  if (!PingsEnabled(&info.maxPings, &info.requireSameHost)) {
++    return;
++  }
++  if (info.maxPings == 0) {
++    return;
++  }
++
++  info.numPings = 0;
++  info.target = aTarget;
++  info.referrer = aReferrer;
++  info.referrerPolicy = aReferrerPolicy;
++  info.docShell = aDocShell;
++
++  ForEachPing(aContent, SendPing, &info);
++}
++
++nsPingListener::~nsPingListener()
++{
++  if (mTimer) {
++    mTimer->Cancel();
++    mTimer = nullptr;
++  }
++}
++
++nsresult
++nsPingListener::StartTimeout(DocGroup* aDocGroup)
++{
++  NS_ENSURE_ARG(aDocGroup);
++
++  return NS_NewTimerWithFuncCallback(getter_AddRefs(mTimer),
++                                     OnPingTimeout,
++                                     mLoadGroup,
++                                     PING_TIMEOUT,
++                                     nsITimer::TYPE_ONE_SHOT,
++                                     "nsPingListener::StartTimeout",
++                                     aDocGroup->EventTargetFor(TaskCategory::Network));
++}
++
++NS_IMETHODIMP
++nsPingListener::OnStartRequest(nsIRequest* aRequest, nsISupports* aContext)
++{
++  return NS_OK;
++}
++
++NS_IMETHODIMP
++nsPingListener::OnDataAvailable(nsIRequest* aRequest, nsISupports* aContext,
++                                nsIInputStream* aStream, uint64_t aOffset,
++                                uint32_t aCount)
++{
++  uint32_t result;
++  return aStream->ReadSegments(NS_DiscardSegment, nullptr, aCount, &result);
++}
++
++NS_IMETHODIMP
++nsPingListener::OnStopRequest(nsIRequest* aRequest, nsISupports* aContext,
++                              nsresult aStatus)
++{
++  mLoadGroup = nullptr;
++
++  if (mTimer) {
++    mTimer->Cancel();
++    mTimer = nullptr;
++  }
++
++  return NS_OK;
++}
+diff --git a/docshell/base/nsPingListener.h b/docshell/base/nsPingListener.h
+new file mode 100644
+--- /dev/null
++++ b/docshell/base/nsPingListener.h
+@@ -0,0 +1,55 @@
++/* -*- 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 nsPingListener_h__
++#define nsPingListener_h__
++
++#include "nsIStreamListener.h"
++
++#include "nsCOMPtr.h"
++
++namespace mozilla {
++namespace dom {
++class DocGroup;
++}
++}
++
++class nsIContent;
++class nsIDocShell;
++class nsILoadGroup;
++class nsITimer;
++class nsIURI;
++
++class nsPingListener final : public nsIStreamListener
++{
++public:
++  NS_DECL_ISUPPORTS
++  NS_DECL_NSIREQUESTOBSERVER
++  NS_DECL_NSISTREAMLISTENER
++
++  nsPingListener()
++  {
++  }
++
++  void SetLoadGroup(nsILoadGroup* aLoadGroup) {
++    mLoadGroup = aLoadGroup;
++  }
++
++  nsresult StartTimeout(mozilla::dom::DocGroup* aDocGroup);
++
++  static void DispatchPings(nsIDocShell* aDocShell,
++              nsIContent* aContent,
++              nsIURI* aTarget,
++              nsIURI* aReferrer,
++              uint32_t aReferrerPolicy);
++private:
++  ~nsPingListener();
++
++  nsCOMPtr<nsILoadGroup> mLoadGroup;
++  nsCOMPtr<nsITimer> mTimer;
++};
++
++#endif /* nsPingListener_h__ */
+diff --git a/docshell/base/nsRefreshTimer.cpp b/docshell/base/nsRefreshTimer.cpp
+new file mode 100644
+--- /dev/null
++++ b/docshell/base/nsRefreshTimer.cpp
+@@ -0,0 +1,56 @@
++/* -*- 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 "nsRefreshTimer.h"
++
++#include "nsIURI.h"
++#include "nsIPrincipal.h"
++
++#include "nsDocShell.h"
++
++NS_IMPL_ADDREF(nsRefreshTimer)
++NS_IMPL_RELEASE(nsRefreshTimer)
++
++NS_INTERFACE_MAP_BEGIN(nsRefreshTimer)
++  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsITimerCallback)
++  NS_INTERFACE_MAP_ENTRY(nsITimerCallback)
++  NS_INTERFACE_MAP_ENTRY(nsINamed)
++NS_INTERFACE_MAP_END
++
++nsRefreshTimer::nsRefreshTimer(nsDocShell* aDocShell,
++                               nsIURI* aURI,
++                               nsIPrincipal* aPrincipal,
++                               int32_t aDelay, bool aRepeat, bool aMetaRefresh)
++  : mDocShell(aDocShell), mURI(aURI), mPrincipal(aPrincipal),
++    mDelay(aDelay), mRepeat(aRepeat),
++    mMetaRefresh(aMetaRefresh)
++{
++}
++
++nsRefreshTimer::~nsRefreshTimer()
++{
++}
++
++NS_IMETHODIMP
++nsRefreshTimer::Notify(nsITimer* aTimer)
++{
++  NS_ASSERTION(mDocShell, "DocShell is somehow null");
++
++  if (mDocShell && aTimer) {
++    // Get the delay count to determine load type
++    uint32_t delay = 0;
++    aTimer->GetDelay(&delay);
++    mDocShell->ForceRefreshURIFromTimer(mURI, mPrincipal, delay, mMetaRefresh, aTimer);
++  }
++  return NS_OK;
++}
++
++NS_IMETHODIMP
++nsRefreshTimer::GetName(nsACString& aName)
++{
++  aName.AssignLiteral("nsRefreshTimer");
++  return NS_OK;
++}
+diff --git a/docshell/base/nsRefreshTimer.h b/docshell/base/nsRefreshTimer.h
+new file mode 100644
+--- /dev/null
++++ b/docshell/base/nsRefreshTimer.h
+@@ -0,0 +1,47 @@
++/* -*- 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 nsRefreshTimer_h__
++#define nsRefreshTimer_h__
++
++#include "nsINamed.h"
++#include "nsITimer.h"
++
++#include "nsCOMPtr.h"
++
++class nsDocShell;
++class nsIURI;
++class nsIPrincipal;
++
++class nsRefreshTimer : public nsITimerCallback
++                     , public nsINamed
++{
++public:
++  nsRefreshTimer(nsDocShell* aDocShell,
++                 nsIURI* aURI,
++                 nsIPrincipal* aPrincipal,
++                 int32_t aDelay,
++                 bool aRepeat,
++                 bool aMetaRefresh);
++
++  NS_DECL_THREADSAFE_ISUPPORTS
++  NS_DECL_NSITIMERCALLBACK
++  NS_DECL_NSINAMED
++
++  int32_t GetDelay() { return mDelay ;}
++
++  RefPtr<nsDocShell> mDocShell;
++  nsCOMPtr<nsIURI> mURI;
++  nsCOMPtr<nsIPrincipal> mPrincipal;
++  int32_t mDelay;
++  bool mRepeat;
++  bool mMetaRefresh;
++
++private:
++  virtual ~nsRefreshTimer();
++};
++
++#endif /* nsRefreshTimer_h__ */

+ 647 - 0
mozilla-release/patches/1406161-5-59a1.patch

@@ -0,0 +1,647 @@
+# HG changeset patch
+# User Samael Wang <freesamael@gmail.com>
+# Date 1513667582 -28800
+# Node ID 62a61710cf861f3aaf9acb4db3f8c3fee979c493
+# Parent  833676affbe0bb015849d940503d413f54e3bbd8
+Bug 1406161 - Part 5: Move LoadType convertion functions to nsDocShellLoadTypes.h. r=smaug
+
+MozReview-Commit-ID: Ccw7cDE20m3
+
+diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp
+--- a/docshell/base/nsDocShell.cpp
++++ b/docshell/base/nsDocShell.cpp
+@@ -275,67 +275,16 @@ FavorPerformanceHint(bool aPerfOverStarv
+   if (appShell) {
+     appShell->FavorPerformanceHint(
+       aPerfOverStarvation,
+       Preferences::GetUint("docshell.event_starvation_delay_hint",
+                            NS_EVENT_STARVATION_DELAY_HINT));
+   }
+ }
+ 
+-static nsDOMNavigationTiming::Type
+-ConvertLoadTypeToNavigationType(uint32_t aLoadType)
+-{
+-  // Not initialized, assume it's normal load.
+-  if (aLoadType == 0) {
+-    aLoadType = LOAD_NORMAL;
+-  }
+-
+-  auto result = nsDOMNavigationTiming::TYPE_RESERVED;
+-  switch (aLoadType) {
+-    case LOAD_NORMAL:
+-    case LOAD_NORMAL_EXTERNAL:
+-    case LOAD_NORMAL_BYPASS_CACHE:
+-    case LOAD_NORMAL_BYPASS_PROXY:
+-    case LOAD_NORMAL_BYPASS_PROXY_AND_CACHE:
+-    case LOAD_NORMAL_REPLACE:
+-    case LOAD_NORMAL_ALLOW_MIXED_CONTENT:
+-    case LOAD_LINK:
+-    case LOAD_STOP_CONTENT:
+-    case LOAD_REPLACE_BYPASS_CACHE:
+-      result = nsDOMNavigationTiming::TYPE_NAVIGATE;
+-      break;
+-    case LOAD_HISTORY:
+-      result = nsDOMNavigationTiming::TYPE_BACK_FORWARD;
+-      break;
+-    case LOAD_RELOAD_NORMAL:
+-    case LOAD_RELOAD_CHARSET_CHANGE:
+-    case LOAD_RELOAD_CHARSET_CHANGE_BYPASS_PROXY_AND_CACHE:
+-    case LOAD_RELOAD_CHARSET_CHANGE_BYPASS_CACHE:
+-    case LOAD_RELOAD_BYPASS_CACHE:
+-    case LOAD_RELOAD_BYPASS_PROXY:
+-    case LOAD_RELOAD_BYPASS_PROXY_AND_CACHE:
+-    case LOAD_RELOAD_ALLOW_MIXED_CONTENT:
+-      result = nsDOMNavigationTiming::TYPE_RELOAD;
+-      break;
+-    case LOAD_STOP_CONTENT_AND_REPLACE:
+-    case LOAD_REFRESH:
+-    case LOAD_BYPASS_HISTORY:
+-    case LOAD_ERROR_PAGE:
+-    case LOAD_PUSHSTATE:
+-      result = nsDOMNavigationTiming::TYPE_RESERVED;
+-      break;
+-    default:
+-      // NS_NOTREACHED("Unexpected load type value");
+-      result = nsDOMNavigationTiming::TYPE_RESERVED;
+-      break;
+-  }
+-
+-  return result;
+-}
+-
+ static nsISHEntry* GetRootSHEntry(nsISHEntry* aEntry);
+ 
+ static void
+ IncreasePrivateDocShellCount()
+ {
+   gNumberOfPrivateDocShells++;
+   if (gNumberOfPrivateDocShells > 1 ||
+       !XRE_IsContentProcess()) {
+@@ -709,181 +658,16 @@ nsDocShell::GetInterface(const nsIID& aI
+   } else {
+     return nsDocLoader::GetInterface(aIID, aSink);
+   }
+ 
+   NS_IF_ADDREF(((nsISupports*)*aSink));
+   return *aSink ? NS_OK : NS_NOINTERFACE;
+ }
+ 
+-uint32_t
+-nsDocShell::ConvertDocShellLoadInfoToLoadType(
+-    nsDocShellInfoLoadType aDocShellLoadType)
+-{
+-  uint32_t loadType = LOAD_NORMAL;
+-
+-  switch (aDocShellLoadType) {
+-    case nsIDocShellLoadInfo::loadNormal:
+-      loadType = LOAD_NORMAL;
+-      break;
+-    case nsIDocShellLoadInfo::loadNormalReplace:
+-      loadType = LOAD_NORMAL_REPLACE;
+-      break;
+-    case nsIDocShellLoadInfo::loadNormalExternal:
+-      loadType = LOAD_NORMAL_EXTERNAL;
+-      break;
+-    case nsIDocShellLoadInfo::loadHistory:
+-      loadType = LOAD_HISTORY;
+-      break;
+-    case nsIDocShellLoadInfo::loadNormalBypassCache:
+-      loadType = LOAD_NORMAL_BYPASS_CACHE;
+-      break;
+-    case nsIDocShellLoadInfo::loadNormalBypassProxy:
+-      loadType = LOAD_NORMAL_BYPASS_PROXY;
+-      break;
+-    case nsIDocShellLoadInfo::loadNormalBypassProxyAndCache:
+-      loadType = LOAD_NORMAL_BYPASS_PROXY_AND_CACHE;
+-      break;
+-    case nsIDocShellLoadInfo::loadNormalAllowMixedContent:
+-      loadType = LOAD_NORMAL_ALLOW_MIXED_CONTENT;
+-      break;
+-    case nsIDocShellLoadInfo::loadReloadNormal:
+-      loadType = LOAD_RELOAD_NORMAL;
+-      break;
+-    case nsIDocShellLoadInfo::loadReloadCharsetChange:
+-      loadType = LOAD_RELOAD_CHARSET_CHANGE;
+-      break;
+-    case nsIDocShellLoadInfo::loadReloadCharsetChangeBypassCache:
+-      loadType = LOAD_RELOAD_CHARSET_CHANGE_BYPASS_CACHE;
+-      break;
+-    case nsIDocShellLoadInfo::loadReloadCharsetChangeBypassProxyAndCache:
+-      loadType = LOAD_RELOAD_CHARSET_CHANGE_BYPASS_PROXY_AND_CACHE;
+-      break;
+-    case nsIDocShellLoadInfo::loadReloadBypassCache:
+-      loadType = LOAD_RELOAD_BYPASS_CACHE;
+-      break;
+-    case nsIDocShellLoadInfo::loadReloadBypassProxy:
+-      loadType = LOAD_RELOAD_BYPASS_PROXY;
+-      break;
+-    case nsIDocShellLoadInfo::loadReloadBypassProxyAndCache:
+-      loadType = LOAD_RELOAD_BYPASS_PROXY_AND_CACHE;
+-      break;
+-    case nsIDocShellLoadInfo::loadLink:
+-      loadType = LOAD_LINK;
+-      break;
+-    case nsIDocShellLoadInfo::loadRefresh:
+-      loadType = LOAD_REFRESH;
+-      break;
+-    case nsIDocShellLoadInfo::loadBypassHistory:
+-      loadType = LOAD_BYPASS_HISTORY;
+-      break;
+-    case nsIDocShellLoadInfo::loadStopContent:
+-      loadType = LOAD_STOP_CONTENT;
+-      break;
+-    case nsIDocShellLoadInfo::loadStopContentAndReplace:
+-      loadType = LOAD_STOP_CONTENT_AND_REPLACE;
+-      break;
+-    case nsIDocShellLoadInfo::loadPushState:
+-      loadType = LOAD_PUSHSTATE;
+-      break;
+-    case nsIDocShellLoadInfo::loadReplaceBypassCache:
+-      loadType = LOAD_REPLACE_BYPASS_CACHE;
+-      break;
+-    case nsIDocShellLoadInfo::loadReloadMixedContent:
+-      loadType = LOAD_RELOAD_ALLOW_MIXED_CONTENT;
+-      break;
+-    default:
+-      NS_NOTREACHED("Unexpected nsDocShellInfoLoadType value");
+-  }
+-
+-  return loadType;
+-}
+-
+-nsDocShellInfoLoadType
+-nsDocShell::ConvertLoadTypeToDocShellLoadInfo(uint32_t aLoadType)
+-{
+-  nsDocShellInfoLoadType docShellLoadType = nsIDocShellLoadInfo::loadNormal;
+-  switch (aLoadType) {
+-    case LOAD_NORMAL:
+-      docShellLoadType = nsIDocShellLoadInfo::loadNormal;
+-      break;
+-    case LOAD_NORMAL_REPLACE:
+-      docShellLoadType = nsIDocShellLoadInfo::loadNormalReplace;
+-      break;
+-    case LOAD_NORMAL_EXTERNAL:
+-      docShellLoadType = nsIDocShellLoadInfo::loadNormalExternal;
+-      break;
+-    case LOAD_NORMAL_BYPASS_CACHE:
+-      docShellLoadType = nsIDocShellLoadInfo::loadNormalBypassCache;
+-      break;
+-    case LOAD_NORMAL_BYPASS_PROXY:
+-      docShellLoadType = nsIDocShellLoadInfo::loadNormalBypassProxy;
+-      break;
+-    case LOAD_NORMAL_BYPASS_PROXY_AND_CACHE:
+-      docShellLoadType = nsIDocShellLoadInfo::loadNormalBypassProxyAndCache;
+-      break;
+-    case LOAD_NORMAL_ALLOW_MIXED_CONTENT:
+-      docShellLoadType = nsIDocShellLoadInfo::loadNormalAllowMixedContent;
+-      break;
+-    case LOAD_HISTORY:
+-      docShellLoadType = nsIDocShellLoadInfo::loadHistory;
+-      break;
+-    case LOAD_RELOAD_NORMAL:
+-      docShellLoadType = nsIDocShellLoadInfo::loadReloadNormal;
+-      break;
+-    case LOAD_RELOAD_CHARSET_CHANGE:
+-      docShellLoadType = nsIDocShellLoadInfo::loadReloadCharsetChange;
+-      break;
+-    case LOAD_RELOAD_CHARSET_CHANGE_BYPASS_CACHE:
+-      docShellLoadType = nsIDocShellLoadInfo::loadReloadCharsetChangeBypassCache;
+-      break;
+-    case LOAD_RELOAD_CHARSET_CHANGE_BYPASS_PROXY_AND_CACHE:
+-      docShellLoadType = nsIDocShellLoadInfo::loadReloadCharsetChangeBypassProxyAndCache;
+-      break;
+-    case LOAD_RELOAD_BYPASS_CACHE:
+-      docShellLoadType = nsIDocShellLoadInfo::loadReloadBypassCache;
+-      break;
+-    case LOAD_RELOAD_BYPASS_PROXY:
+-      docShellLoadType = nsIDocShellLoadInfo::loadReloadBypassProxy;
+-      break;
+-    case LOAD_RELOAD_BYPASS_PROXY_AND_CACHE:
+-      docShellLoadType = nsIDocShellLoadInfo::loadReloadBypassProxyAndCache;
+-      break;
+-    case LOAD_LINK:
+-      docShellLoadType = nsIDocShellLoadInfo::loadLink;
+-      break;
+-    case LOAD_REFRESH:
+-      docShellLoadType = nsIDocShellLoadInfo::loadRefresh;
+-      break;
+-    case LOAD_BYPASS_HISTORY:
+-    case LOAD_ERROR_PAGE:
+-      docShellLoadType = nsIDocShellLoadInfo::loadBypassHistory;
+-      break;
+-    case LOAD_STOP_CONTENT:
+-      docShellLoadType = nsIDocShellLoadInfo::loadStopContent;
+-      break;
+-    case LOAD_STOP_CONTENT_AND_REPLACE:
+-      docShellLoadType = nsIDocShellLoadInfo::loadStopContentAndReplace;
+-      break;
+-    case LOAD_PUSHSTATE:
+-      docShellLoadType = nsIDocShellLoadInfo::loadPushState;
+-      break;
+-    case LOAD_REPLACE_BYPASS_CACHE:
+-      docShellLoadType = nsIDocShellLoadInfo::loadReplaceBypassCache;
+-      break;
+-    case LOAD_RELOAD_ALLOW_MIXED_CONTENT:
+-      docShellLoadType = nsIDocShellLoadInfo::loadReloadMixedContent;
+-      break;
+-    default:
+-      NS_NOTREACHED("Unexpected load type value");
+-  }
+-
+-  return docShellLoadType;
+-}
+-
+ NS_IMETHODIMP
+ nsDocShell::LoadURI(nsIURI* aURI,
+                     nsIDocShellLoadInfo* aLoadInfo,
+                     uint32_t aLoadFlags,
+                     bool aFirstParty)
+ {
+   NS_PRECONDITION(aLoadInfo || (aLoadFlags & EXTRA_LOAD_FLAGS) == 0,
+                   "Unexpected flags");
+@@ -933,17 +717,17 @@ nsDocShell::LoadURI(nsIURI* aURI,
+     aLoadInfo->GetReferrer(getter_AddRefs(referrer));
+     aLoadInfo->GetOriginalURI(getter_AddRefs(originalURI));
+     GetMaybeResultPrincipalURI(aLoadInfo, resultPrincipalURI);
+     aLoadInfo->GetKeepResultPrincipalURIIfSet(&keepResultPrincipalURIIfSet);
+     aLoadInfo->GetLoadReplace(&loadReplace);
+     nsDocShellInfoLoadType lt = nsIDocShellLoadInfo::loadNormal;
+     aLoadInfo->GetLoadType(&lt);
+     // Get the appropriate loadType from nsIDocShellLoadInfo type
+-    loadType = ConvertDocShellLoadInfoToLoadType(lt);
++    loadType = ConvertDocShellInfoLoadTypeToLoadType(lt);
+ 
+     aLoadInfo->GetTriggeringPrincipal(getter_AddRefs(triggeringPrincipal));
+     aLoadInfo->GetInheritPrincipal(&inheritPrincipal);
+     aLoadInfo->GetPrincipalIsExplicit(&principalIsExplicit);
+     aLoadInfo->GetSHEntry(getter_AddRefs(shEntry));
+     aLoadInfo->GetTarget(getter_Copies(target));
+     aLoadInfo->GetPostDataStream(getter_AddRefs(postStream));
+     aLoadInfo->GetHeadersStream(getter_AddRefs(headersStream));
+@@ -1277,17 +1061,17 @@ nsDocShell::LoadStream(nsIInputStream* a
+   }
+ 
+   uint32_t loadType = LOAD_NORMAL;
+   nsCOMPtr<nsIPrincipal> triggeringPrincipal;
+   if (aLoadInfo) {
+     nsDocShellInfoLoadType lt = nsIDocShellLoadInfo::loadNormal;
+     (void)aLoadInfo->GetLoadType(&lt);
+     // Get the appropriate LoadType from nsIDocShellLoadInfo type
+-    loadType = ConvertDocShellLoadInfoToLoadType(lt);
++    loadType = ConvertDocShellInfoLoadTypeToLoadType(lt);
+     aLoadInfo->GetTriggeringPrincipal(getter_AddRefs(triggeringPrincipal));
+   }
+ 
+   NS_ENSURE_SUCCESS(Stop(nsIWebNavigation::STOP_NETWORK), NS_ERROR_FAILURE);
+ 
+   mLoadType = loadType;
+ 
+   if (!triggeringPrincipal) {
+@@ -4612,17 +4396,17 @@ nsDocShell::LoadURIWithOptions(const cha
+     popupState = openOverridden;
+   }
+   nsAutoPopupStatePusher statePusher(popupState);
+ 
+   bool forceAllowDataURI =
+     aLoadFlags & LOAD_FLAGS_FORCE_ALLOW_DATA_URI;
+ 
+   // Don't pass certain flags that aren't needed and end up confusing
+-  // ConvertLoadTypeToDocShellLoadInfo.  We do need to ensure that they are
++  // 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;
+ 
+   nsCOMPtr<nsIDocShellLoadInfo> loadInfo;
+   rv = CreateLoadInfo(getter_AddRefs(loadInfo));
+   if (NS_FAILED(rv)) {
+     return rv;
+@@ -4634,17 +4418,17 @@ nsDocShell::LoadURIWithOptions(const cha
+    */
+   uint32_t loadType;
+   if (aLoadFlags & LOAD_FLAGS_ALLOW_MIXED_CONTENT) {
+     loadType = MAKE_LOAD_TYPE(LOAD_NORMAL_ALLOW_MIXED_CONTENT, aLoadFlags);
+   } else {
+     loadType = MAKE_LOAD_TYPE(LOAD_NORMAL, aLoadFlags);
+   }
+ 
+-  loadInfo->SetLoadType(ConvertLoadTypeToDocShellLoadInfo(loadType));
++  loadInfo->SetLoadType(ConvertLoadTypeToDocShellInfoLoadType(loadType));
+   loadInfo->SetPostDataStream(postStream);
+   loadInfo->SetReferrer(aReferringURI);
+   loadInfo->SetReferrerPolicy(aReferrerPolicy);
+   loadInfo->SetHeadersStream(aHeaderStream);
+   loadInfo->SetBaseURI(aBaseURI);
+   loadInfo->SetTriggeringPrincipal(aTriggeringPrincipal);
+   loadInfo->SetForceAllowDataURI(forceAllowDataURI);
+ 
+@@ -9823,17 +9607,17 @@ nsDocShell::InternalLoad(nsIURI* aURI,
+         loadInfo->SetKeepResultPrincipalURIIfSet(aKeepResultPrincipalURIIfSet);
+         loadInfo->SetLoadReplace(aLoadReplace);
+         loadInfo->SetTriggeringPrincipal(aTriggeringPrincipal);
+         loadInfo->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(ConvertLoadTypeToDocShellLoadInfo(LOAD_LINK));
++        loadInfo->SetLoadType(ConvertLoadTypeToDocShellInfoLoadType(LOAD_LINK));
+         loadInfo->SetForceAllowDataURI(aFlags & INTERNAL_LOAD_FLAGS_FORCE_ALLOW_DATA_URI);
+ 
+         rv = win->Open(NS_ConvertUTF8toUTF16(spec),
+                        aWindowTarget, // window name
+                        EmptyString(), // Features
+                        loadInfo,
+                        true, // aForceNoOpener
+                        getter_AddRefs(newWin));
+diff --git a/docshell/base/nsDocShell.h b/docshell/base/nsDocShell.h
+--- a/docshell/base/nsDocShell.h
++++ b/docshell/base/nsDocShell.h
+@@ -226,20 +226,16 @@ public:
+                              nsIDocShell** aDocShell = 0,
+                              nsIRequest** aRequest = 0,
+                              nsIPrincipal* aTriggeringPrincipal = nullptr) override;
+   NS_IMETHOD OnOverLink(nsIContent* aContent,
+                         nsIURI* aURI,
+                         const char16_t* aTargetSpec) override;
+   NS_IMETHOD OnLeaveLink() override;
+ 
+-  nsDocShellInfoLoadType ConvertLoadTypeToDocShellLoadInfo(uint32_t aLoadType);
+-  uint32_t ConvertDocShellLoadInfoToLoadType(
+-    nsDocShellInfoLoadType aDocShellLoadType);
+-
+   // Don't use NS_DECL_NSILOADCONTEXT because some of nsILoadContext's methods
+   // are shared with nsIDocShell (appID, etc.) and can't be declared twice.
+   NS_IMETHOD GetAssociatedWindow(mozIDOMWindowProxy**) override;
+   NS_IMETHOD GetTopWindow(mozIDOMWindowProxy**) override;
+   NS_IMETHOD GetTopFrameElement(nsIDOMElement**) override;
+   NS_IMETHOD GetNestedFrameId(uint64_t*) override;
+   NS_IMETHOD GetIsContent(bool*) override;
+   NS_IMETHOD GetUsePrivateBrowsing(bool*) override;
+diff --git a/docshell/base/nsDocShellLoadTypes.h b/docshell/base/nsDocShellLoadTypes.h
+--- a/docshell/base/nsDocShellLoadTypes.h
++++ b/docshell/base/nsDocShellLoadTypes.h
+@@ -4,17 +4,19 @@
+  * 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 nsDocShellLoadTypes_h_
+ #define nsDocShellLoadTypes_h_
+ 
+ #ifdef MOZILLA_INTERNAL_API
+ 
++#include "nsDOMNavigationTiming.h"
+ #include "nsIDocShell.h"
++#include "nsIDocShellLoadInfo.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
+ 
+@@ -67,16 +69,17 @@ enum LoadType
+    * Docshell. Instead, Docshell triggers the load itself when a
+    * consumer-triggered load failed.
+    */
+   LOAD_ERROR_PAGE = MAKE_LOAD_TYPE(nsIDocShell::LOAD_CMD_NORMAL,
+                                    LOAD_FLAGS_ERROR_PAGE)
+ 
+   // NOTE: Adding a new value? Remember to update IsValidLoadType!
+ };
++
+ static inline bool
+ IsValidLoadType(uint32_t aLoadType)
+ {
+   switch (aLoadType) {
+     case LOAD_NORMAL:
+     case LOAD_NORMAL_REPLACE:
+     case LOAD_NORMAL_EXTERNAL:
+     case LOAD_NORMAL_BYPASS_CACHE:
+@@ -112,10 +115,224 @@ IsForceReloadType(uint32_t aLoadType) {
+     case LOAD_RELOAD_BYPASS_PROXY:
+     case LOAD_RELOAD_BYPASS_PROXY_AND_CACHE:
+     case LOAD_RELOAD_ALLOW_MIXED_CONTENT:
+       return true;
+   }
+   return false;
+ }
+ 
++static inline nsDocShellInfoLoadType
++ConvertLoadTypeToDocShellInfoLoadType(uint32_t aLoadType)
++{
++  nsDocShellInfoLoadType docShellLoadType = nsIDocShellLoadInfo::loadNormal;
++  switch (aLoadType) {
++    case LOAD_NORMAL:
++      docShellLoadType = nsIDocShellLoadInfo::loadNormal;
++      break;
++    case LOAD_NORMAL_REPLACE:
++      docShellLoadType = nsIDocShellLoadInfo::loadNormalReplace;
++      break;
++    case LOAD_NORMAL_EXTERNAL:
++      docShellLoadType = nsIDocShellLoadInfo::loadNormalExternal;
++      break;
++    case LOAD_NORMAL_BYPASS_CACHE:
++      docShellLoadType = nsIDocShellLoadInfo::loadNormalBypassCache;
++      break;
++    case LOAD_NORMAL_BYPASS_PROXY:
++      docShellLoadType = nsIDocShellLoadInfo::loadNormalBypassProxy;
++      break;
++    case LOAD_NORMAL_BYPASS_PROXY_AND_CACHE:
++      docShellLoadType = nsIDocShellLoadInfo::loadNormalBypassProxyAndCache;
++      break;
++    case LOAD_NORMAL_ALLOW_MIXED_CONTENT:
++      docShellLoadType = nsIDocShellLoadInfo::loadNormalAllowMixedContent;
++      break;
++    case LOAD_HISTORY:
++      docShellLoadType = nsIDocShellLoadInfo::loadHistory;
++      break;
++    case LOAD_RELOAD_NORMAL:
++      docShellLoadType = nsIDocShellLoadInfo::loadReloadNormal;
++      break;
++    case LOAD_RELOAD_CHARSET_CHANGE:
++      docShellLoadType = nsIDocShellLoadInfo::loadReloadCharsetChange;
++      break;
++    case LOAD_RELOAD_CHARSET_CHANGE_BYPASS_CACHE:
++      docShellLoadType = nsIDocShellLoadInfo::loadReloadCharsetChangeBypassCache;
++      break;
++    case LOAD_RELOAD_CHARSET_CHANGE_BYPASS_PROXY_AND_CACHE:
++      docShellLoadType = nsIDocShellLoadInfo::loadReloadCharsetChangeBypassProxyAndCache;
++      break;
++    case LOAD_RELOAD_BYPASS_CACHE:
++      docShellLoadType = nsIDocShellLoadInfo::loadReloadBypassCache;
++      break;
++    case LOAD_RELOAD_BYPASS_PROXY:
++      docShellLoadType = nsIDocShellLoadInfo::loadReloadBypassProxy;
++      break;
++    case LOAD_RELOAD_BYPASS_PROXY_AND_CACHE:
++      docShellLoadType = nsIDocShellLoadInfo::loadReloadBypassProxyAndCache;
++      break;
++    case LOAD_LINK:
++      docShellLoadType = nsIDocShellLoadInfo::loadLink;
++      break;
++    case LOAD_REFRESH:
++      docShellLoadType = nsIDocShellLoadInfo::loadRefresh;
++      break;
++    case LOAD_BYPASS_HISTORY:
++    case LOAD_ERROR_PAGE:
++      docShellLoadType = nsIDocShellLoadInfo::loadBypassHistory;
++      break;
++    case LOAD_STOP_CONTENT:
++      docShellLoadType = nsIDocShellLoadInfo::loadStopContent;
++      break;
++    case LOAD_STOP_CONTENT_AND_REPLACE:
++      docShellLoadType = nsIDocShellLoadInfo::loadStopContentAndReplace;
++      break;
++    case LOAD_PUSHSTATE:
++      docShellLoadType = nsIDocShellLoadInfo::loadPushState;
++      break;
++    case LOAD_REPLACE_BYPASS_CACHE:
++      docShellLoadType = nsIDocShellLoadInfo::loadReplaceBypassCache;
++      break;
++    case LOAD_RELOAD_ALLOW_MIXED_CONTENT:
++      docShellLoadType = nsIDocShellLoadInfo::loadReloadMixedContent;
++      break;
++    default:
++      NS_NOTREACHED("Unexpected load type value");
++  }
++
++  return docShellLoadType;
++}
++
++static inline uint32_t
++ConvertDocShellInfoLoadTypeToLoadType(nsDocShellInfoLoadType aDocShellLoadType)
++{
++  uint32_t loadType = LOAD_NORMAL;
++
++  switch (aDocShellLoadType) {
++    case nsIDocShellLoadInfo::loadNormal:
++      loadType = LOAD_NORMAL;
++      break;
++    case nsIDocShellLoadInfo::loadNormalReplace:
++      loadType = LOAD_NORMAL_REPLACE;
++      break;
++    case nsIDocShellLoadInfo::loadNormalExternal:
++      loadType = LOAD_NORMAL_EXTERNAL;
++      break;
++    case nsIDocShellLoadInfo::loadHistory:
++      loadType = LOAD_HISTORY;
++      break;
++    case nsIDocShellLoadInfo::loadNormalBypassCache:
++      loadType = LOAD_NORMAL_BYPASS_CACHE;
++      break;
++    case nsIDocShellLoadInfo::loadNormalBypassProxy:
++      loadType = LOAD_NORMAL_BYPASS_PROXY;
++      break;
++    case nsIDocShellLoadInfo::loadNormalBypassProxyAndCache:
++      loadType = LOAD_NORMAL_BYPASS_PROXY_AND_CACHE;
++      break;
++    case nsIDocShellLoadInfo::loadNormalAllowMixedContent:
++      loadType = LOAD_NORMAL_ALLOW_MIXED_CONTENT;
++      break;
++    case nsIDocShellLoadInfo::loadReloadNormal:
++      loadType = LOAD_RELOAD_NORMAL;
++      break;
++    case nsIDocShellLoadInfo::loadReloadCharsetChange:
++      loadType = LOAD_RELOAD_CHARSET_CHANGE;
++      break;
++    case nsIDocShellLoadInfo::loadReloadCharsetChangeBypassCache:
++      loadType = LOAD_RELOAD_CHARSET_CHANGE_BYPASS_CACHE;
++      break;
++    case nsIDocShellLoadInfo::loadReloadCharsetChangeBypassProxyAndCache:
++      loadType = LOAD_RELOAD_CHARSET_CHANGE_BYPASS_PROXY_AND_CACHE;
++      break;
++    case nsIDocShellLoadInfo::loadReloadBypassCache:
++      loadType = LOAD_RELOAD_BYPASS_CACHE;
++      break;
++    case nsIDocShellLoadInfo::loadReloadBypassProxy:
++      loadType = LOAD_RELOAD_BYPASS_PROXY;
++      break;
++    case nsIDocShellLoadInfo::loadReloadBypassProxyAndCache:
++      loadType = LOAD_RELOAD_BYPASS_PROXY_AND_CACHE;
++      break;
++    case nsIDocShellLoadInfo::loadLink:
++      loadType = LOAD_LINK;
++      break;
++    case nsIDocShellLoadInfo::loadRefresh:
++      loadType = LOAD_REFRESH;
++      break;
++    case nsIDocShellLoadInfo::loadBypassHistory:
++      loadType = LOAD_BYPASS_HISTORY;
++      break;
++    case nsIDocShellLoadInfo::loadStopContent:
++      loadType = LOAD_STOP_CONTENT;
++      break;
++    case nsIDocShellLoadInfo::loadStopContentAndReplace:
++      loadType = LOAD_STOP_CONTENT_AND_REPLACE;
++      break;
++    case nsIDocShellLoadInfo::loadPushState:
++      loadType = LOAD_PUSHSTATE;
++      break;
++    case nsIDocShellLoadInfo::loadReplaceBypassCache:
++      loadType = LOAD_REPLACE_BYPASS_CACHE;
++      break;
++    case nsIDocShellLoadInfo::loadReloadMixedContent:
++      loadType = LOAD_RELOAD_ALLOW_MIXED_CONTENT;
++      break;
++    default:
++      NS_NOTREACHED("Unexpected nsDocShellInfoLoadType value");
++  }
++
++  return loadType;
++}
++
++static inline nsDOMNavigationTiming::Type
++ConvertLoadTypeToNavigationType(uint32_t aLoadType)
++{
++  // Not initialized, assume it's normal load.
++  if (aLoadType == 0) {
++    aLoadType = LOAD_NORMAL;
++  }
++
++  auto result = nsDOMNavigationTiming::TYPE_RESERVED;
++  switch (aLoadType) {
++    case LOAD_NORMAL:
++    case LOAD_NORMAL_EXTERNAL:
++    case LOAD_NORMAL_BYPASS_CACHE:
++    case LOAD_NORMAL_BYPASS_PROXY:
++    case LOAD_NORMAL_BYPASS_PROXY_AND_CACHE:
++    case LOAD_NORMAL_REPLACE:
++    case LOAD_NORMAL_ALLOW_MIXED_CONTENT:
++    case LOAD_LINK:
++    case LOAD_STOP_CONTENT:
++    case LOAD_REPLACE_BYPASS_CACHE:
++      result = nsDOMNavigationTiming::TYPE_NAVIGATE;
++      break;
++    case LOAD_HISTORY:
++      result = nsDOMNavigationTiming::TYPE_BACK_FORWARD;
++      break;
++    case LOAD_RELOAD_NORMAL:
++    case LOAD_RELOAD_CHARSET_CHANGE:
++    case LOAD_RELOAD_CHARSET_CHANGE_BYPASS_PROXY_AND_CACHE:
++    case LOAD_RELOAD_CHARSET_CHANGE_BYPASS_CACHE:
++    case LOAD_RELOAD_BYPASS_CACHE:
++    case LOAD_RELOAD_BYPASS_PROXY:
++    case LOAD_RELOAD_BYPASS_PROXY_AND_CACHE:
++    case LOAD_RELOAD_ALLOW_MIXED_CONTENT:
++      result = nsDOMNavigationTiming::TYPE_RELOAD;
++      break;
++    case LOAD_STOP_CONTENT_AND_REPLACE:
++    case LOAD_REFRESH:
++    case LOAD_BYPASS_HISTORY:
++    case LOAD_ERROR_PAGE:
++    case LOAD_PUSHSTATE:
++      result = nsDOMNavigationTiming::TYPE_RESERVED;
++      break;
++    default:
++      result = nsDOMNavigationTiming::TYPE_RESERVED;
++      break;
++  }
++
++  return result;
++}
++
+ #endif // MOZILLA_INTERNAL_API
+ #endif

+ 814 - 0
mozilla-release/patches/1406161-6-59a1.patch

@@ -0,0 +1,814 @@
+# HG changeset patch
+# User Samael Wang <freesamael@gmail.com>
+# Date 1513679196 -28800
+# Node ID 4a7086f02b605337d91e9ca877faec138c83c02a
+# Parent  4e07700d7f0aaa411bf0a3e5496f403069817464
+Bug 1406161 - Part 6: Move shistory related static functions to nsSHistory. r=smaug
+
+MozReview-Commit-ID: 7rqo2rISCB5
+
+diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp
+--- a/docshell/base/nsDocShell.cpp
++++ b/docshell/base/nsDocShell.cpp
+@@ -275,18 +275,16 @@ FavorPerformanceHint(bool aPerfOverStarv
+   if (appShell) {
+     appShell->FavorPerformanceHint(
+       aPerfOverStarvation,
+       Preferences::GetUint("docshell.event_starvation_delay_hint",
+                            NS_EVENT_STARVATION_DELAY_HINT));
+   }
+ }
+ 
+-static nsISHEntry* GetRootSHEntry(nsISHEntry* aEntry);
+-
+ static void
+ IncreasePrivateDocShellCount()
+ {
+   gNumberOfPrivateDocShells++;
+   if (gNumberOfPrivateDocShells > 1 ||
+       !XRE_IsContentProcess()) {
+     return;
+   }
+@@ -3958,18 +3956,18 @@ nsDocShell::AddChildSHEntryInternal(nsIS
+                                           getter_AddRefs(currentHE));
+     NS_ENSURE_TRUE(currentHE, NS_ERROR_FAILURE);
+ 
+     nsCOMPtr<nsISHEntry> currentEntry(do_QueryInterface(currentHE));
+     if (currentEntry) {
+       uint32_t cloneID = 0;
+       nsCOMPtr<nsISHEntry> nextEntry;
+       aCloneRef->GetID(&cloneID);
+-      rv = CloneAndReplace(currentEntry, this, cloneID, aNewEntry,
+-                           aCloneChildren, getter_AddRefs(nextEntry));
++      rv = nsSHistory::CloneAndReplace(currentEntry, this, cloneID,
++        aNewEntry, aCloneChildren, getter_AddRefs(nextEntry));
+ 
+       if (NS_SUCCEEDED(rv)) {
+         nsCOMPtr<nsISHistoryInternal> shPrivate =
+           do_QueryInterface(mSessionHistory);
+         NS_ENSURE_TRUE(shPrivate, NS_ERROR_FAILURE);
+         rv = shPrivate->AddEntry(nextEntry, true);
+       }
+     }
+@@ -11861,17 +11859,17 @@ nsDocShell::AddState(JS::Handle<JS::Valu
+ 
+   if (!aReplace) {
+     int32_t curIndex = -1;
+     rv = rootSH->GetIndex(&curIndex);
+     if (NS_SUCCEEDED(rv) && curIndex > -1) {
+       internalSH->EvictOutOfRangeContentViewers(curIndex);
+     }
+   } else {
+-    nsCOMPtr<nsISHEntry> rootSHEntry = GetRootSHEntry(newSHEntry);
++    nsCOMPtr<nsISHEntry> rootSHEntry = nsSHistory::GetRootSHEntry(newSHEntry);
+ 
+     int32_t index = -1;
+     rv = rootSH->GetIndexOfEntry(rootSHEntry, &index);
+     if (NS_SUCCEEDED(rv) && index > -1) {
+       internalSH->ReplaceEntry(index, rootSHEntry);
+     }
+   }
+ 
+@@ -12161,18 +12159,18 @@ nsDocShell::AddToSessionHistory(nsIURI* 
+ 
+   if (root == static_cast<nsIDocShellTreeItem*>(this) && mSessionHistory) {
+     // If we need to clone our children onto the new session
+     // history entry, do so now.
+     if (aCloneChildren && mOSHE) {
+       uint32_t cloneID;
+       mOSHE->GetID(&cloneID);
+       nsCOMPtr<nsISHEntry> newEntry;
+-      CloneAndReplace(mOSHE, this, cloneID, entry, true,
+-                      getter_AddRefs(newEntry));
++      nsSHistory::CloneAndReplace(mOSHE, this, cloneID, entry, true,
++                                  getter_AddRefs(newEntry));
+       NS_ASSERTION(entry == newEntry,
+                    "The new session history should be in the new entry");
+     }
+ 
+     // This is the root docshell
+     bool addToSHistory = !LOAD_TYPE_HAS_FLAGS(mLoadType, LOAD_FLAGS_REPLACE_HISTORY);
+     if (!addToSHistory) {
+       // Replace current entry in session history; If the requested index is
+@@ -12407,275 +12405,59 @@ nsDocShell::PersistLayoutHistoryState()
+     if (scrollRestorationIsManual && layoutState) {
+       layoutState->ResetScrollState();
+     }
+   }
+ 
+   return rv;
+ }
+ 
+-/* static */ nsresult
+-nsDocShell::WalkHistoryEntries(nsISHEntry* aRootEntry,
+-                               nsDocShell* aRootShell,
+-                               WalkHistoryEntriesFunc aCallback,
+-                               void* aData)
+-{
+-  NS_ENSURE_TRUE(aRootEntry, NS_ERROR_FAILURE);
+-
+-  nsCOMPtr<nsISHContainer> container(do_QueryInterface(aRootEntry));
+-  if (!container) {
+-    return NS_ERROR_FAILURE;
+-  }
+-
+-  int32_t childCount;
+-  container->GetChildCount(&childCount);
+-  for (int32_t i = 0; i < childCount; i++) {
+-    nsCOMPtr<nsISHEntry> childEntry;
+-    container->GetChildAt(i, getter_AddRefs(childEntry));
+-    if (!childEntry) {
+-      // childEntry can be null for valid reasons, for example if the
+-      // docshell at index i never loaded anything useful.
+-      // Remember to clone also nulls in the child array (bug 464064).
+-      aCallback(nullptr, nullptr, i, aData);
+-      continue;
+-    }
+-
+-    nsDocShell* childShell = nullptr;
+-    if (aRootShell) {
+-      // Walk the children of aRootShell and see if one of them
+-      // has srcChild as a SHEntry.
+-      nsTObserverArray<nsDocLoader*>::ForwardIterator iter(
+-        aRootShell->mChildList);
+-      while (iter.HasMore()) {
+-        nsDocShell* child = static_cast<nsDocShell*>(iter.GetNext());
+-
+-        if (child->HasHistoryEntry(childEntry)) {
+-          childShell = child;
+-          break;
+-        }
+-      }
+-    }
+-    nsresult rv = aCallback(childEntry, childShell, i, aData);
+-    NS_ENSURE_SUCCESS(rv, rv);
+-  }
+-
+-  return NS_OK;
+-}
+-
+-// callback data for WalkHistoryEntries
+-struct MOZ_STACK_CLASS CloneAndReplaceData
+-{
+-  CloneAndReplaceData(uint32_t aCloneID, nsISHEntry* aReplaceEntry,
+-                      bool aCloneChildren, nsISHEntry* aDestTreeParent)
+-    : cloneID(aCloneID)
+-    , cloneChildren(aCloneChildren)
+-    , replaceEntry(aReplaceEntry)
+-    , destTreeParent(aDestTreeParent)
+-  {
+-  }
+-
+-  uint32_t cloneID;
+-  bool cloneChildren;
+-  nsISHEntry* replaceEntry;
+-  nsISHEntry* destTreeParent;
+-  nsCOMPtr<nsISHEntry> resultEntry;
+-};
+-
+-/* static */ nsresult
+-nsDocShell::CloneAndReplaceChild(nsISHEntry* aEntry, nsDocShell* aShell,
+-                                 int32_t aEntryIndex, void* aData)
+-{
+-  nsCOMPtr<nsISHEntry> dest;
+-
+-  CloneAndReplaceData* data = static_cast<CloneAndReplaceData*>(aData);
+-  uint32_t cloneID = data->cloneID;
+-  nsISHEntry* replaceEntry = data->replaceEntry;
+-
+-  nsCOMPtr<nsISHContainer> container = do_QueryInterface(data->destTreeParent);
+-  if (!aEntry) {
+-    if (container) {
+-      container->AddChild(nullptr, aEntryIndex);
+-    }
+-    return NS_OK;
+-  }
+-
+-  uint32_t srcID;
+-  aEntry->GetID(&srcID);
+-
+-  nsresult rv = NS_OK;
+-  if (srcID == cloneID) {
+-    // Replace the entry
+-    dest = replaceEntry;
+-  } else {
+-    // Clone the SHEntry...
+-    rv = aEntry->Clone(getter_AddRefs(dest));
+-    NS_ENSURE_SUCCESS(rv, rv);
+-  }
+-  dest->SetIsSubFrame(true);
+-
+-  if (srcID != cloneID || data->cloneChildren) {
+-    // Walk the children
+-    CloneAndReplaceData childData(cloneID, replaceEntry,
+-                                  data->cloneChildren, dest);
+-    rv = WalkHistoryEntries(aEntry, aShell,
+-                            CloneAndReplaceChild, &childData);
+-    NS_ENSURE_SUCCESS(rv, rv);
+-  }
+-
+-  if (srcID != cloneID && aShell) {
+-    aShell->SwapHistoryEntries(aEntry, dest);
+-  }
+-
+-  if (container) {
+-    container->AddChild(dest, aEntryIndex);
+-  }
+-
+-  data->resultEntry = dest;
+-  return rv;
+-}
+-
+-/* static */ nsresult
+-nsDocShell::CloneAndReplace(nsISHEntry* aSrcEntry,
+-                            nsDocShell* aSrcShell,
+-                            uint32_t aCloneID,
+-                            nsISHEntry* aReplaceEntry,
+-                            bool aCloneChildren,
+-                            nsISHEntry** aResultEntry)
+-{
+-  NS_ENSURE_ARG_POINTER(aResultEntry);
+-  NS_ENSURE_TRUE(aReplaceEntry, NS_ERROR_FAILURE);
+-
+-  CloneAndReplaceData data(aCloneID, aReplaceEntry, aCloneChildren, nullptr);
+-  nsresult rv = CloneAndReplaceChild(aSrcEntry, aSrcShell, 0, &data);
+-
+-  data.resultEntry.swap(*aResultEntry);
+-  return rv;
+-}
+-
+ void
+ nsDocShell::SwapHistoryEntries(nsISHEntry* aOldEntry, nsISHEntry* aNewEntry)
+ {
+   if (aOldEntry == mOSHE) {
+     mOSHE = aNewEntry;
+   }
+ 
+   if (aOldEntry == mLSHE) {
+     mLSHE = aNewEntry;
+   }
+ }
+ 
+-struct SwapEntriesData
+-{
+-  nsDocShell* ignoreShell;     // constant; the shell to ignore
+-  nsISHEntry* destTreeRoot;    // constant; the root of the dest tree
+-  nsISHEntry* destTreeParent;  // constant; the node under destTreeRoot
+-                               // whose children will correspond to aEntry
+-};
+-
+-nsresult
+-nsDocShell::SetChildHistoryEntry(nsISHEntry* aEntry, nsDocShell* aShell,
+-                                 int32_t aEntryIndex, void* aData)
+-{
+-  SwapEntriesData* data = static_cast<SwapEntriesData*>(aData);
+-  nsDocShell* ignoreShell = data->ignoreShell;
+-
+-  if (!aShell || aShell == ignoreShell) {
+-    return NS_OK;
+-  }
+-
+-  nsISHEntry* destTreeRoot = data->destTreeRoot;
+-
+-  nsCOMPtr<nsISHEntry> destEntry;
+-  nsCOMPtr<nsISHContainer> container = do_QueryInterface(data->destTreeParent);
+-
+-  if (container) {
+-    // aEntry is a clone of some child of destTreeParent, but since the
+-    // trees aren't necessarily in sync, we'll have to locate it.
+-    // Note that we could set aShell's entry to null if we don't find a
+-    // corresponding entry under destTreeParent.
+-
+-    uint32_t targetID, id;
+-    aEntry->GetID(&targetID);
+-
+-    // First look at the given index, since this is the common case.
+-    nsCOMPtr<nsISHEntry> entry;
+-    container->GetChildAt(aEntryIndex, getter_AddRefs(entry));
+-    if (entry && NS_SUCCEEDED(entry->GetID(&id)) && id == targetID) {
+-      destEntry.swap(entry);
+-    } else {
+-      int32_t childCount;
+-      container->GetChildCount(&childCount);
+-      for (int32_t i = 0; i < childCount; ++i) {
+-        container->GetChildAt(i, getter_AddRefs(entry));
+-        if (!entry) {
+-          continue;
+-        }
+-
+-        entry->GetID(&id);
+-        if (id == targetID) {
+-          destEntry.swap(entry);
+-          break;
+-        }
+-      }
+-    }
+-  } else {
+-    destEntry = destTreeRoot;
+-  }
+-
+-  aShell->SwapHistoryEntries(aEntry, destEntry);
+-
+-  // Now handle the children of aEntry.
+-  SwapEntriesData childData = { ignoreShell, destTreeRoot, destEntry };
+-  return WalkHistoryEntries(aEntry, aShell, SetChildHistoryEntry, &childData);
+-}
+-
+-static nsISHEntry*
+-GetRootSHEntry(nsISHEntry* aEntry)
+-{
+-  nsCOMPtr<nsISHEntry> rootEntry = aEntry;
+-  nsISHEntry* result = nullptr;
+-  while (rootEntry) {
+-    result = rootEntry;
+-    result->GetParent(getter_AddRefs(rootEntry));
+-  }
+-
+-  return result;
+-}
+-
+ void
+ nsDocShell::SetHistoryEntry(nsCOMPtr<nsISHEntry>* aPtr, nsISHEntry* aEntry)
+ {
+   // We need to sync up the docshell and session history trees for
+   // subframe navigation.  If the load was in a subframe, we forward up to
+   // the root docshell, which will then recursively sync up all docshells
+   // to their corresponding entries in the new session history tree.
+   // If we don't do this, then we can cache a content viewer on the wrong
+   // cloned entry, and subsequently restore it at the wrong time.
+ 
+-  nsISHEntry* newRootEntry = GetRootSHEntry(aEntry);
++  nsISHEntry* newRootEntry = nsSHistory::GetRootSHEntry(aEntry);
+   if (newRootEntry) {
+     // newRootEntry is now the new root entry.
+     // Find the old root entry as well.
+ 
+     // Need a strong ref. on |oldRootEntry| so it isn't destroyed when
+     // SetChildHistoryEntry() does SwapHistoryEntries() (bug 304639).
+-    nsCOMPtr<nsISHEntry> oldRootEntry = GetRootSHEntry(*aPtr);
++    nsCOMPtr<nsISHEntry> oldRootEntry = nsSHistory::GetRootSHEntry(*aPtr);
+     if (oldRootEntry) {
+       nsCOMPtr<nsIDocShellTreeItem> rootAsItem;
+       GetSameTypeRootTreeItem(getter_AddRefs(rootAsItem));
+       nsCOMPtr<nsIDocShell> rootShell = do_QueryInterface(rootAsItem);
+       if (rootShell) { // if we're the root just set it, nothing to swap
+-        SwapEntriesData data = { this, newRootEntry };
++        nsSHistory::SwapEntriesData data = { this, newRootEntry };
+         nsIDocShell* rootIDocShell = static_cast<nsIDocShell*>(rootShell);
+         nsDocShell* rootDocShell = static_cast<nsDocShell*>(rootIDocShell);
+ 
+ #ifdef DEBUG
+         nsresult rv =
+ #endif
+-        SetChildHistoryEntry(oldRootEntry, rootDocShell, 0, &data);
++        nsSHistory::SetChildHistoryEntry(oldRootEntry, rootDocShell, 0, &data);
+         NS_ASSERTION(NS_SUCCEEDED(rv), "SetChildHistoryEntry failed");
+       }
+     }
+   }
+ 
+   *aPtr = aEntry;
+ }
+ 
+diff --git a/docshell/base/nsDocShell.h b/docshell/base/nsDocShell.h
+--- a/docshell/base/nsDocShell.h
++++ b/docshell/base/nsDocShell.h
+@@ -349,16 +349,26 @@ public:
+     mAncestorOuterWindowIDs = mozilla::Move(aAncestorOuterWindowIDs);
+   }
+ 
+   const mozilla::OriginAttributes& GetOriginAttributes()
+   {
+     return mOriginAttributes;
+   }
+ 
++  // Determine whether this docshell corresponds to the given history entry,
++  // via having a pointer to it in mOSHE or mLSHE.
++  bool HasHistoryEntry(nsISHEntry* aEntry) const
++  {
++    return aEntry && (aEntry == mOSHE || aEntry == mLSHE);
++  }
++
++  // Update any pointers (mOSHE or mLSHE) to aOldEntry to point to aNewEntry
++  void SwapHistoryEntries(nsISHEntry* aOldEntry, nsISHEntry* aNewEntry);
++
+   static bool SandboxFlagsImplyCookies(const uint32_t &aSandboxFlags);
+ 
+   // Tell the favicon service that aNewURI has the same favicon as aOldURI.
+   static void CopyFavicon(nsIURI* aOldURI,
+                           nsIURI* aNewURI,
+                           nsIPrincipal* aLoadingPrincipal,
+                           bool aInPrivateBrowsing);
+ 
+@@ -384,57 +394,16 @@ private: // member functions
+   friend void mozilla::TimelineConsumers::AddMarkerForDocShell(
+     nsDocShell*, const char*, const TimeStamp&, MarkerTracingType,
+     MarkerStackRequest);
+   friend void mozilla::TimelineConsumers::AddMarkerForDocShell(
+     nsDocShell*, UniquePtr<AbstractTimelineMarker>&&);
+   friend void mozilla::TimelineConsumers::PopMarkers(nsDocShell*,
+     JSContext*, nsTArray<dom::ProfileTimelineMarker>&);
+ 
+-  // Callback prototype for WalkHistoryEntries.
+-  // aEntry is the child history entry, aShell is its corresponding docshell,
+-  // aChildIndex is the child's index in its parent entry, and aData is
+-  // the opaque pointer passed to WalkHistoryEntries.
+-  typedef nsresult(*WalkHistoryEntriesFunc)(nsISHEntry* aEntry,
+-                                            nsDocShell* aShell,
+-                                            int32_t aChildIndex,
+-                                            void* aData);
+-
+-  // Clone a session history tree for subframe navigation.
+-  // The tree rooted at |aSrcEntry| will be cloned into |aDestEntry|, except
+-  // for the entry with id |aCloneID|, which will be replaced with
+-  // |aReplaceEntry|. |aSrcShell| is a (possibly null) docshell which
+-  // corresponds to |aSrcEntry| via its mLSHE or mOHE pointers, and will
+-  // have that pointer updated to point to the cloned history entry.
+-  // If aCloneChildren is true then the children of the entry with id
+-  // |aCloneID| will be cloned into |aReplaceEntry|.
+-  static nsresult CloneAndReplace(nsISHEntry* aSrcEntry,
+-                                  nsDocShell* aSrcShell,
+-                                  uint32_t aCloneID,
+-                                  nsISHEntry* aReplaceEntry,
+-                                  bool aCloneChildren,
+-                                  nsISHEntry** aDestEntry);
+-
+-  // Child-walking callback for CloneAndReplace
+-  static nsresult CloneAndReplaceChild(nsISHEntry* aEntry, nsDocShell* aShell,
+-                                       int32_t aChildIndex, void* aData);
+-
+-
+-  // Child-walking callback for SetHistoryEntry
+-  static nsresult SetChildHistoryEntry(nsISHEntry* aEntry, nsDocShell* aShell,
+-                                       int32_t aEntryIndex, void* aData);
+-
+-  // For each child of aRootEntry, find the corresponding docshell which is
+-  // a child of aRootShell, and call aCallback. The opaque pointer aData
+-  // is passed to the callback.
+-  static nsresult WalkHistoryEntries(nsISHEntry* aRootEntry,
+-                                     nsDocShell* aRootShell,
+-                                     WalkHistoryEntriesFunc aCallback,
+-                                     void* aData);
+-
+   // Security checks to prevent frameset spoofing. See comments at
+   // implementation sites.
+   static bool CanAccessItem(nsIDocShellTreeItem* aTargetItem,
+                             nsIDocShellTreeItem* aAccessingItem,
+                             bool aConsiderOpener = true);
+   static bool ValidateOrigin(nsIDocShellTreeItem* aOriginTreeItem,
+                              nsIDocShellTreeItem* aTargetTreeItem);
+ 
+@@ -520,26 +489,16 @@ private: // member functions
+ 
+   nsresult AddChildSHEntryToParent(nsISHEntry* aNewEntry, int32_t aChildOffset,
+                                    bool aCloneChildren);
+ 
+   nsresult AddChildSHEntryInternal(nsISHEntry* aCloneRef, nsISHEntry* aNewEntry,
+                                    int32_t aChildOffset, uint32_t aLoadType,
+                                    bool aCloneChildren);
+ 
+-  // Determine whether this docshell corresponds to the given history entry,
+-  // via having a pointer to it in mOSHE or mLSHE.
+-  bool HasHistoryEntry(nsISHEntry* aEntry) const
+-  {
+-    return aEntry && (aEntry == mOSHE || aEntry == mLSHE);
+-  }
+-
+-  // Update any pointers (mOSHE or mLSHE) to aOldEntry to point to aNewEntry
+-  void SwapHistoryEntries(nsISHEntry* aOldEntry, nsISHEntry* aNewEntry);
+-
+   // Call this method to swap in a new history entry to m[OL]SHE, rather than
+   // setting it directly. This completes the navigation in all docshells
+   // in the case of a subframe navigation.
+   void SetHistoryEntry(nsCOMPtr<nsISHEntry>* aPtr, nsISHEntry* aEntry);
+ 
+   //
+   // URI Load
+   //
+diff --git a/docshell/shistory/nsSHistory.cpp b/docshell/shistory/nsSHistory.cpp
+--- a/docshell/shistory/nsSHistory.cpp
++++ b/docshell/shistory/nsSHistory.cpp
+@@ -369,16 +369,233 @@ nsSHistory::Shutdown()
+     if (obsSvc) {
+       obsSvc->RemoveObserver(gObserver, "cacheservice:empty-cache");
+       obsSvc->RemoveObserver(gObserver, "memory-pressure");
+     }
+     gObserver = nullptr;
+   }
+ }
+ 
++// static
++nsISHEntry*
++nsSHistory::GetRootSHEntry(nsISHEntry* aEntry)
++{
++  nsCOMPtr<nsISHEntry> rootEntry = aEntry;
++  nsISHEntry* result = nullptr;
++  while (rootEntry) {
++    result = rootEntry;
++    result->GetParent(getter_AddRefs(rootEntry));
++  }
++
++  return result;
++}
++
++// static
++nsresult
++nsSHistory::WalkHistoryEntries(nsISHEntry* aRootEntry,
++                               nsDocShell* aRootShell,
++                               WalkHistoryEntriesFunc aCallback,
++                               void* aData)
++{
++  NS_ENSURE_TRUE(aRootEntry, NS_ERROR_FAILURE);
++
++  nsCOMPtr<nsISHContainer> container(do_QueryInterface(aRootEntry));
++  if (!container) {
++    return NS_ERROR_FAILURE;
++  }
++
++  int32_t childCount;
++  container->GetChildCount(&childCount);
++  for (int32_t i = 0; i < childCount; i++) {
++    nsCOMPtr<nsISHEntry> childEntry;
++    container->GetChildAt(i, getter_AddRefs(childEntry));
++    if (!childEntry) {
++      // childEntry can be null for valid reasons, for example if the
++      // docshell at index i never loaded anything useful.
++      // Remember to clone also nulls in the child array (bug 464064).
++      aCallback(nullptr, nullptr, i, aData);
++      continue;
++    }
++
++    nsDocShell* childShell = nullptr;
++    if (aRootShell) {
++      // Walk the children of aRootShell and see if one of them
++      // has srcChild as a SHEntry.
++      int32_t length;
++      aRootShell->GetChildCount(&length);
++      for (int32_t i = 0; i < length; i++) {
++        nsCOMPtr<nsIDocShellTreeItem> item;
++        nsresult rv = aRootShell->GetChildAt(i, getter_AddRefs(item));
++        NS_ENSURE_SUCCESS(rv, rv);
++        nsDocShell* child = static_cast<nsDocShell*>(item.get());
++        if (child->HasHistoryEntry(childEntry)) {
++          childShell = child;
++          break;
++        }
++      }
++    }
++    nsresult rv = aCallback(childEntry, childShell, i, aData);
++    NS_ENSURE_SUCCESS(rv, rv);
++  }
++
++  return NS_OK;
++}
++
++// callback data for WalkHistoryEntries
++struct MOZ_STACK_CLASS CloneAndReplaceData
++{
++  CloneAndReplaceData(uint32_t aCloneID, nsISHEntry* aReplaceEntry,
++                      bool aCloneChildren, nsISHEntry* aDestTreeParent)
++    : cloneID(aCloneID)
++    , cloneChildren(aCloneChildren)
++    , replaceEntry(aReplaceEntry)
++    , destTreeParent(aDestTreeParent)
++  {
++  }
++
++  uint32_t cloneID;
++  bool cloneChildren;
++  nsISHEntry* replaceEntry;
++  nsISHEntry* destTreeParent;
++  nsCOMPtr<nsISHEntry> resultEntry;
++};
++
++// static
++nsresult
++nsSHistory::CloneAndReplaceChild(nsISHEntry* aEntry,
++                                          nsDocShell* aShell,
++                                          int32_t aEntryIndex,
++                                          void* aData)
++{
++  nsCOMPtr<nsISHEntry> dest;
++
++  CloneAndReplaceData* data = static_cast<CloneAndReplaceData*>(aData);
++  uint32_t cloneID = data->cloneID;
++  nsISHEntry* replaceEntry = data->replaceEntry;
++
++  nsCOMPtr<nsISHContainer> container = do_QueryInterface(data->destTreeParent);
++  if (!aEntry) {
++    if (container) {
++      container->AddChild(nullptr, aEntryIndex);
++    }
++    return NS_OK;
++  }
++
++  uint32_t srcID;
++  aEntry->GetID(&srcID);
++
++  nsresult rv = NS_OK;
++  if (srcID == cloneID) {
++    // Replace the entry
++    dest = replaceEntry;
++  } else {
++    // Clone the SHEntry...
++    rv = aEntry->Clone(getter_AddRefs(dest));
++    NS_ENSURE_SUCCESS(rv, rv);
++  }
++  dest->SetIsSubFrame(true);
++
++  if (srcID != cloneID || data->cloneChildren) {
++    // Walk the children
++    CloneAndReplaceData childData(cloneID, replaceEntry,
++                                  data->cloneChildren, dest);
++    rv = WalkHistoryEntries(aEntry, aShell,
++                            CloneAndReplaceChild, &childData);
++    NS_ENSURE_SUCCESS(rv, rv);
++  }
++
++  if (srcID != cloneID && aShell) {
++    aShell->SwapHistoryEntries(aEntry, dest);
++  }
++
++  if (container) {
++    container->AddChild(dest, aEntryIndex);
++  }
++
++  data->resultEntry = dest;
++  return rv;
++}
++
++// static
++nsresult
++nsSHistory::CloneAndReplace(nsISHEntry* aSrcEntry,
++                                     nsDocShell* aSrcShell,
++                                     uint32_t aCloneID,
++                                     nsISHEntry* aReplaceEntry,
++                                     bool aCloneChildren,
++                                     nsISHEntry** aResultEntry)
++{
++  NS_ENSURE_ARG_POINTER(aResultEntry);
++  NS_ENSURE_TRUE(aReplaceEntry, NS_ERROR_FAILURE);
++
++  CloneAndReplaceData data(aCloneID, aReplaceEntry, aCloneChildren, nullptr);
++  nsresult rv = CloneAndReplaceChild(aSrcEntry, aSrcShell, 0, &data);
++
++  data.resultEntry.swap(*aResultEntry);
++  return rv;
++}
++
++// static
++nsresult
++nsSHistory::SetChildHistoryEntry(nsISHEntry* aEntry, nsDocShell* aShell,
++                                 int32_t aEntryIndex, void* aData)
++{
++  SwapEntriesData* data = static_cast<SwapEntriesData*>(aData);
++  nsDocShell* ignoreShell = data->ignoreShell;
++
++  if (!aShell || aShell == ignoreShell) {
++    return NS_OK;
++  }
++
++  nsISHEntry* destTreeRoot = data->destTreeRoot;
++
++  nsCOMPtr<nsISHEntry> destEntry;
++  nsCOMPtr<nsISHContainer> container = do_QueryInterface(data->destTreeParent);
++
++  if (container) {
++    // aEntry is a clone of some child of destTreeParent, but since the
++    // trees aren't necessarily in sync, we'll have to locate it.
++    // Note that we could set aShell's entry to null if we don't find a
++    // corresponding entry under destTreeParent.
++
++    uint32_t targetID, id;
++    aEntry->GetID(&targetID);
++
++    // First look at the given index, since this is the common case.
++    nsCOMPtr<nsISHEntry> entry;
++    container->GetChildAt(aEntryIndex, getter_AddRefs(entry));
++    if (entry && NS_SUCCEEDED(entry->GetID(&id)) && id == targetID) {
++      destEntry.swap(entry);
++    } else {
++      int32_t childCount;
++      container->GetChildCount(&childCount);
++      for (int32_t i = 0; i < childCount; ++i) {
++        container->GetChildAt(i, getter_AddRefs(entry));
++        if (!entry) {
++          continue;
++        }
++
++        entry->GetID(&id);
++        if (id == targetID) {
++          destEntry.swap(entry);
++          break;
++        }
++      }
++    }
++  } else {
++    destEntry = destTreeRoot;
++  }
++
++  aShell->SwapHistoryEntries(aEntry, destEntry);
++
++  // Now handle the children of aEntry.
++  SwapEntriesData childData = { ignoreShell, destTreeRoot, destEntry };
++  return WalkHistoryEntries(aEntry, aShell, SetChildHistoryEntry, &childData);
++}
++
+ /* Add an entry to the History list at mIndex and
+  * increment the index to point to the new entry
+  */
+ NS_IMETHODIMP
+ nsSHistory::AddEntry(nsISHEntry* aSHEntry, bool aPersist)
+ {
+   NS_ENSURE_ARG(aSHEntry);
+ 
+diff --git a/docshell/shistory/nsSHistory.h b/docshell/shistory/nsSHistory.h
+--- a/docshell/shistory/nsSHistory.h
++++ b/docshell/shistory/nsSHistory.h
+@@ -55,16 +55,25 @@ public:
+     }
+ 
+   private:
+     // HistoryTracker is owned by nsSHistory; it always outlives HistoryTracker
+     // so it's safe to use raw pointer here.
+     nsSHistory* mSHistory;
+   };
+ 
++  // Structure used in SetChildHistoryEntry
++  struct SwapEntriesData
++  {
++    nsDocShell* ignoreShell;     // constant; the shell to ignore
++    nsISHEntry* destTreeRoot;    // constant; the root of the dest tree
++    nsISHEntry* destTreeParent;  // constant; the node under destTreeRoot
++                                 // whose children will correspond to aEntry
++  };
++
+   nsSHistory();
+   NS_DECL_ISUPPORTS
+   NS_DECL_NSISHISTORY
+   NS_DECL_NSISHISTORYINTERNAL
+   NS_DECL_NSIWEBNAVIGATION
+ 
+   // One time initialization method called upon docshell module construction
+   static nsresult Startup();
+@@ -72,16 +81,60 @@ public:
+   static void UpdatePrefs();
+ 
+   // Max number of total cached content viewers.  If the pref
+   // browser.sessionhistory.max_total_viewers is negative, then
+   // this value is calculated based on the total amount of memory.
+   // Otherwise, it comes straight from the pref.
+   static uint32_t GetMaxTotalViewers() { return sHistoryMaxTotalViewers; }
+ 
++  // Get the root SHEntry from a given entry.
++  static nsISHEntry* GetRootSHEntry(nsISHEntry* aEntry);
++
++  // Callback prototype for WalkHistoryEntries.
++  // aEntry is the child history entry, aShell is its corresponding docshell,
++  // aChildIndex is the child's index in its parent entry, and aData is
++  // the opaque pointer passed to WalkHistoryEntries.
++  typedef nsresult(*WalkHistoryEntriesFunc)(nsISHEntry* aEntry,
++                                            nsDocShell* aShell,
++                                            int32_t aChildIndex,
++                                            void* aData);
++
++  // Clone a session history tree for subframe navigation.
++  // The tree rooted at |aSrcEntry| will be cloned into |aDestEntry|, except
++  // for the entry with id |aCloneID|, which will be replaced with
++  // |aReplaceEntry|. |aSrcShell| is a (possibly null) docshell which
++  // corresponds to |aSrcEntry| via its mLSHE or mOHE pointers, and will
++  // have that pointer updated to point to the cloned history entry.
++  // If aCloneChildren is true then the children of the entry with id
++  // |aCloneID| will be cloned into |aReplaceEntry|.
++  static nsresult CloneAndReplace(nsISHEntry* aSrcEntry,
++                                  nsDocShell* aSrcShell,
++                                  uint32_t aCloneID,
++                                  nsISHEntry* aReplaceEntry,
++                                  bool aCloneChildren,
++                                  nsISHEntry** aDestEntry);
++
++  // Child-walking callback for CloneAndReplace
++  static nsresult CloneAndReplaceChild(nsISHEntry* aEntry, nsDocShell* aShell,
++                                       int32_t aChildIndex, void* aData);
++
++
++  // Child-walking callback for SetHistoryEntry
++  static nsresult SetChildHistoryEntry(nsISHEntry* aEntry, nsDocShell* aShell,
++                                       int32_t aEntryIndex, void* aData);
++
++  // For each child of aRootEntry, find the corresponding docshell which is
++  // a child of aRootShell, and call aCallback. The opaque pointer aData
++  // is passed to the callback.
++  static nsresult WalkHistoryEntries(nsISHEntry* aRootEntry,
++                                     nsDocShell* aRootShell,
++                                     WalkHistoryEntriesFunc aCallback,
++                                     void* aData);
++
+ private:
+   virtual ~nsSHistory();
+   friend class nsSHEnumerator;
+   friend class nsSHistoryObserver;
+ 
+   nsresult GetTransactionAtIndex(int32_t aIndex, nsISHTransaction** aResult);
+   nsresult LoadDifferingEntries(nsISHEntry* aPrevEntry, nsISHEntry* aNextEntry,
+                                 nsIDocShell* aRootDocShell, long aLoadType,

+ 174 - 0
mozilla-release/patches/1424809-59a1.patch

@@ -0,0 +1,174 @@
+# HG changeset patch
+# User Andrea Marchesini <amarchesini@mozilla.com>
+# Date 1513080077 21600
+# Node ID e63b2060c206907e81c32a9f4ff79a25b2eb87b7
+# Parent  db447092bc9623c6dc5d2ce7ec3665cdadd0062f
+Bug 1424809 - Get rid of NS_NewPostDataStream, r=valentin
+
+diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp
+--- a/docshell/base/nsDocShell.cpp
++++ b/docshell/base/nsDocShell.cpp
+@@ -95,16 +95,17 @@
+ #include "nsIDocShellTreeItem.h"
+ #include "nsIChannel.h"
+ #include "IHistory.h"
+ #include "nsViewSourceHandler.h"
+ #include "nsWhitespaceTokenizer.h"
+ #include "nsICookieService.h"
+ #include "nsIConsoleReportCollector.h"
+ #include "nsObjectLoadingContent.h"
++#include "nsStringStream.h"
+ 
+ // we want to explore making the document own the load group
+ // so we can associate the document URI with the load group.
+ // until this point, we have an evil hack:
+ #include "nsIHttpChannelInternal.h"
+ #include "nsPILoadGroupInternal.h"
+ 
+ // Local Includes
+@@ -610,18 +611,18 @@ SendPing(void* aClosure, nsIContent* aCo
+   nsCOMPtr<nsIUploadChannel2> uploadChan = do_QueryInterface(httpChan);
+   if (!uploadChan) {
+     return;
+   }
+ 
+   NS_NAMED_LITERAL_CSTRING(uploadData, "PING");
+ 
+   nsCOMPtr<nsIInputStream> uploadStream;
+-  NS_NewPostDataStream(getter_AddRefs(uploadStream), false, uploadData);
+-  if (!uploadStream) {
++  rv = NS_NewCStringInputStream(getter_AddRefs(uploadStream), uploadData);
++  if (NS_WARN_IF(NS_FAILED(rv))) {
+     return;
+   }
+ 
+   uploadChan->ExplicitSetUploadStream(uploadStream,
+                                       NS_LITERAL_CSTRING("text/ping"),
+                                       uploadData.Length(),
+                                       NS_LITERAL_CSTRING("POST"), false);
+ 
+diff --git a/netwerk/base/nsNetUtil.cpp b/netwerk/base/nsNetUtil.cpp
+--- a/netwerk/base/nsNetUtil.cpp
++++ b/netwerk/base/nsNetUtil.cpp
+@@ -1355,53 +1355,16 @@ NS_NewBufferedInputStream(nsIInputStream
+         rv = in->Init(inputStream, aBufferSize);
+         if (NS_SUCCEEDED(rv)) {
+             in.forget(aResult);
+         }
+     }
+     return rv;
+ }
+ 
+-nsresult
+-NS_NewPostDataStream(nsIInputStream  **result,
+-                     bool              isFile,
+-                     const nsACString &data)
+-{
+-    nsresult rv;
+-
+-    if (isFile) {
+-        nsCOMPtr<nsIFile> file;
+-        nsCOMPtr<nsIInputStream> fileStream;
+-
+-        rv = NS_NewNativeLocalFile(data, false, getter_AddRefs(file));
+-        if (NS_SUCCEEDED(rv)) {
+-            rv = NS_NewLocalFileInputStream(getter_AddRefs(fileStream), file);
+-            if (NS_SUCCEEDED(rv)) {
+-                // wrap the file stream with a buffered input stream
+-                rv = NS_NewBufferedInputStream(result, fileStream.forget(),
+-                                               8192);
+-            }
+-        }
+-        return rv;
+-    }
+-
+-    // otherwise, create a string stream for the data (copies)
+-    nsCOMPtr<nsIStringInputStream> stream
+-        (do_CreateInstance("@mozilla.org/io/string-input-stream;1", &rv));
+-    if (NS_FAILED(rv))
+-        return rv;
+-
+-    rv = stream->SetData(data.BeginReading(), data.Length());
+-    if (NS_FAILED(rv))
+-        return rv;
+-
+-    stream.forget(result);
+-    return NS_OK;
+-}
+-
+ namespace {
+ 
+ #define BUFFER_SIZE 4096
+ 
+ class BufferWriter final : public Runnable
+                          , public nsIInputStreamCallback
+ {
+ public:
+diff --git a/netwerk/base/nsNetUtil.h b/netwerk/base/nsNetUtil.h
+--- a/netwerk/base/nsNetUtil.h
++++ b/netwerk/base/nsNetUtil.h
+@@ -505,21 +505,16 @@ NS_NewBufferedInputStream(nsIInputStream
+                           uint32_t aBufferSize);
+ 
+ // note: the resulting stream can be QI'ed to nsISafeOutputStream iff the
+ // provided stream supports it.
+ nsresult NS_NewBufferedOutputStream(nsIOutputStream** aResult,
+                                     already_AddRefed<nsIOutputStream> aOutputStream,
+                                     uint32_t aBufferSize);
+ 
+-// returns an input stream compatible with nsIUploadChannel::SetUploadStream()
+-nsresult NS_NewPostDataStream(nsIInputStream  **result,
+-                              bool              isFile,
+-                              const nsACString &data);
+-
+ /**
+  * This function reads an inputStream and stores its content into a buffer. In
+  * general, you should avoid using this function because, it blocks the current
+  * thread until the operation is done.
+  * If the inputStream is async, the reading happens on an I/O thread.
+  *
+  * @param aInputStream the inputStream.
+  * @param aDest the destination buffer. if *aDest is null, it will be allocated
+diff --git a/security/manager/ssl/nsNSSCallbacks.cpp b/security/manager/ssl/nsNSSCallbacks.cpp
+--- a/security/manager/ssl/nsNSSCallbacks.cpp
++++ b/security/manager/ssl/nsNSSCallbacks.cpp
+@@ -25,16 +25,17 @@
+ #include "nsIUploadChannel.h"
+ #include "nsIWebProgressListener.h"
+ #include "nsNSSCertificate.h"
+ #include "nsNSSComponent.h"
+ #include "nsNSSIOLayer.h"
+ #include "nsNetUtil.h"
+ #include "nsProtectedAuthThread.h"
+ #include "nsProxyRelease.h"
++#include "nsStringStream.h"
+ #include "mozpkix/pkixtypes.h"
+ #include "ssl.h"
+ #include "sslproto.h"
+ 
+ #include "TrustOverrideUtils.h"
+ #include "TrustOverride-SymantecData.inc"
+ #include "TrustOverride-AppleGoogleDigiCertData.inc"
+ #include "TrustOverride-TestImminentDistrustData.inc"
+@@ -135,19 +136,18 @@ nsHTTPDownloadEvent::Run()
+   // Create a loadgroup for this new channel.  This way if the channel
+   // is redirected, we'll have a way to cancel the resulting channel.
+   nsCOMPtr<nsILoadGroup> lg = do_CreateInstance(NS_LOADGROUP_CONTRACTID);
+   chan->SetLoadGroup(lg);
+ 
+   if (mRequestSession->mHasPostData)
+   {
+     nsCOMPtr<nsIInputStream> uploadStream;
+-    rv = NS_NewPostDataStream(getter_AddRefs(uploadStream),
+-                              false,
+-                              mRequestSession->mPostData);
++    rv = NS_NewCStringInputStream(getter_AddRefs(uploadStream),
++                                  mRequestSession->mPostData);
+     NS_ENSURE_SUCCESS(rv, rv);
+ 
+     nsCOMPtr<nsIUploadChannel> uploadChannel(do_QueryInterface(chan));
+     NS_ENSURE_STATE(uploadChannel);
+ 
+     rv = uploadChannel->SetUploadStream(uploadStream,
+                                         mRequestSession->mPostContentType,
+                                         -1);

+ 19 - 19
mozilla-release/patches/1425975-07no08-59a1.patch

@@ -2,31 +2,31 @@
 # User Ben Kelly <ben@wanderview.com>
 # Date 1515172221 18000
 # Node ID 841e106b28101d1762d8c41740f433d19e7def92
-# Parent  679687cc3e08a1afd166dc8083f6d0e6c982a662
+# Parent  f398e4bb59ac916d7b7788b5598c03b3457e0161
 Bug 1425975 P7 Use the mControlledClients list to drive controller start and stop logic. r=asuth
 
 diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp
 --- a/docshell/base/nsDocShell.cpp
 +++ b/docshell/base/nsDocShell.cpp
-@@ -148,16 +148,17 @@
- #include "nsIStructuredCloneContainer.h"
- #include "nsISupportsPrimitives.h"
- #ifdef MOZ_PLACES
- #include "nsIFaviconService.h"
- #include "mozIPlacesPendingOperation.h"
- #include "mozIAsyncFavicons.h"
- #endif
- #include "nsINetworkPredictor.h"
+@@ -113,16 +113,17 @@
+ #include "nsIScriptObjectPrincipal.h"
+ #include "nsIScriptSecurityManager.h"
+ #include "nsIScrollableFrame.h"
+ #include "nsIScrollObserver.h"
+ #include "nsISecureBrowserUI.h"
+ #include "nsISecurityUITelemetry.h"
+ #include "nsISeekableStream.h"
+ #include "nsISelectionDisplay.h"
 +#include "nsIServiceWorkerManager.h"
- 
- // Editor-related
- #include "nsIEditingSession.h"
- 
- #include "nsPIDOMWindow.h"
- #include "nsGlobalWindow.h"
- #include "nsPIWindowRoot.h"
- #include "nsICachingChannel.h"
-@@ -3442,23 +3443,37 @@ nsDocShell::MaybeCreateInitialClientSour
+ #include "nsISHContainer.h"
+ #include "nsISHEntry.h"
+ #include "nsISHistory.h"
+ #include "nsISHistoryInternal.h"
+ #include "nsISiteSecurityService.h"
+ #include "nsISocketProvider.h"
+ #include "nsIStringBundle.h"
+ #include "nsIStructuredCloneContainer.h"
+@@ -2823,23 +2824,37 @@ nsDocShell::MaybeCreateInitialClientSour
      return;
    }
  

+ 12 - 12
mozilla-release/patches/1425975-16-59a1.patch

@@ -2,13 +2,13 @@
 # User Ben Kelly <ben@wanderview.com>
 # Date 1515172222 18000
 # Node ID 5b1109ca1c1f887a793748f1e115152a42122151
-# Parent  54b5f539a81dc4b0824b1b2ab4539fedf06766c3
+# Parent  dd20e44e6d198aa67cebdd773ece5614e001b978
 Bug 1425975 P16 Make nsDocShell check for session cookie lifetime policy before allowing service worker intercept. r=asuth
 
 diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp
 --- a/docshell/base/nsDocShell.cpp
 +++ b/docshell/base/nsDocShell.cpp
-@@ -3438,21 +3438,20 @@ nsDocShell::MaybeCreateInitialClientSour
+@@ -2819,21 +2819,20 @@ nsDocShell::MaybeCreateInitialClientSour
    nsCOMPtr<nsIDocShell> parent = GetParentDocshell();
    nsPIDOMWindowOuter* parentOuter = parent ? parent->GetWindow() : nullptr;
    nsPIDOMWindowInner* parentInner =
@@ -33,7 +33,7 @@ diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp
      return;
    }
  
-@@ -14888,16 +14887,64 @@ nsDocShell::CanSetOriginAttributes()
+@@ -13991,16 +13990,64 @@ nsDocShell::CanSetOriginAttributes()
          return false;
        }
      }
@@ -98,7 +98,7 @@ diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp
    }
  
    AssertOriginAttributesMatchPrivateBrowsing();
-@@ -15090,73 +15137,49 @@ nsDocShell::MaybeNotifyKeywordSearchLoad
+@@ -14193,73 +14240,49 @@ nsDocShell::MaybeNotifyKeywordSearchLoad
  #endif
  }
  
@@ -193,15 +193,15 @@ diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp
 diff --git a/docshell/base/nsDocShell.h b/docshell/base/nsDocShell.h
 --- a/docshell/base/nsDocShell.h
 +++ b/docshell/base/nsDocShell.h
-@@ -357,16 +357,27 @@ public:
+@@ -344,16 +344,27 @@ public:
+    *
+    * This method steals the data from the passed-in array.
+    */
    void SetAncestorOuterWindowIDs(nsTArray<uint64_t>&& aAncestorOuterWindowIDs)
    {
      mAncestorOuterWindowIDs = mozilla::Move(aAncestorOuterWindowIDs);
    }
  
- private:
-   bool CanSetOriginAttributes();
- 
 +  // Determine if a service worker is allowed to control a window in this
 +  // docshell with the given URL.  If there are any reasons it should not,
 +  // this will return false.  If true is returned then the window *may* be
@@ -213,14 +213,14 @@ diff --git a/docshell/base/nsDocShell.h b/docshell/base/nsDocShell.h
 +  // trigger 3rd party iframe checks.
 +  bool ServiceWorkerAllowedToControlWindow(nsIURI* aURI);
 +
- public:
-   const mozilla::OriginAttributes&
-   GetOriginAttributes()
+   const mozilla::OriginAttributes& GetOriginAttributes()
    {
      return mOriginAttributes;
    }
  
-   nsresult SetOriginAttributes(const mozilla::OriginAttributes& aAttrs);
+   // Determine whether this docshell corresponds to the given history entry,
+   // via having a pointer to it in mOSHE or mLSHE.
+   bool HasHistoryEntry(nsISHEntry* aEntry) const
 diff --git a/dom/base/nsContentUtils.h b/dom/base/nsContentUtils.h
 --- a/dom/base/nsContentUtils.h
 +++ b/dom/base/nsContentUtils.h

+ 12 - 12
mozilla-release/patches/1425975-19-59a1.patch

@@ -2,21 +2,21 @@
 # User Sebastian Hengst <archaeopteryx@coole-files.de>
 # Date 1515196306 -7200
 # Node ID 9099a6ed993f0113c47c0d9e800bf0ff6e1a1dc1
-# Parent  ac43086e18c70dfce9591a4f06ecfa00ae429e8e
+# Parent  7648ef62b73fe2cce04830d81bea072ae1587641
 Bug 1425975 - Follow-up: Move method to correct position. r=merge-fix a=merge-fix
 
 diff --git a/docshell/base/nsDocShell.h b/docshell/base/nsDocShell.h
 --- a/docshell/base/nsDocShell.h
 +++ b/docshell/base/nsDocShell.h
-@@ -357,27 +357,16 @@ public:
+@@ -344,27 +344,16 @@ public:
+    *
+    * This method steals the data from the passed-in array.
+    */
    void SetAncestorOuterWindowIDs(nsTArray<uint64_t>&& aAncestorOuterWindowIDs)
    {
      mAncestorOuterWindowIDs = mozilla::Move(aAncestorOuterWindowIDs);
    }
  
- private:
-   bool CanSetOriginAttributes();
- 
 -  // Determine if a service worker is allowed to control a window in this
 -  // docshell with the given URL.  If there are any reasons it should not,
 -  // this will return false.  If true is returned then the window *may* be
@@ -28,15 +28,15 @@ diff --git a/docshell/base/nsDocShell.h b/docshell/base/nsDocShell.h
 -  // trigger 3rd party iframe checks.
 -  bool ServiceWorkerAllowedToControlWindow(nsIURI* aURI);
 -
- public:
-   const mozilla::OriginAttributes&
-   GetOriginAttributes()
+   const mozilla::OriginAttributes& GetOriginAttributes()
    {
      return mOriginAttributes;
    }
  
-   nsresult SetOriginAttributes(const mozilla::OriginAttributes& aAttrs);
-@@ -845,16 +834,27 @@ protected:
+   // Determine whether this docshell corresponds to the given history entry,
+   // via having a pointer to it in mOSHE or mLSHE.
+   bool HasHistoryEntry(nsISHEntry* aEntry) const
+@@ -790,16 +779,27 @@ private: // member functions
    // the principal is not provided we will attempt to inherit it when we
    // are sure it will match what the real about:blank window principal
    // would have been.  There are some corner cases where we cannot easily
@@ -62,5 +62,5 @@ diff --git a/docshell/base/nsDocShell.h b/docshell/base/nsDocShell.h
    // even if GetExtantDoc() returns nullptr.
    mozilla::Maybe<mozilla::dom::ClientInfo> GetInitialClientInfo() const;
  
- protected:
-   nsresult GetCurScrollPos(int32_t aScrollOrientation, int32_t* aCurPos);
+   /**
+    * Initializes mTiming if it isn't yet.

+ 15 - 15
mozilla-release/patches/1426501-4-59a1.patch

@@ -2,7 +2,7 @@
 # User Valentin Gosu <valentin.gosu@gmail.com>
 # Date 1515421235 -3600
 # Node ID 0ca777d3a396f1130efe477fa376407fe7836228
-# Parent  1586183375bb345888bce40dc73bd45b69ed3f8f
+# Parent  3b7a116b8ba327d67e703a0814b3dc8d579722de
 Bug 1426501 - Change C++ code to use NS_MutateURI when changing URI r=mayhemer
 
 MozReview-Commit-ID: 4VzZlhWrtSJ
@@ -10,25 +10,25 @@ MozReview-Commit-ID: 4VzZlhWrtSJ
 diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp
 --- a/docshell/base/nsDocShell.cpp
 +++ b/docshell/base/nsDocShell.cpp
-@@ -209,16 +209,17 @@
- #include "nsIOService.h"
- #include "nsISHContainer.h"
- #include "nsISHistory.h"
- #include "nsISecureBrowserUI.h"
- #include "nsISocketProvider.h"
- #include "nsIStringBundle.h"
+@@ -131,16 +131,17 @@
+ #include "nsITabChild.h"
+ #include "nsITextToSubURI.h"
+ #include "nsITimedChannel.h"
+ #include "nsITimer.h"
+ #include "nsITransportSecurityInfo.h"
+ #include "nsIUploadChannel.h"
  #include "nsIURIFixup.h"
  #include "nsIURILoader.h"
 +#include "nsIURIMutator.h"
  #include "nsIURL.h"
+ #include "nsIViewSourceChannel.h"
+ #include "nsIWebBrowserChrome.h"
+ #include "nsIWebBrowserChrome3.h"
+ #include "nsIWebBrowserChromeFocus.h"
  #include "nsIWebBrowserFind.h"
+ #include "nsIWebProgress.h"
  #include "nsIWidget.h"
- #include "mozilla/dom/PerformanceNavigation.h"
- #include "mozilla/dom/ScriptSettings.h"
- #include "mozilla/Encoding.h"
- #include "nsJSEnvironment.h"
- 
-@@ -1647,23 +1648,21 @@ nsDocShell::LoadStream(nsIInputStream* a
+@@ -1042,23 +1043,21 @@ nsDocShell::LoadStream(nsIInputStream* a
  
    // if the caller doesn't pass in a URI we need to create a dummy URI. necko
    // currently requires a URI in various places during the load. Some consumers
@@ -76,7 +76,7 @@ diff --git a/layout/generic/nsImageFrame.cpp b/layout/generic/nsImageFrame.cpp
  #include "nsCSSFrameConstructor.h"
  #include "nsIDOMRange.h"
  
-@@ -2125,17 +2126,19 @@ nsImageFrame::HandleEvent(nsPresContext*
+@@ -2127,17 +2128,19 @@ nsImageFrame::HandleEvent(nsPresContext*
            if (p.x < 0) p.x = 0;
            if (p.y < 0) p.y = 0;
  

+ 11 - 11
mozilla-release/patches/1435939-1-60a1.patch

@@ -2,7 +2,7 @@
 # User Emilio Cobos Alvarez <emilio@crisal.io>
 # Date 1517917892 -3600
 # Node ID 12ca97022384d5461f597088f6941c85c213197d
-# Parent  ea678fa933a3f58d03b60a162ec15ef6723913fd
+# Parent  1e8494a7ccbdb7102e1a35f70872a0211c08de85
 Bug 1435939: Make media feature changes always async. r=bz
 
 Much in the spirit of bug 1434474.
@@ -22,14 +22,14 @@ diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp
 --- a/docshell/base/nsDocShell.cpp
 +++ b/docshell/base/nsDocShell.cpp
 @@ -20,16 +20,17 @@
- #include "mozilla/dom/ProfileTimelineMarkerBinding.h"
- #include "mozilla/dom/ScreenOrientation.h"
- #include "mozilla/dom/ToJSValue.h"
- #include "mozilla/dom/PermissionMessageUtils.h"
- #include "mozilla/dom/workers/ServiceWorkerManager.h"
+ #include "mozilla/AutoRestore.h"
+ #include "mozilla/BasePrincipal.h"
+ #include "mozilla/Casting.h"
+ #include "mozilla/Encoding.h"
  #include "mozilla/EventStateManager.h"
- #include "mozilla/LoadInfo.h"
  #include "mozilla/HTMLEditor.h"
+ #include "mozilla/LoadInfo.h"
+ #include "mozilla/Logging.h"
 +#include "mozilla/MediaFeatureChange.h"
  #include "mozilla/Preferences.h"
  #include "mozilla/ResultExtensions.h"
@@ -37,9 +37,9 @@ diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp
  #include "mozilla/StartupTimeline.h"
  #include "mozilla/Telemetry.h"
  #include "mozilla/Unused.h"
- #include "Navigator.h"
- #include "URIUtils.h"
-@@ -4640,17 +4641,18 @@ nsDocShell::GetWindow()
+ 
+ #include "mozilla/dom/ClientChannelHelper.h"
+@@ -4149,17 +4150,18 @@ nsDocShell::GetWindow()
  NS_IMETHODIMP
  nsDocShell::SetDeviceSizeIsPageSize(bool aValue)
  {
@@ -59,7 +59,7 @@ diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp
  NS_IMETHODIMP
  nsDocShell::GetDeviceSizeIsPageSize(bool* aValue)
  {
-@@ -15193,14 +15195,15 @@ nsDocShell::SetDisplayMode(uint32_t aDis
+@@ -14461,14 +14463,15 @@ nsDocShell::SetDisplayMode(uint32_t aDis
      return NS_ERROR_INVALID_ARG;
    }
  

+ 15 - 15
mozilla-release/patches/1465585-3-std-62a1.patch

@@ -2,7 +2,7 @@
 # User Emilio Cobos Alvarez <emilio@crisal.io>
 # Date 1527707735 -7200
 # Node ID b54db66223586b4e04f5cb926fccdacf8a176b91
-# Parent  c0895216247f5217d44b45693e8b62513c01a96f
+# Parent  bc7de37a6e158757e4bd70536974f7e46e2fe455
 Bug 1465585: Switch from mozilla::Move to std::move. r=froydnj
 
 This was done automatically replacing:
@@ -1280,7 +1280,7 @@ diff --git a/devtools/shared/heapsnapshot/tests/gtest/DevTools.h b/devtools/shar
 diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp
 --- a/docshell/base/nsDocShell.cpp
 +++ b/docshell/base/nsDocShell.cpp
-@@ -3479,17 +3479,17 @@ nsDocShell::MaybeCreateInitialClientSour
+@@ -2860,17 +2860,17 @@ nsDocShell::MaybeCreateInitialClientSour
  }
  
  Maybe<ClientInfo>
@@ -1299,7 +1299,7 @@ diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp
  
    if (!doc || !doc->IsInitialDocument()) {
      return Maybe<ClientInfo>();
-@@ -5677,17 +5677,17 @@ nsDocShell::Reload(uint32_t aReloadFlags
+@@ -5058,17 +5058,17 @@ nsDocShell::Reload(uint32_t aReloadFlags
      // Stack variables to ensure changes to the member variables don't affect to
      // the call.
      nsCOMPtr<nsIURI> currentURI = mCurrentURI;
@@ -1318,7 +1318,7 @@ diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp
                        referrerURI,
                        referrerPolicy,
                        triggeringPrincipal,
-@@ -11786,17 +11786,17 @@ nsDocShell::DoChannelLoad(nsIChannel* aC
+@@ -11167,17 +11167,17 @@ nsDocShell::DoChannelLoad(nsIChannel* aC
  
    // Since we are loading a document we need to make sure the proper reserved
    // and initial client data is stored on the nsILoadInfo.  The
@@ -1337,8 +1337,8 @@ diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp
    NS_ENSURE_SUCCESS(rv, rv);
  
    // We're about to load a new page and it may take time before necko
-@@ -12970,17 +12970,17 @@ nsDocShell::LoadHistoryEntry(nsISHEntry*
-     triggeringPrincipal = nsContentUtils::GetSystemPrincipal();
+@@ -12353,17 +12353,17 @@ nsDocShell::LoadHistoryEntry(nsISHEntry*
+     return NS_ERROR_FAILURE;
    }
  
    // Passing nullptr as aSourceDocShell gives the same behaviour as before
@@ -1356,7 +1356,7 @@ diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp
                      referrerURI,
                      referrerPolicy,
                      triggeringPrincipal,
-@@ -15073,17 +15073,17 @@ nsDocShell::NotifyJSRunToCompletionStart
+@@ -14176,17 +14176,17 @@ nsDocShell::NotifyJSRunToCompletionStart
                                           const uint32_t aLineNumber,
                                           JS::Handle<JS::Value> aAsyncStack,
                                           const char* aAsyncCause)
@@ -1375,7 +1375,7 @@ diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp
  
    mJSRunToCompletionDepth++;
  }
-@@ -15226,17 +15226,17 @@ nsDocShell::InFrameSwap()
+@@ -14329,17 +14329,17 @@ nsDocShell::InFrameSwap()
      shell = shell->GetParentDocshell();
    } while (shell);
    return false;
@@ -1397,7 +1397,7 @@ diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp
 diff --git a/docshell/base/nsDocShell.h b/docshell/base/nsDocShell.h
 --- a/docshell/base/nsDocShell.h
 +++ b/docshell/base/nsDocShell.h
-@@ -329,17 +329,17 @@ public:
+@@ -319,17 +319,17 @@ public:
     * docshell is added to the docshell tree, which can affect what the ancestor
     * principals should look like.
     *
@@ -1416,7 +1416,7 @@ diff --git a/docshell/base/nsDocShell.h b/docshell/base/nsDocShell.h
     * above.   For each ancestor principal, we store the parent window ID.
     */
    const nsTArray<uint64_t>& AncestorOuterWindowIDs() const
-@@ -351,17 +351,17 @@ public:
+@@ -341,17 +341,17 @@ public:
     * Set the list of ancestor outer window IDs for this docshell.  We call this
     * from frameloader as well in order to keep the array matched with the
     * ancestor principals.
@@ -1429,12 +1429,12 @@ diff --git a/docshell/base/nsDocShell.h b/docshell/base/nsDocShell.h
 +    mAncestorOuterWindowIDs = std::move(aAncestorOuterWindowIDs);
    }
  
- private:
-   bool CanSetOriginAttributes();
+   const mozilla::OriginAttributes& GetOriginAttributes()
+   {
+     return mOriginAttributes;
+   }
  
- public:
-   const mozilla::OriginAttributes&
-   GetOriginAttributes()
+   // Determine whether this docshell corresponds to the given history entry,
 diff --git a/docshell/base/nsDocShellLoadInfo.cpp b/docshell/base/nsDocShellLoadInfo.cpp
 --- a/docshell/base/nsDocShellLoadInfo.cpp
 +++ b/docshell/base/nsDocShellLoadInfo.cpp

+ 30 - 30
mozilla-release/patches/NOBUG-killtelemetry-docshell-25317.patch

@@ -1,16 +1,16 @@
 # HG changeset patch
 # User Frank-Rainer Grahl <frgrahl@gmx.net>
 # Date 1684967687 -7200
-# Parent  3c29745cbd51079e3dfab2860bf310f1736e4ff6
+# Parent  362aa4fb5e1f3640e5a5cba91af07ab36b636b3c
 No Bug - Kill telemetry code in docshell. r=me a=me
 
 diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp
 --- a/docshell/base/nsDocShell.cpp
 +++ b/docshell/base/nsDocShell.cpp
 @@ -25,17 +25,16 @@
- #include "mozilla/EventStateManager.h"
- #include "mozilla/LoadInfo.h"
  #include "mozilla/HTMLEditor.h"
+ #include "mozilla/LoadInfo.h"
+ #include "mozilla/Logging.h"
  #include "mozilla/MediaFeatureChange.h"
  #include "mozilla/Preferences.h"
  #include "mozilla/ResultExtensions.h"
@@ -18,32 +18,32 @@ diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp
  #include "mozilla/StartupTimeline.h"
 -#include "mozilla/Telemetry.h"
  #include "mozilla/Unused.h"
- #include "Navigator.h"
- #include "URIUtils.h"
- #include "mozilla/dom/DocGroup.h"
- #include "mozilla/dom/TabGroup.h"
- 
- #include "nsIContent.h"
- #include "nsIContentInlines.h"
-@@ -191,17 +190,16 @@
- #endif
  
- #include "nsContentUtils.h"
- #include "nsIContentSecurityPolicy.h"
- #include "nsILoadInfo.h"
- #include "nsSandboxFlags.h"
- #include "nsXULAppAPI.h"
- #include "nsDOMNavigationTiming.h"
+ #include "mozilla/dom/ClientChannelHelper.h"
+ #include "mozilla/dom/ClientHandle.h"
+ #include "mozilla/dom/ClientInfo.h"
+ #include "mozilla/dom/ClientManager.h"
+ #include "mozilla/dom/ClientSource.h"
+ #include "mozilla/dom/ContentChild.h"
+@@ -111,17 +110,16 @@
+ #include "nsIReflowObserver.h"
+ #include "nsIScriptChannel.h"
+ #include "nsIScriptError.h"
+ #include "nsIScriptObjectPrincipal.h"
+ #include "nsIScriptSecurityManager.h"
+ #include "nsIScrollableFrame.h"
+ #include "nsIScrollObserver.h"
+ #include "nsISecureBrowserUI.h"
 -#include "nsISecurityUITelemetry.h"
- #include "nsDSURIContentListener.h"
- #include "nsDocShellLoadTypes.h"
- #include "nsDocShellTransferableHooks.h"
- #include "nsICommandManager.h"
- #include "nsIDOMNode.h"
- #include "nsIClassOfService.h"
- #include "nsIDocShellTreeOwner.h"
- #include "nsIHttpChannel.h"
-@@ -2079,87 +2077,16 @@ nsDocShell::GetCharset(nsACString& aChar
+ #include "nsISeekableStream.h"
+ #include "nsISelectionDisplay.h"
+ #include "nsIServiceWorkerManager.h"
+ #include "nsISHContainer.h"
+ #include "nsISHEntry.h"
+ #include "nsISHistory.h"
+ #include "nsISHistoryInternal.h"
+ #include "nsISiteSecurityService.h"
+@@ -1470,87 +1468,16 @@ nsDocShell::GetCharset(nsACString& aChar
    NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE);
    nsIDocument* doc = presShell->GetDocument();
    NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE);
@@ -131,7 +131,7 @@ diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp
  
  NS_IMETHODIMP
  nsDocShell::SetForcedCharset(const nsACString& aCharset)
-@@ -5114,38 +5041,25 @@ nsDocShell::DisplayLoadError(nsresult aE
+@@ -4627,38 +4554,25 @@ nsDocShell::DisplayLoadError(nsresult aE
          // HSTS/pinning takes precedence over the expert bad cert pref. We
          // never want to show the "Add Exception" button for these sites.
          // In the future we should differentiate between an HSTS host and a
@@ -170,7 +170,7 @@ diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp
               NS_ERROR_MALWARE_URI == aError ||
               NS_ERROR_UNWANTED_URI == aError ||
               NS_ERROR_HARMFUL_URI == aError) {
-@@ -7669,18 +7583,16 @@ nsDocShell::EndPageLoad(nsIWebProgress* 
+@@ -7195,18 +7109,16 @@ nsDocShell::EndPageLoad(nsIWebProgress* 
      return rv;
    }
  
@@ -192,7 +192,7 @@ diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp
 diff --git a/docshell/base/nsIDocShell.idl b/docshell/base/nsIDocShell.idl
 --- a/docshell/base/nsIDocShell.idl
 +++ b/docshell/base/nsIDocShell.idl
-@@ -701,23 +701,16 @@ interface nsIDocShell : nsIDocShellTreeI
+@@ -709,23 +709,16 @@ interface nsIDocShell : nsIDocShellTreeI
     * Upon getting, returns the canonical encoding label of the document
     * currently loaded into this docshell.
     *

+ 9 - 0
mozilla-release/patches/series

@@ -544,6 +544,8 @@ NOBUG-20170803-promisehelper-57a1.patch
 1408939-59a1.patch
 1408934-59a1.patch
 1419301-59a1.patch
+1345433-1-59a1.patch
+1345433-2-59a1.patch
 1422314-59a1.patch
 1420594-1-59a1.patch
 1420594-2-59a1.patch
@@ -605,6 +607,7 @@ NOBUG-20170803-promisehelper-57a1.patch
 1424338-7-59a1.patch
 1419401-59a1.patch
 1424658-59a1.patch
+1424809-59a1.patch
 1411622-59a1.patch
 1293277-1-59a1.patch
 1293277-2-59a1.patch
@@ -706,6 +709,12 @@ NOBUG-20170803-promisehelper-57a1.patch
 1426920-59a1.patch
 1428231-59a1.patch
 1428043-59a1.patch
+1406161-1-59a1.patch
+1406161-2-59a1.patch
+1406161-3-59a1.patch
+1406161-4-59a1.patch
+1406161-5-59a1.patch
+1406161-6-59a1.patch
 1427392-59a1.patch
 1427187-59a1.patch
 1398981-59a1.patch