Backed out 2 changesets (bug 1510569) for crashtests/1419902.html crashes CLOSED TREE
authorBogdan Tara <btara@mozilla.com>
Fri, 03 May 2019 03:48:15 +0300
changeset 531217 9186bf351f2c474ddd10bcac736a3cf4fd460f21
parent 531216 c2f648fbcbf18415b631252995edf38301c3063e
child 531218 de9073c57d209c9b4ea110194ae31503f5cf4363
push id11265
push userffxbld-merge
push dateMon, 13 May 2019 10:53:39 +0000
treeherdermozilla-beta@77e0fe8dbdd3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1510569, 1419902
milestone68.0a1
backs outfc0ae629221af74287f6df6f2ffb8bcc0b52c123
97f6ac273b5dcc04a553e4dec24362da2dbc5809
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Backed out 2 changesets (bug 1510569) for crashtests/1419902.html crashes CLOSED TREE Backed out changeset fc0ae629221a (bug 1510569) Backed out changeset 97f6ac273b5d (bug 1510569)
browser/base/content/browser.js
browser/base/content/tabbrowser.js
devtools/client/responsive.html/browser/tunnel.js
docshell/base/nsDocShell.cpp
docshell/base/nsDocShell.h
docshell/base/nsIDocShell.idl
dom/interfaces/base/nsIBrowser.idl
dom/ipc/BrowserChild.cpp
dom/ipc/BrowserParent.cpp
dom/ipc/BrowserParent.h
dom/ipc/PBrowser.ipdl
toolkit/actors/WebNavigationChild.jsm
toolkit/content/widgets/browser-custom-element.js
toolkit/modules/RemoteWebProgress.jsm
toolkit/modules/WebProgressChild.jsm
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -1203,17 +1203,17 @@ function _loadURI(browser, uri, params =
   if (newFrameloader) {
     // If a new frameloader is needed for process reselection because this used
     // to be a preloaded browser, clear the preloaded state now.
     browser.removeAttribute("preloadedState");
   }
 
   // !requiredRemoteType means we're loading in the parent/this process.
   if (!requiredRemoteType) {
-    browser.isNavigating = true;
+    browser.inLoadURI = true;
   }
   let loadURIOptions = {
     triggeringPrincipal,
     csp,
     loadFlags: flags,
     referrerInfo,
     postData,
   };
@@ -1273,17 +1273,17 @@ function _loadURI(browser, uri, params =
         });
       }
       browser.webNavigation.loadURI(uri, loadURIOptions);
     } else {
       throw e;
     }
   } finally {
     if (!requiredRemoteType) {
-      browser.isNavigating = false;
+      browser.inLoadURI = false;
     }
   }
 }
 
 // Starts a new load in the browser first switching the browser to the correct
 // process
 function LoadInOtherProcess(browser, loadOptions, historyIndex = -1) {
   let tab = gBrowser.getTabForBrowser(browser);
--- a/browser/base/content/tabbrowser.js
+++ b/browser/base/content/tabbrowser.js
@@ -5022,18 +5022,18 @@ class TabProgressListener {
         let isSuccessful = Components.isSuccessCode(aStatus);
         if (!isSuccessful && !this.mTab.isEmpty) {
           // Restore the current document's location in case the
           // request was stopped (possibly from a content script)
           // before the location changed.
 
           this.mBrowser.userTypedValue = null;
 
-          let isNavigating = this.mBrowser.isNavigating;
-          if (this.mTab.selected && gURLBar && !isNavigating) {
+          let inLoadURI = this.mBrowser.inLoadURI;
+          if (this.mTab.selected && gURLBar && !inLoadURI) {
             URLBarSetURI();
           }
         } else if (isSuccessful) {
           this.mBrowser.urlbarChangeTracker.finishedLoad();
         }
       }
 
       // If we don't already have an icon for this tab then clear the tab's
@@ -5096,17 +5096,17 @@ class TabProgressListener {
       // if the error page's URI is about:blank, because that causes complete
       // loss of urlbar contents for invalid URI errors (see bug 867957).
       // Another reason to clear the userTypedValue is if this was an anchor
       // navigation initiated by the user.
       // Finally, we do insert the URL if this is a same-document navigation
       // and the user cleared the URL manually.
       if (this.mBrowser.didStartLoadSinceLastUserTyping() ||
           (isErrorPage && aLocation.spec != "about:blank") ||
-          (isSameDocument && this.mBrowser.isNavigating) ||
+          (isSameDocument && this.mBrowser.inLoadURI) ||
           (isSameDocument && !this.mBrowser.userTypedValue)) {
         this.mBrowser.userTypedValue = null;
       }
 
       // If the tab has been set to "busy" outside the stateChange
       // handler below (e.g. by sessionStore.navigateAndRestore), and
       // the load results in an error page, it's possible that there
       // isn't any (STATE_IS_NETWORK & STATE_STOP) state to cause busy
--- a/devtools/client/responsive.html/browser/tunnel.js
+++ b/devtools/client/responsive.html/browser/tunnel.js
@@ -431,16 +431,17 @@ MessageManagerTunnel.prototype = {
     "Link:SetFailedIcon",
     "Link:AddFeed",
     "Link:AddSearch",
     "PageStyle:StyleSheets",
     // Messages sent to RemoteWebProgress.jsm
     "Content:LoadURIResult",
     "Content:LocationChange",
     "Content:SecurityChange",
+    "Content:StateChange",
     // Messages sent to browser.js
     "DOMTitleChanged",
     "ImageDocumentLoaded",
     "Forms:ShowDropDown",
     "Forms:HideDropDown",
     "InPermitUnload",
     "PermitUnload",
     // Messages sent to tabbrowser.xml
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -380,18 +380,17 @@ nsDocShell::nsDocShell(BrowsingContext* 
       mIsPrintingOrPP(false),
       mSavingOldViewer(false),
       mDynamicallyCreated(false),
       mAffectPrivateSessionLifetime(true),
       mInvisible(false),
       mHasLoadedNonBlankURI(false),
       mBlankTiming(false),
       mTitleValidForCurrentURI(false),
-      mIsFrame(false),
-      mIsNavigating(false) {
+      mIsFrame(false) {
   mHistoryID.m0 = 0;
   mHistoryID.m1 = 0;
   mHistoryID.m2 = 0;
   AssertOriginAttributesMatchPrivateBrowsing();
 
   nsContentUtils::GenerateUUIDInPlace(mHistoryID);
 
   if (gDocShellCount++ == 0) {
@@ -3722,22 +3721,16 @@ nsDocShell::GetContentBlockingLog(Promis
   }
   promise->MaybeResolve(
       NS_ConvertUTF8toUTF16(doc->GetContentBlockingLog()->Stringify()));
   promise.forget(aPromise);
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsDocShell::GetIsNavigating(bool* aOut) {
-  *aOut = mIsNavigating;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
 nsDocShell::SetDeviceSizeIsPageSize(bool aValue) {
   if (mDeviceSizeIsPageSize != aValue) {
     mDeviceSizeIsPageSize = aValue;
     RefPtr<nsPresContext> presContext = GetPresContext();
     if (presContext) {
       presContext->MediaFeatureValuesChanged(
           {MediaFeatureChangeReason::DeviceSizeIsPageSizeChange});
     }
@@ -3828,73 +3821,57 @@ nsDocShell::GetCanGoForward(bool* aCanGo
   return NS_ERROR_FAILURE;
 }
 
 NS_IMETHODIMP
 nsDocShell::GoBack() {
   if (!IsNavigationAllowed()) {
     return NS_OK;  // JS may not handle returning of an error code
   }
-
-  auto cleanupIsNavigating = MakeScopeExit([&]() { mIsNavigating = false; });
-  mIsNavigating = true;
-
   RefPtr<ChildSHistory> rootSH = GetRootSessionHistory();
   NS_ENSURE_TRUE(rootSH, NS_ERROR_FAILURE);
   ErrorResult rv;
   rootSH->Go(-1, rv);
   return rv.StealNSResult();
 }
 
 NS_IMETHODIMP
 nsDocShell::GoForward() {
   if (!IsNavigationAllowed()) {
     return NS_OK;  // JS may not handle returning of an error code
   }
-
-  auto cleanupIsNavigating = MakeScopeExit([&]() { mIsNavigating = false; });
-  mIsNavigating = true;
-
   RefPtr<ChildSHistory> rootSH = GetRootSessionHistory();
   NS_ENSURE_TRUE(rootSH, NS_ERROR_FAILURE);
   ErrorResult rv;
   rootSH->Go(1, rv);
   return rv.StealNSResult();
 }
 
 // XXX(nika): We may want to stop exposing this API in the child process? Going
 // to a specific index from multiple different processes could definitely race.
 NS_IMETHODIMP
 nsDocShell::GotoIndex(int32_t aIndex) {
   if (!IsNavigationAllowed()) {
     return NS_OK;  // JS may not handle returning of an error code
   }
-
-  auto cleanupIsNavigating = MakeScopeExit([&]() { mIsNavigating = false; });
-  mIsNavigating = true;
-
   RefPtr<ChildSHistory> rootSH = GetRootSessionHistory();
   NS_ENSURE_TRUE(rootSH, NS_ERROR_FAILURE);
   return rootSH->LegacySHistory()->GotoIndex(aIndex);
 }
 
 nsresult nsDocShell::LoadURI(const nsAString& aURI,
                              const LoadURIOptions& aLoadURIOptions) {
   uint32_t loadFlags = aLoadURIOptions.mLoadFlags;
 
   NS_ASSERTION((loadFlags & INTERNAL_LOAD_FLAGS_LOADURI_SETUP_FLAGS) == 0,
                "Unexpected flags");
 
   if (!IsNavigationAllowed()) {
     return NS_OK;  // JS may not handle returning of an error code
   }
-
-  auto cleanupIsNavigating = MakeScopeExit([&]() { mIsNavigating = false; });
-  mIsNavigating = true;
-
   nsCOMPtr<nsIURI> uri;
   nsCOMPtr<nsIInputStream> postData(aLoadURIOptions.mPostData);
   nsresult rv = NS_OK;
 
   // Create a URI from our string; if that succeeds, we want to
   // change loadFlags to not include the ALLOW_THIRD_PARTY_FIXUP
   // flag.
 
--- a/docshell/base/nsDocShell.h
+++ b/docshell/base/nsDocShell.h
@@ -1200,15 +1200,11 @@ class nsDocShell final : public nsDocLoa
   // We will check the innerWin's timing before creating a new one
   // in MaybeInitTiming()
   bool mBlankTiming : 1;
 
   // This flag indicates when the title is valid for the current URI.
   bool mTitleValidForCurrentURI : 1;
 
   bool mIsFrame : 1;
-
-  // This flag indicates whether or not the DocShell is currently executing an
-  // nsIWebNavigation navigation method.
-  bool mIsNavigating : 1;
 };
 
 #endif /* nsDocShell_h__ */
--- a/docshell/base/nsIDocShell.idl
+++ b/docshell/base/nsIDocShell.idl
@@ -1162,22 +1162,9 @@ interface nsIDocShell : nsIDocShellTreeI
    */
   Promise getContentBlockingLog();
 
   /**
    * Return whether this docshell is "attempting to navigate" in the
    * sense that's relevant to document.open.
    */
   [notxpcom, nostdcall] readonly attribute boolean isAttemptingToNavigate;
-
-  /**
-   * Whether or not this docshell is executing a nsIWebNavigation navigation
-   * method.
-   *
-   * This will be true when the following methods are executing:
-   *   nsIWebNavigation.binaryLoadURI
-   *   nsIWebNavigation.goBack
-   *   nsIWebNavigation.goForward
-   *   nsIWebNavigation.gotoIndex
-   *   nsIWebNavigation.loadURI
-   */
-  [infallible] readonly attribute boolean isNavigating;
 };
--- a/dom/interfaces/base/nsIBrowser.idl
+++ b/dom/interfaces/base/nsIBrowser.idl
@@ -1,16 +1,15 @@
 /* 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 "nsISupports.idl"
 
 interface nsIContentSecurityPolicy;
 interface nsIPrincipal;
-interface nsIURI;
 interface nsIWebProgress;
 
 webidl FrameLoader;
 
 [scriptable, uuid(14e5a0cb-e223-4202-95e8-fe53275193ea)]
 interface nsIBrowser : nsISupports
 {
   /**
@@ -82,31 +81,9 @@ interface nsIBrowser : nsISupports
   void enableDisableCommandsRemoteOnly(in AString action,
                                        in unsigned long enabledLength,
                                        [array, size_is(enabledLength)] in string enabledCommands,
                                        in unsigned long disabledLength,
                                        [array, size_is(disabledLength)] in string disabledCommands);
 
   readonly attribute nsIPrincipal contentPrincipal;
   readonly attribute nsIContentSecurityPolicy csp;
-
-  /**
-   * Whether or not the browser is in the process of an nsIWebNavigation
-   * navigation method.
-   */
-  attribute boolean isNavigating;
-
-  /**
-   * Whether or not the character encoding menu may be enabled.
-   */
-  attribute boolean mayEnableCharacterEncodingMenu;
-
-  /**
-   * Called by Gecko to update the browser when its state changes.
-   *
-   * @param aCharset the new character set of the document
-   * @param aDocumentURI the URI of the current document
-   * @param aContentType the content type of the document
-   */
-  void updateForStateChange(in AString aCharset,
-                            in nsIURI aDocumentURI,
-                            in AString aContentType);
 };
--- a/dom/ipc/BrowserChild.cpp
+++ b/dom/ipc/BrowserChild.cpp
@@ -126,17 +126,16 @@
 #include "mozilla/dom/DocGroup.h"
 #include "nsString.h"
 #include "nsISupportsPrimitives.h"
 #include "mozilla/Telemetry.h"
 #include "nsDocShellLoadState.h"
 #include "nsWebBrowser.h"
 #include "mozilla/dom/WindowGlobalChild.h"
 #include "MMPrinter.h"
-#include "mozilla/ResultExtensions.h"
 
 #ifdef XP_WIN
 #  include "mozilla/plugins/PluginWidgetChild.h"
 #endif
 
 #ifdef NS_PRINTING
 #  include "nsIPrintSession.h"
 #  include "nsIPrintSettings.h"
@@ -539,19 +538,18 @@ nsresult BrowserChild::Init(mozIDOMWindo
   // IPC uses a WebBrowser object for which DNS prefetching is turned off
   // by default. But here we really want it, so enable it explicitly
   mWebBrowser->SetAllowDNSPrefetch(true);
 
   nsCOMPtr<nsIDocShell> docShell = do_GetInterface(WebNavigation());
   MOZ_ASSERT(docShell);
 
   const uint32_t notifyMask =
-      nsIWebProgress::NOTIFY_STATE_ALL | nsIWebProgress::NOTIFY_PROGRESS |
-      nsIWebProgress::NOTIFY_STATUS | nsIWebProgress::NOTIFY_REFRESH |
-      nsIWebProgress::NOTIFY_CONTENT_BLOCKING;
+      nsIWebProgress::NOTIFY_PROGRESS | nsIWebProgress::NOTIFY_STATUS |
+      nsIWebProgress::NOTIFY_REFRESH | nsIWebProgress::NOTIFY_CONTENT_BLOCKING;
 
   mStatusFilter = new nsBrowserStatusFilter();
 
   RefPtr<nsIEventTarget> eventTarget =
       TabGroup()->EventTargetFor(TaskCategory::Network);
 
   mStatusFilter->SetTarget(eventTarget);
   nsresult rv = mStatusFilter->AddProgressListener(this, notifyMask);
@@ -3433,62 +3431,17 @@ nsresult BrowserChild::SetHasSiblings(bo
   mHasSiblings = aHasSiblings;
   return NS_OK;
 }
 
 NS_IMETHODIMP BrowserChild::OnStateChange(nsIWebProgress* aWebProgress,
                                           nsIRequest* aRequest,
                                           uint32_t aStateFlags,
                                           nsresult aStatus) {
-  if (!IPCOpen()) {
-    return NS_OK;
-  }
-
-  nsCOMPtr<nsIDocShell> docShell = do_GetInterface(WebNavigation());
-  if (!docShell) {
-    return NS_OK;
-  }
-
-  RefPtr<Document> document;
-  if (nsCOMPtr<nsPIDOMWindowOuter> outerWindow = do_GetInterface(docShell)) {
-    document = outerWindow->GetExtantDoc();
-  } else {
-    return NS_OK;
-  }
-
-  Maybe<WebProgressData> webProgressData;
-  Maybe<WebProgressStateChangeData> stateChangeData;
-  RequestData requestData;
-
-  MOZ_TRY(PrepareProgressListenerData(aWebProgress, aRequest, webProgressData,
-                                      requestData));
-
-  if (webProgressData->isTopLevel()) {
-    stateChangeData.emplace();
-
-    stateChangeData->isNavigating() = docShell->GetIsNavigating();
-    stateChangeData->mayEnableCharacterEncodingMenu() =
-        docShell->GetMayEnableCharacterEncodingMenu();
-
-    if (aStateFlags & nsIWebProgressListener::STATE_STOP) {
-      MOZ_ASSERT(document);
-
-      document->GetContentType(stateChangeData->contentType());
-      document->GetCharacterSet(stateChangeData->charset());
-      stateChangeData->documentURI() = document->GetDocumentURIObject();
-    } else {
-      stateChangeData->contentType().SetIsVoid(true);
-      stateChangeData->charset().SetIsVoid(true);
-    }
-  }
-
-  Unused << SendOnStateChange(webProgressData, requestData, aStateFlags,
-                              aStatus, stateChangeData);
-
-  return NS_OK;
+  return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 NS_IMETHODIMP BrowserChild::OnProgressChange(nsIWebProgress* aWebProgress,
                                              nsIRequest* aRequest,
                                              int32_t aCurSelfProgress,
                                              int32_t aMaxSelfProgress,
                                              int32_t aCurTotalProgress,
                                              int32_t aMaxTotalProgress) {
--- a/dom/ipc/BrowserParent.cpp
+++ b/dom/ipc/BrowserParent.cpp
@@ -2268,64 +2268,16 @@ mozilla::ipc::IPCResult BrowserParent::R
   if (registrar) {
     registrar->RegisterProtocolHandler(aScheme, aHandlerURI, aTitle, aDocURI,
                                        mFrameElement);
   }
 
   return IPC_OK();
 }
 
-mozilla::ipc::IPCResult BrowserParent::RecvOnStateChange(
-    const Maybe<WebProgressData>& aWebProgressData,
-    const RequestData& aRequestData, const uint32_t aStateFlags,
-    const nsresult aStatus,
-    const Maybe<WebProgressStateChangeData>& aStateChangeData) {
-  nsCOMPtr<nsIBrowser> browser =
-      mFrameElement ? mFrameElement->AsBrowser() : nullptr;
-
-  if (!browser) {
-    return IPC_OK();
-  }
-
-  nsCOMPtr<nsIWebProgress> manager;
-  nsresult rv = browser->GetRemoteWebProgressManager(getter_AddRefs(manager));
-  NS_ENSURE_SUCCESS(rv, IPC_OK());
-
-  nsCOMPtr<nsIWebProgressListener> managerAsListener =
-      do_QueryInterface(manager);
-
-  if (!managerAsListener) {
-    // We are no longer remote, so we cannot propagate this message.
-    return IPC_OK();
-  }
-
-  nsCOMPtr<nsIWebProgress> webProgress;
-  nsCOMPtr<nsIRequest> request;
-  ReconstructWebProgressAndRequest(manager, aWebProgressData, aRequestData,
-                                   webProgress, request);
-
-  if (aWebProgressData && aWebProgressData->isTopLevel()) {
-    Unused << browser->SetIsNavigating(aStateChangeData->isNavigating());
-    Unused << browser->SetMayEnableCharacterEncodingMenu(
-        aStateChangeData->mayEnableCharacterEncodingMenu());
-    Unused << browser->UpdateForStateChange(aStateChangeData->charset(),
-                                            aStateChangeData->documentURI(),
-                                            aStateChangeData->contentType());
-  } else if (aStateChangeData.isSome()) {
-    return IPC_FAIL(
-        this,
-        "Unexpected WebProgressStateChangeData for non-top-level WebProgress");
-  }
-
-  Unused << managerAsListener->OnStateChange(webProgress, request, aStateFlags,
-                                             aStatus);
-
-  return IPC_OK();
-}
-
 mozilla::ipc::IPCResult BrowserParent::RecvOnProgressChange(
     const Maybe<WebProgressData>& aWebProgressData,
     const RequestData& aRequestData, const int32_t aCurSelfProgress,
     const int32_t aMaxSelfProgress, const int32_t aCurTotalProgress,
     const int32_t aMaxTotalProgress) {
   nsCOMPtr<nsIBrowser> browser =
       mFrameElement ? mFrameElement->AsBrowser() : nullptr;
 
--- a/dom/ipc/BrowserParent.h
+++ b/dom/ipc/BrowserParent.h
@@ -165,22 +165,16 @@ class BrowserParent final : public PBrow
 
   mozilla::ipc::IPCResult RecvSetHasBeforeUnload(const bool& aHasBeforeUnload);
 
   mozilla::ipc::IPCResult RecvRegisterProtocolHandler(const nsString& aScheme,
                                                       nsIURI* aHandlerURI,
                                                       const nsString& aTitle,
                                                       nsIURI* aDocURI);
 
-  mozilla::ipc::IPCResult RecvOnStateChange(
-      const Maybe<WebProgressData>& awebProgressData,
-      const RequestData& aRequestData, const uint32_t aStateFlags,
-      const nsresult aStatus,
-      const Maybe<WebProgressStateChangeData>& aStateChangeData);
-
   mozilla::ipc::IPCResult RecvOnProgressChange(
       const Maybe<WebProgressData>& aWebProgressData,
       const RequestData& aRequestData, const int32_t aCurSelfProgress,
       const int32_t aMaxSelfProgress, const int32_t aCurTotalProgres,
       const int32_t aMaxTotalProgress);
 
   mozilla::ipc::IPCResult RecvOnStatusChange(
       const Maybe<WebProgressData>& aWebProgressData,
--- a/dom/ipc/PBrowser.ipdl
+++ b/dom/ipc/PBrowser.ipdl
@@ -113,28 +113,16 @@ struct WebProgressData
 
 struct RequestData
 {
   nsIURI requestURI;
   nsIURI originalRequestURI;
   nsCString matchedList;
 };
 
-struct WebProgressStateChangeData
-{
-  bool isNavigating;
-  bool mayEnableCharacterEncodingMenu;
-
-  // The following fields are only set when the aStateFlags param passed with
-  // this struct is |nsIWebProgress.STATE_STOP|.
-  nsString contentType;
-  nsString charset;
-  nsIURI documentURI;
-};
-
 nested(upto inside_cpow) sync protocol PBrowser
 {
     manager PContent;
 
     manages PColorPicker;
     manages PDocAccessible;
     manages PFilePicker;
     manages PPluginWidget;
@@ -544,21 +532,16 @@ parent:
 
     async AccessKeyNotHandled(WidgetKeyboardEvent event);
 
     async SetHasBeforeUnload(bool aHasBeforeUnload);
 
     async RegisterProtocolHandler(nsString scheme, nsIURI handlerURI, nsString title,
                                   nsIURI documentURI);
 
-    async OnStateChange(WebProgressData? aWebProgressData,
-                        RequestData aRequestData, uint32_t aStateFlags,
-                        nsresult aStatus,
-                        WebProgressStateChangeData? aStateChangeData);
-
     async OnProgressChange(WebProgressData? aWebProgressData,
                            RequestData aRequestData, int32_t aCurSelfProgress,
                            int32_t aMaxSelfProgress, int32_t aCurTotalProgress,
                            int32_t aMaxTotalProgress);
 
     async OnStatusChange(WebProgressData? aWebProgressData,
                          RequestData aRequestData, nsresult aStatus,
                          nsString aMessage);
--- a/toolkit/actors/WebNavigationChild.jsm
+++ b/toolkit/actors/WebNavigationChild.jsm
@@ -51,19 +51,21 @@ class WebNavigationChild extends ActorCh
         break;
       case "WebNavigation:Stop":
         this.stop(message.data.flags);
         break;
     }
   }
 
   _wrapURIChangeCall(fn) {
+    this.mm.WebProgress.inLoadURI = true;
     try {
       fn();
     } finally {
+      this.mm.WebProgress.inLoadURI = false;
       this.mm.WebProgress.sendLoadCallResult();
     }
   }
 
   goBack(params) {
     if (this.webNavigation.canGoBack) {
       this.mm.docShell.setCancelContentJSEpoch(params.cancelContentJSEpoch);
       this._wrapURIChangeCall(() => this.webNavigation.goBack());
--- a/toolkit/content/widgets/browser-custom-element.js
+++ b/toolkit/content/widgets/browser-custom-element.js
@@ -37,22 +37,16 @@ class MozBrowser extends MozElements.Moz
     }
   }
 
   constructor() {
     super();
 
     this.onPageHide = this.onPageHide.bind(this);
 
-    this.isNavigating = false;
-
-    this._documentURI = null;
-    this._characterSet = null;
-    this._documentContentType = null;
-
     /**
      * These are managed by the tabbrowser:
      */
     this.droppedLinkHandler = null;
     this.mIconURL = null;
     this.lastURI = null;
 
     this.addEventListener("keypress", (event) => {
@@ -353,26 +347,16 @@ class MozBrowser extends MozElements.Moz
 
   get documentContentType() {
     if (this.isRemoteBrowser) {
       return this._documentContentType;
     }
     return this.contentDocument ? this.contentDocument.contentType : null;
   }
 
-  set documentContentType(aContentType) {
-    if (aContentType != null) {
-      if (this.isRemoteBrowser) {
-        this._documentContentType = aContentType;
-      } else {
-        this.contentDocument.documentContentType = aContentType;
-      }
-    }
-  }
-
   set sameProcessAsFrameLoader(val) {
     this._sameProcessAsFrameLoader = Cu.getWeakReference(val);
   }
 
   get sameProcessAsFrameLoader() {
     return this._sameProcessAsFrameLoader && this._sameProcessAsFrameLoader.get();
   }
 
@@ -605,22 +589,16 @@ class MozBrowser extends MozElements.Moz
   get characterSet() {
     return this.isRemoteBrowser ? this._characterSet : this.docShell.charset;
   }
 
   get mayEnableCharacterEncodingMenu() {
     return this.isRemoteBrowser ? this._mayEnableCharacterEncodingMenu : this.docShell.mayEnableCharacterEncodingMenu;
   }
 
-  set mayEnableCharacterEncodingMenu(aMayEnable) {
-    if (this.isRemoteBrowser) {
-      this._mayEnableCharacterEncodingMenu = aMayEnable;
-    }
-  }
-
   get contentPrincipal() {
     return this.isRemoteBrowser ? this._contentPrincipal : this.contentDocument.nodePrincipal;
   }
 
   get csp() {
     // After Bug 965637 we can query the csp directly from the contentDocument
     // instead of contentDocument.nodePrincipal.
     return this.isRemoteBrowser ? this._csp : this.contentDocument.nodePrincipal.csp;
@@ -776,21 +754,21 @@ class MozBrowser extends MozElements.Moz
   }
 
   get dontPromptAndUnload() {
     return 2;
   }
 
   _wrapURIChangeCall(fn) {
     if (!this.isRemoteBrowser) {
-      this.isNavigating = true;
+      this.inLoadURI = true;
       try {
         fn();
       } finally {
-        this.isNavigating = false;
+        this.inLoadURI = false;
       }
     } else {
       fn();
     }
   }
 
   goBack() {
     var webNavigation = this.webNavigation;
@@ -1039,17 +1017,17 @@ class MozBrowser extends MozElements.Moz
   unselectedTabHover(hovered) {
     if (!this._shouldSendUnselectedTabHover) {
       return;
     }
     this.messageManager.sendAsyncMessage("Browser:UnselectedTabHover", { hovered });
   }
 
   didStartLoadSinceLastUserTyping() {
-    return !this.isNavigating &&
+    return !this.inLoadURI &&
       this.urlbarChangeTracker._startedLoadSinceLastUserTyping;
   }
 
   construct() {
     elementsToDestroyOnUnload.add(this);
     this.resetFields();
     this.mInitialized = true;
     if (this.isRemoteBrowser) {
@@ -1387,32 +1365,16 @@ class MozBrowser extends MozElements.Moz
       this._securityUI._updateContentBlockingEvent(aEvent);
     }
   }
 
   get remoteWebProgressManager() {
     return this._remoteWebProgressManager;
   }
 
-  updateForStateChange(aCharset, aDocumentURI, aContentType) {
-    if (this.isRemoteBrowser && this.messageManager) {
-      if (aCharset != null) {
-        this._characterSet = aCharset;
-      }
-
-      if (aDocumentURI != null) {
-        this._documentURI = aDocumentURI;
-      }
-
-      if (aContentType != null) {
-        this._documentContentType = aContentType;
-      }
-    }
-  }
-
   purgeSessionHistory() {
     if (this.isRemoteBrowser) {
       try {
         this.messageManager.sendAsyncMessage("Browser:PurgeSessionHistory");
       } catch (ex) {
         // This can throw if the browser has started to go away.
         if (ex.result != Cr.NS_ERROR_NOT_INITIALIZED) {
           throw ex;
--- a/toolkit/modules/RemoteWebProgress.jsm
+++ b/toolkit/modules/RemoteWebProgress.jsm
@@ -23,23 +23,25 @@ class RemoteWebProgressManager {
       /* aIsTopLevel = */ true);
     this._progressListeners = [];
 
     this.swapBrowser(aBrowser);
   }
 
   swapBrowser(aBrowser) {
     if (this._messageManager) {
+      this._messageManager.removeMessageListener("Content:StateChange", this);
       this._messageManager.removeMessageListener("Content:LocationChange", this);
       this._messageManager.removeMessageListener("Content:SecurityChange", this);
       this._messageManager.removeMessageListener("Content:LoadURIResult", this);
     }
 
     this._browser = aBrowser;
     this._messageManager = aBrowser.messageManager;
+    this._messageManager.addMessageListener("Content:StateChange", this);
     this._messageManager.addMessageListener("Content:LocationChange", this);
     this._messageManager.addMessageListener("Content:SecurityChange", this);
     this._messageManager.addMessageListener("Content:LoadURIResult", this);
   }
 
   swapListeners(aOtherRemoteWebProgressManager) {
     let temp = aOtherRemoteWebProgressManager.progressListeners;
     aOtherRemoteWebProgressManager._progressListeners = this._progressListeners;
@@ -151,17 +153,17 @@ class RemoteWebProgressManager {
   }
 
   receiveMessage(aMessage) {
     let json = aMessage.json;
     // This message is a custom one we send as a result of a loadURI call.
     // It shouldn't go through the same processing as all the forwarded
     // webprogresslistener messages.
     if (aMessage.name == "Content:LoadURIResult") {
-      this._browser.isNavigating = false;
+      this._browser.inLoadURI = false;
       return;
     }
 
     let webProgress = null;
     let isTopLevel = json.webProgress && json.webProgress.isTopLevel;
     // The top-level WebProgress is always the same, but because we don't
     // really have a concept of subframes/content we always create a new object
     // for those.
@@ -186,26 +188,33 @@ class RemoteWebProgressManager {
     }
 
     if (isTopLevel) {
       // Setting a content-type back to `null` is quite nonsensical for the
       // frontend, especially since we're not expecting it.
       if (json.documentContentType !== null) {
         this._browser._documentContentType = json.documentContentType;
       }
-      if (typeof json.isNavigating != "undefined") {
-        this._browser.isNavigating = json.isNavigating;
+      if (typeof json.inLoadURI != "undefined") {
+        this._browser.inLoadURI = json.inLoadURI;
       }
       if (json.charset) {
         this._browser._characterSet = json.charset;
         this._browser._mayEnableCharacterEncodingMenu = json.mayEnableCharacterEncodingMenu;
       }
     }
 
     switch (aMessage.name) {
+    case "Content:StateChange":
+      if (isTopLevel) {
+        this._browser._documentURI = Services.io.newURI(json.documentURI);
+      }
+      this.onStateChange(webProgress, request, json.stateFlags, json.status);
+      break;
+
     case "Content:LocationChange":
       let location = Services.io.newURI(json.location);
       let flags = json.flags;
       let remoteWebNav = this._browser._remoteWebNavigationImpl;
 
       // These properties can change even for a sub-frame navigation.
       remoteWebNav.canGoBack = json.canGoBack;
       remoteWebNav.canGoForward = json.canGoForward;
--- a/toolkit/modules/WebProgressChild.jsm
+++ b/toolkit/modules/WebProgressChild.jsm
@@ -20,20 +20,21 @@ XPCOMUtils.defineLazyServiceGetter(this,
 XPCOMUtils.defineLazyServiceGetter(this, "serializationHelper",
                                    "@mozilla.org/network/serialization-helper;1",
                                    "nsISerializationHelper");
 
 class WebProgressChild {
   constructor(mm) {
     this.mm = mm;
 
-    // NOTIFY_PROGRESS, NOTIFY_STATE_ALL, NOTIFY_STATUS, NOTIFY_REFRESH, and
+    this.inLoadURI = false;
+
+    // NOTIFY_PROGRESS, NOTIFY_STATUS, NOTIFY_REFRESH, and
     // NOTIFY_CONTENT_BLOCKING are handled by PBrowser.
     let notifyCode = Ci.nsIWebProgress.NOTIFY_ALL &
-                        ~Ci.nsIWebProgress.NOTIFY_STATE_ALL &
                         ~Ci.nsIWebProgress.NOTIFY_PROGRESS &
                         ~Ci.nsIWebProgress.NOTIFY_STATUS &
                         ~Ci.nsIWebProgress.NOTIFY_REFRESH &
                         ~Ci.nsIWebProgress.NOTIFY_CONTENT_BLOCKING;
 
     this._filter = Cc["@mozilla.org/appshell/component/browser-status-filter;1"]
                      .createInstance(Ci.nsIWebProgress);
     this._filter.addProgressListener(this, notifyCode);
@@ -95,16 +96,36 @@ class WebProgressChild {
       innerWindowID,
     };
   }
 
   _send(name, data) {
     this.mm.sendAsyncMessage(name, data);
   }
 
+  onStateChange(aWebProgress, aRequest, aStateFlags, aStatus) {
+    let json = this._setupJSON(aWebProgress, aRequest, aStateFlags);
+
+    json.stateFlags = aStateFlags;
+    json.status = aStatus;
+
+    // It's possible that this state change was triggered by
+    // loading an internal error page, for which the parent
+    // will want to know some details, so we'll update it with
+    // the documentURI.
+    if (aWebProgress && aWebProgress.isTopLevel) {
+      json.documentURI = this.mm.content.document.documentURIObject.spec;
+      json.charset = this.mm.content.document.characterSet;
+      json.mayEnableCharacterEncodingMenu = this.mm.docShell.mayEnableCharacterEncodingMenu;
+      json.inLoadURI = this.inLoadURI;
+    }
+
+    this._send("Content:StateChange", json);
+  }
+
   onLocationChange(aWebProgress, aRequest, aLocationURI, aFlags) {
     let json = this._setupJSON(aWebProgress, aRequest);
 
     json.location = aLocationURI ? aLocationURI.spec : "";
     json.flags = aFlags;
 
     // These properties can change even for a sub-frame navigation.
     let webNav = this.mm.docShell.QueryInterface(Ci.nsIWebNavigation);
@@ -117,17 +138,17 @@ class WebProgressChild {
       json.charset = this.mm.content.document.characterSet;
       json.mayEnableCharacterEncodingMenu = this.mm.docShell.mayEnableCharacterEncodingMenu;
       json.principal = this.mm.content.document.nodePrincipal;
       // After Bug 965637 we can query the csp directly from content.document
       // instead of content.document.nodePrincipal.
       let csp = this.mm.content.document.nodePrincipal.csp;
       json.csp = E10SUtils.serializeCSP(csp);
       json.synthetic = this.mm.content.document.mozSyntheticDocument;
-      json.isNavigating = this.mm.docShell.isNavigating;
+      json.inLoadURI = this.inLoadURI;
       json.requestContextID = this.mm.content.document.documentLoadGroup
         ? this.mm.content.document.documentLoadGroup.requestContextID
         : null;
 
       if (AppConstants.MOZ_CRASHREPORTER && CrashReporter.enabled) {
         let uri = aLocationURI;
         try {
           // If the current URI contains a username/password, remove it.