diff --git a/browser/base/content/test/performance/browser_startup_content.js b/browser/base/content/test/performance/browser_startup_content.js index 1df6116eaf95..bb4aee2ca44f 100644 --- a/browser/base/content/test/performance/browser_startup_content.js +++ b/browser/base/content/test/performance/browser_startup_content.js @@ -49,7 +49,6 @@ const whitelist = { "resource://gre/modules/ActorManagerChild.jsm", "resource://gre/modules/E10SUtils.jsm", "resource://gre/modules/Readerable.jsm", - "resource://gre/modules/WebProgressChild.jsm", // Telemetry "resource://gre/modules/TelemetryController.jsm", // bug 1470339 diff --git a/devtools/client/responsive/browser/tunnel.js b/devtools/client/responsive/browser/tunnel.js index 599dce68a4cc..868bf4cb0685 100644 --- a/devtools/client/responsive/browser/tunnel.js +++ b/devtools/client/responsive/browser/tunnel.js @@ -103,7 +103,6 @@ function tunnelToInnerBrowser(outer, inner) { onLocationChange: (webProgress, request, location, flags) => { if (webProgress && webProgress.isTopLevel) { - inner._securityUI = outer._securityUI; inner._documentURI = outer._documentURI; inner._documentContentType = outer._documentContentType; inner._contentTitle = outer._contentTitle; @@ -117,6 +116,10 @@ function tunnelToInnerBrowser(outer, inner) { } }, + // We do not need an onSecurityChange handler since the remote security UI + // has been copied from the inner (remote) browser to the outer (non-remote) + // browser and they share it. + QueryInterface: ChromeUtils.generateQI([ Ci.nsISupportsWeakReference, Ci.nsIWebProgressListener, @@ -464,8 +467,6 @@ MessageManagerTunnel.prototype = { "Link:AddFeed", "Link:AddSearch", "PageStyle:StyleSheets", - // Messages sent to RemoteWebProgress.jsm - "Content:SecurityChange", // Messages sent to browser.js "DOMTitleChanged", "ImageDocumentLoaded", diff --git a/dom/interfaces/base/nsIBrowser.idl b/dom/interfaces/base/nsIBrowser.idl index 30ecbd82e90b..bfcf059e6d57 100644 --- a/dom/interfaces/base/nsIBrowser.idl +++ b/dom/interfaces/base/nsIBrowser.idl @@ -5,6 +5,7 @@ interface nsIContentSecurityPolicy; interface nsIPrincipal; +interface nsITransportSecurityInfo; interface nsIURI; interface nsIWebProgress; interface nsIReferrerInfo; @@ -164,4 +165,18 @@ interface nsIBrowser : nsISupports in boolean aHasRequestContextID, in uint64_t aRequestContextID, in AString aContentType); + + /** + * Called by Gecko when a security chang event needs to update the event + * state stored in the security UI object stored in the parent process. + * + * @param aSecurityInfo the transport security information from the content + * process + * @param aState the flags from the OnSecurityChange event that triggered + * this method, as outlined in nsIWebProgressListener + * @param aIsSecureContext whether or not the context is secure + */ + void updateSecurityUIForSecurityChange(in nsITransportSecurityInfo aSecurityInfo, + in uint32_t aState, + in boolean aIsSecureContext); }; diff --git a/dom/ipc/BrowserChild.cpp b/dom/ipc/BrowserChild.cpp index eed0d5e7caaa..5d1d58fa95d9 100644 --- a/dom/ipc/BrowserChild.cpp +++ b/dom/ipc/BrowserChild.cpp @@ -528,23 +528,20 @@ nsresult BrowserChild::Init(mozIDOMWindowProxy* aParent, nsCOMPtr docShell = do_GetInterface(WebNavigation()); MOZ_ASSERT(docShell); - const uint32_t notifyMask = - nsIWebProgress::NOTIFY_STATE_ALL | nsIWebProgress::NOTIFY_PROGRESS | - nsIWebProgress::NOTIFY_STATUS | nsIWebProgress::NOTIFY_LOCATION | - nsIWebProgress::NOTIFY_REFRESH | nsIWebProgress::NOTIFY_CONTENT_BLOCKING; - mStatusFilter = new nsBrowserStatusFilter(); RefPtr eventTarget = TabGroup()->EventTargetFor(TaskCategory::Network); mStatusFilter->SetTarget(eventTarget); - nsresult rv = mStatusFilter->AddProgressListener(this, notifyMask); + nsresult rv = + mStatusFilter->AddProgressListener(this, nsIWebProgress::NOTIFY_ALL); NS_ENSURE_SUCCESS(rv, rv); { nsCOMPtr webProgress = do_QueryInterface(docShell); - rv = webProgress->AddProgressListener(mStatusFilter, notifyMask); + rv = webProgress->AddProgressListener(mStatusFilter, + nsIWebProgress::NOTIFY_ALL); NS_ENSURE_SUCCESS(rv, rv); } @@ -3697,8 +3694,59 @@ NS_IMETHODIMP BrowserChild::OnStatusChange(nsIWebProgress* aWebProgress, NS_IMETHODIMP BrowserChild::OnSecurityChange(nsIWebProgress* aWebProgress, nsIRequest* aRequest, uint32_t aState) { - return NS_ERROR_NOT_IMPLEMENTED; + if (!IPCOpen() || !mShouldSendWebProgressEventsToParent) { + return NS_OK; + } + + Maybe webProgressData; + RequestData requestData; + + MOZ_TRY(PrepareProgressListenerData(aWebProgress, aRequest, webProgressData, + requestData)); + + Maybe securityChangeData; + + if (aWebProgress && webProgressData->isTopLevel()) { + nsCOMPtr docShell = do_GetInterface(WebNavigation()); + if (!docShell) { + return NS_OK; + } + + nsCOMPtr securityInfo; + { + nsCOMPtr securityUI; + MOZ_TRY(docShell->GetSecurityUI(getter_AddRefs(securityUI))); + + if (securityUI) { + MOZ_TRY(securityUI->GetSecInfo(getter_AddRefs(securityInfo))); + } + } + + bool isSecureContext = false; + { + nsCOMPtr outerWindow = do_GetInterface(docShell); + if (!outerWindow) { + return NS_OK; + } + + if (nsPIDOMWindowInner* window = outerWindow->GetCurrentInnerWindow()) { + isSecureContext = window->IsSecureContext(); + } else { + return NS_OK; + } + } + + securityChangeData.emplace(); + securityChangeData->securityInfo() = securityInfo.forget(); + securityChangeData->isSecureContext() = isSecureContext; + } + + Unused << SendOnSecurityChange(webProgressData, requestData, aState, + securityChangeData); + + return NS_OK; } + NS_IMETHODIMP BrowserChild::OnContentBlockingEvent(nsIWebProgress* aWebProgress, nsIRequest* aRequest, uint32_t aEvent) { diff --git a/dom/ipc/BrowserParent.cpp b/dom/ipc/BrowserParent.cpp index 111be3ef01c2..f23371f7409a 100644 --- a/dom/ipc/BrowserParent.cpp +++ b/dom/ipc/BrowserParent.cpp @@ -2565,6 +2565,35 @@ mozilla::ipc::IPCResult BrowserParent::RecvOnStatusChange( return IPC_OK(); } +mozilla::ipc::IPCResult BrowserParent::RecvOnSecurityChange( + const Maybe& aWebProgressData, + const RequestData& aRequestData, const uint32_t aState, + const Maybe& aSecurityChangeData) { + nsCOMPtr browser; + nsCOMPtr manager; + nsCOMPtr managerAsListener; + if (!GetWebProgressListener(getter_AddRefs(browser), getter_AddRefs(manager), + getter_AddRefs(managerAsListener))) { + return IPC_OK(); + } + + nsCOMPtr webProgress; + nsCOMPtr request; + ReconstructWebProgressAndRequest(manager, aWebProgressData, aRequestData, + getter_AddRefs(webProgress), + getter_AddRefs(request)); + + if (aWebProgressData && aWebProgressData->isTopLevel()) { + Unused << browser->UpdateSecurityUIForSecurityChange( + aSecurityChangeData->securityInfo(), aState, + aSecurityChangeData->isSecureContext()); + } + + Unused << managerAsListener->OnSecurityChange(webProgress, request, aState); + + return IPC_OK(); +} + mozilla::ipc::IPCResult BrowserParent::RecvOnContentBlockingEvent( const Maybe& aWebProgressData, const RequestData& aRequestData, const uint32_t& aEvent) { diff --git a/dom/ipc/BrowserParent.h b/dom/ipc/BrowserParent.h index 13fa2c63a25c..5db49e78d1b7 100644 --- a/dom/ipc/BrowserParent.h +++ b/dom/ipc/BrowserParent.h @@ -311,6 +311,11 @@ class BrowserParent final : public PBrowserParent, const RequestData& aRequestData, const nsresult aStatus, const nsString& aMessage); + mozilla::ipc::IPCResult RecvOnSecurityChange( + const Maybe& aWebProgressData, + const RequestData& aRequestData, const uint32_t aState, + const Maybe& aSecurityChangeData); + mozilla::ipc::IPCResult RecvOnContentBlockingEvent( const Maybe& aWebProgressData, const RequestData& aRequestData, const uint32_t& aEvent); diff --git a/dom/ipc/PBrowser.ipdl b/dom/ipc/PBrowser.ipdl index 17834e4515c6..97583fb0fe5e 100644 --- a/dom/ipc/PBrowser.ipdl +++ b/dom/ipc/PBrowser.ipdl @@ -30,6 +30,7 @@ include PBackgroundSharedTypes; include "mozilla/GfxMessageUtils.h"; include "mozilla/layers/LayersMessageUtils.h"; +include "mozilla/ipc/TransportSecurityInfoUtils.h"; using mozilla::gfx::Matrix4x4 from "mozilla/gfx/Matrix.h"; using mozilla::gfx::MaybeMatrix4x4 from "mozilla/gfx/Matrix.h"; @@ -91,6 +92,7 @@ using mozilla::ScrollAxis from "mozilla/PresShellForwards.h"; using mozilla::ScrollFlags from "mozilla/PresShellForwards.h"; using struct InputFormData from "mozilla/dom/SessionStoreMessageUtils.h"; using struct CollectedInputDataValue from "mozilla/dom/SessionStoreMessageUtils.h"; +using refcounted class nsITransportSecurityInfo from "nsITransportSecurityInfo.h"; namespace mozilla { namespace dom { @@ -161,6 +163,12 @@ struct WebProgressLocationChangeData uint64_t? requestContextID; }; +struct WebProgressSecurityChangeData +{ + nsITransportSecurityInfo securityInfo; + bool isSecureContext; +}; + /** * A PBrowser manages a maximal locally connected subtree of BrowsingContexts * in a content process. @@ -600,6 +608,10 @@ parent: RequestData aRequestData, nsresult aStatus, nsString aMessage); + async OnSecurityChange(WebProgressData? aWebProgressData, + RequestData aRequestData, uint32_t aState, + WebProgressSecurityChangeData? aSecurityChangeData); + async OnContentBlockingEvent(WebProgressData? aWebProgressData, RequestData aRequestData, uint32_t aEvent); diff --git a/toolkit/content/browser-child.js b/toolkit/content/browser-child.js index 7e759390e1c9..3663406ab76b 100644 --- a/toolkit/content/browser-child.js +++ b/toolkit/content/browser-child.js @@ -10,12 +10,6 @@ ChromeUtils.defineModuleGetter( "resource://gre/modules/BrowserUtils.jsm" ); -const { WebProgressChild } = ChromeUtils.import( - "resource://gre/modules/WebProgressChild.jsm" -); - -this.WebProgress = new WebProgressChild(this); - try { docShell .QueryInterface(Ci.nsIInterfaceRequestor) diff --git a/toolkit/content/widgets/browser-custom-element.js b/toolkit/content/widgets/browser-custom-element.js index 149bbebc3799..98b1ce21cb68 100644 --- a/toolkit/content/widgets/browser-custom-element.js +++ b/toolkit/content/widgets/browser-custom-element.js @@ -1264,8 +1264,6 @@ this.messageManager.addMessageListener("DOMTitleChanged", this); this.messageManager.addMessageListener("ImageDocumentLoaded", this); - // browser-child messages, such as Content:LocationChange, are handled in - // RemoteWebProgress, ensure it is loaded and ready. let jsm = "resource://gre/modules/RemoteWebProgress.jsm"; let { RemoteWebProgressManager } = ChromeUtils.import(jsm, {}); @@ -1514,6 +1512,16 @@ } } + updateSecurityUIForSecurityChange(aSecurityInfo, aState, aIsSecureContext) { + if (this.isRemoteBrowser && this.messageManager) { + // Invoking this getter triggers the generation of the underlying object, + // which we need to access with ._securityUI, because .securityUI returns + // a wrapper that makes _update inaccessible. + void this.securityUI; + this._securityUI._update(aSecurityInfo, aState, aIsSecureContext); + } + } + updateSecurityUIForContentBlockingEvent(aEvent) { if (this.isRemoteBrowser && this.messageManager) { // Invoking this getter triggers the generation of the underlying object, diff --git a/toolkit/modules/RemoteWebProgress.jsm b/toolkit/modules/RemoteWebProgress.jsm index 2606eb7fa978..a4e781196edb 100644 --- a/toolkit/modules/RemoteWebProgress.jsm +++ b/toolkit/modules/RemoteWebProgress.jsm @@ -5,17 +5,11 @@ var EXPORTED_SYMBOLS = ["RemoteWebProgressManager"]; -const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm"); const RemoteWebProgress = Components.Constructor( "@mozilla.org/dom/remote-web-progress;1", "nsIRemoteWebProgress", "init" ); -const RemoteWebProgressRequest = Components.Constructor( - "@mozilla.org/dom/remote-web-progress-request;1", - "nsIRemoteWebProgressRequest", - "init" -); class RemoteWebProgressManager { constructor(aBrowser) { @@ -29,16 +23,7 @@ class RemoteWebProgressManager { } swapBrowser(aBrowser) { - if (this._messageManager) { - this._messageManager.removeMessageListener( - "Content:SecurityChange", - this - ); - } - this._browser = aBrowser; - this._messageManager = aBrowser.messageManager; - this._messageManager.addMessageListener("Content:SecurityChange", this); } swapListeners(aOtherRemoteWebProgressManager) { @@ -69,20 +54,6 @@ class RemoteWebProgressManager { ); } - _fixSecInfo(aSecInfo) { - let deserialized = null; - if (aSecInfo) { - let helper = Cc["@mozilla.org/network/serialization-helper;1"].getService( - Ci.nsISerializationHelper - ); - - deserialized = helper.deserializeObject(aSecInfo); - deserialized.QueryInterface(Ci.nsITransportSecurityInfo); - } - - return deserialized; - } - setCurrentURI(aURI) { // This function is simpler than nsDocShell::SetCurrentURI since // it doesn't have to deal with child docshells. @@ -183,56 +154,6 @@ class RemoteWebProgressManager { aEvent ); } - - receiveMessage(aMessage) { - let json = aMessage.json; - 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. - if (json.webProgress) { - webProgress = isTopLevel - ? this._topLevelWebProgress - : new RemoteWebProgress(this, isTopLevel); - webProgress.update( - json.webProgress.DOMWindowID, - 0, - json.webProgress.loadType, - json.webProgress.isLoadingDocument - ); - webProgress.QueryInterface(Ci.nsIWebProgress); - } - - // The WebProgressRequest object however is always dynamic. - let request = null; - if (json.requestURI) { - request = new RemoteWebProgressRequest( - Services.io.newURI(json.requestURI), - Services.io.newURI(json.originalRequestURI) - ); - request = request.QueryInterface(Ci.nsIRequest); - } - - switch (aMessage.name) { - case "Content:SecurityChange": - let state = json.state; - - if (isTopLevel) { - let secInfo = this._fixSecInfo(json.secInfo); - let isSecureContext = json.isSecureContext; - - // Invoking this getter triggers the generation of the underlying object, - // which we need to access with ._securityUI, because .securityUI returns - // a wrapper that makes _update inaccessible. - void this._browser.securityUI; - this._browser._securityUI._update(secInfo, state, isSecureContext); - } - - this.onSecurityChange(webProgress, request, state); - break; - } - } } RemoteWebProgressManager.prototype.QueryInterface = ChromeUtils.generateQI([ diff --git a/toolkit/modules/WebProgressChild.jsm b/toolkit/modules/WebProgressChild.jsm deleted file mode 100644 index c711d2657ac2..000000000000 --- a/toolkit/modules/WebProgressChild.jsm +++ /dev/null @@ -1,110 +0,0 @@ -/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ -/* 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/. */ -"use strict"; - -var EXPORTED_SYMBOLS = ["WebProgressChild"]; - -const { XPCOMUtils } = ChromeUtils.import( - "resource://gre/modules/XPCOMUtils.jsm" -); - -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_LOCATION, 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_LOCATION & - ~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); - this._filter.target = this.mm.tabEventTarget; - - let webProgress = this.mm.docShell - .QueryInterface(Ci.nsIInterfaceRequestor) - .getInterface(Ci.nsIWebProgress); - webProgress.addProgressListener(this._filter, notifyCode); - } - - _requestSpec(aRequest, aPropertyName) { - if (!aRequest || !(aRequest instanceof Ci.nsIChannel)) { - return null; - } - return aRequest[aPropertyName].spec; - } - - _setupJSON(aWebProgress, aRequest) { - if (aWebProgress) { - let domWindowID = null; - try { - domWindowID = aWebProgress.DOMWindowID; - } catch (e) { - // The DOM Window ID getters above may throw if the inner or outer - // windows aren't created yet or are destroyed at the time we're making - // this call but that isn't fatal so ignore the exceptions here. - } - - aWebProgress = { - isTopLevel: aWebProgress.isTopLevel, - isLoadingDocument: aWebProgress.isLoadingDocument, - loadType: aWebProgress.loadType, - DOMWindowID: domWindowID, - }; - } - - return { - webProgress: aWebProgress || null, - requestURI: this._requestSpec(aRequest, "URI"), - originalRequestURI: this._requestSpec(aRequest, "originalURI"), - }; - } - - _send(name, data) { - this.mm.sendAsyncMessage(name, data); - } - - getSecInfoAsString() { - let secInfo = this.mm.docShell.securityUI.secInfo; - if (secInfo) { - return serializationHelper.serializeToString(secInfo); - } - - return null; - } - - onSecurityChange(aWebProgress, aRequest, aState) { - let json = this._setupJSON(aWebProgress, aRequest); - - json.state = aState; - - if (aWebProgress.isTopLevel) { - json.secInfo = this.getSecInfoAsString(); - json.isSecureContext = this.mm.content.isSecureContext; - } - - this._send("Content:SecurityChange", json); - } -} - -WebProgressChild.prototype.QueryInterface = ChromeUtils.generateQI([ - "nsIWebProgressListener", - "nsISupportsWeakReference", -]); diff --git a/toolkit/modules/moz.build b/toolkit/modules/moz.build index a67e1aca601a..eceece8466ee 100644 --- a/toolkit/modules/moz.build +++ b/toolkit/modules/moz.build @@ -229,7 +229,6 @@ EXTRA_JS_MODULES += [ 'Troubleshoot.jsm', 'UpdateUtils.jsm', 'WebChannel.jsm', - 'WebProgressChild.jsm', 'ZipUtils.jsm', ]