author | Ehsan Akhgari <ehsan@mozilla.com> |
Sat, 22 Sep 2018 20:29:07 -0400 | |
changeset 438799 | f8849239da42a6d2aae6415871ea9ed3b7ae4992 |
parent 438798 | d0997972e4d417f275fe39815c73e092023ccbdd |
child 438800 | acbf4450b55e5b8f863ef5c1b2eb6b3f49adaa5b |
push id | 34736 |
push user | aiakab@mozilla.com |
push date | Sat, 29 Sep 2018 04:16:58 +0000 |
treeherder | mozilla-central@13b0256be449 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | baku |
bugs | 1493563 |
milestone | 64.0a1 |
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
|
--- a/accessible/base/DocManager.cpp +++ b/accessible/base/DocManager.cpp @@ -339,17 +339,19 @@ DocManager::OnStatusChange(nsIWebProgres { MOZ_ASSERT_UNREACHABLE("notification excluded in AddProgressListener(...)"); return NS_OK; } NS_IMETHODIMP DocManager::OnSecurityChange(nsIWebProgress* aWebProgress, nsIRequest* aRequest, - uint32_t aState) + uint32_t aOldState, + uint32_t aState, + const nsAString& aContentBlockingLogJSON) { MOZ_ASSERT_UNREACHABLE("notification excluded in AddProgressListener(...)"); return NS_OK; } //////////////////////////////////////////////////////////////////////////////// // nsIDOMEventListener
--- a/browser/base/content/browser-contentblocking.js +++ b/browser/base/content/browser-contentblocking.js @@ -459,17 +459,18 @@ var ContentBlocking = { shieldHistogramAdd(value) { if (PrivateBrowsingUtils.isWindowPrivate(window)) { return; } Services.telemetry.getHistogramById("TRACKING_PROTECTION_SHIELD").add(value); }, - onSecurityChange(state, webProgress, isSimulated) { + onSecurityChange(oldState, state, webProgress, isSimulated, + contentBlockingLogJSON) { let baseURI = this._baseURIForChannelClassifier; // Don't deal with about:, file: etc. if (!baseURI) { this.iconBox.removeAttribute("animate"); this.iconBox.removeAttribute("active"); this.iconBox.removeAttribute("hasException"); return;
--- a/browser/base/content/browser.js +++ b/browser/base/content/browser.js @@ -4984,17 +4984,18 @@ var XULBrowserWindow = { _lastLocation: null, // This is called in multiple ways: // 1. Due to the nsIWebProgressListener.onSecurityChange notification. // 2. Called by tabbrowser.xml when updating the current browser. // 3. Called directly during this object's initializations. // aRequest will be null always in case 2 and 3, and sometimes in case 1 (for // instance, there won't be a request when STATE_BLOCKED_TRACKING_CONTENT is observed). - onSecurityChange(aWebProgress, aRequest, aState, aIsSimulated) { + onSecurityChange(aWebProgress, aRequest, aOldState, aState, + aContentBlockingLogJSON, aIsSimulated) { // Don't need to do anything if the data we use to update the UI hasn't // changed let uri = gBrowser.currentURI; let spec = uri.spec; if (this._state == aState && this._lastLocation == spec) { // Switching to a tab of the same URL doesn't change most security // information, but tab specific permissions may be different. @@ -5011,17 +5012,18 @@ var XULBrowserWindow = { // Make sure the "https" part of the URL is striked out or not, // depending on the current mixed active content blocking state. gURLBar.formatValue(); try { uri = Services.uriFixup.createExposableURI(uri); } catch (e) {} gIdentityHandler.updateIdentity(this._state, uri); - ContentBlocking.onSecurityChange(this._state, aWebProgress, aIsSimulated); + ContentBlocking.onSecurityChange(aOldState, this._state, aWebProgress, aIsSimulated, + aContentBlockingLogJSON); }, // simulate all change notifications after switching tabs onUpdateCurrentBrowser: function XWB_onUpdateCurrentBrowser(aStateFlags, aStatus, aMessage, aTotalProgress) { if (FullZoom.updateBackgroundTabs) FullZoom.onLocationChange(gBrowser.currentURI, true); CombinedStopReload.onTabSwitch();
--- a/browser/base/content/tabbrowser.js +++ b/browser/base/content/tabbrowser.js @@ -939,18 +939,23 @@ window._gBrowser = { this._callProgressListeners(null, "onLocationChange", [webProgress, null, newBrowser.currentURI, 0, true], true, false); let securityUI = newBrowser.securityUI; if (securityUI) { // Include the true final argument to indicate that this event is // simulated (instead of being observed by the webProgressListener). + // Note: check state first to make sure the security UI object updates its + // state from the docshell correctly. + let state = securityUI.state; + let oldState = securityUI.oldState; this._callProgressListeners(null, "onSecurityChange", - [webProgress, null, securityUI.state, true], + [webProgress, null, oldState, state, + securityUI.contentBlockingLogJSON, true], true, false); } let listener = this._tabListeners.get(newTab); if (listener && listener.mStateFlags) { this._callProgressListeners(null, "onUpdateCurrentBrowser", [listener.mStateFlags, listener.mStatus, listener.mMessage, listener.mTotalProgress], @@ -1660,22 +1665,27 @@ window._gBrowser = { this._tabListeners.set(tab, listener); filter.addProgressListener(listener, Ci.nsIWebProgress.NOTIFY_ALL); // Restore the progress listener. aBrowser.webProgress.addProgressListener(filter, Ci.nsIWebProgress.NOTIFY_ALL); // Restore the securityUI state. let securityUI = aBrowser.securityUI; + // Make sure to call the state getter before the oldState getter to give + // the securityUI object a chance to sync its state with the docshell let state = securityUI ? securityUI.state : Ci.nsIWebProgressListener.STATE_IS_INSECURE; + let oldState = securityUI ? securityUI.oldState : + Ci.nsIWebProgressListener.STATE_IS_INSECURE; // Include the true final argument to indicate that this event is // simulated (instead of being observed by the webProgressListener). this._callProgressListeners(aBrowser, "onSecurityChange", - [aBrowser.webProgress, null, state, true], + [aBrowser.webProgress, null, oldState, state, + securityUI.contentBlockingLogJSON, true], true, false); if (aShouldBeRemote) { // Switching the browser to be remote will connect to a new child // process so the browser can no longer be considered to be // crashed. tab.removeAttribute("crashed"); } else { @@ -5055,19 +5065,20 @@ class TabProgressListener { return; this._callProgressListeners("onStatusChange", [aWebProgress, aRequest, aStatus, aMessage]); this.mMessage = aMessage; } - onSecurityChange(aWebProgress, aRequest, aState) { + onSecurityChange(aWebProgress, aRequest, aOldState, aState, aContentBlockingLogJSON) { this._callProgressListeners("onSecurityChange", - [aWebProgress, aRequest, aState]); + [aWebProgress, aRequest, aOldState, aState, + aContentBlockingLogJSON]); } onRefreshAttempted(aWebProgress, aURI, aDelay, aSameURI) { return this._callProgressListeners("onRefreshAttempted", [aWebProgress, aURI, aDelay, aSameURI]); } } TabProgressListener.prototype.QueryInterface = ChromeUtils.generateQI(
--- a/browser/base/content/test/general/browser_alltabslistener.js +++ b/browser/base/content/test/general/browser_alltabslistener.js @@ -21,17 +21,18 @@ var gFrontProgressListener = { ok(gFrontNotificationsPos < gFrontNotifications.length, "Got an expected notification for the front notifications listener"); is(state, gFrontNotifications[gFrontNotificationsPos], "Got a notification for the front notifications listener"); gFrontNotificationsPos++; }, onStatusChange(aWebProgress, aRequest, aStatus, aMessage) { }, - onSecurityChange(aWebProgress, aRequest, aState) { + onSecurityChange(aWebProgress, aRequest, aOldState, aState, + aContentBlockingLogJSON) { var state = "onSecurityChange"; info("FrontProgress: " + state + " 0x" + aState.toString(16)); ok(gFrontNotificationsPos < gFrontNotifications.length, "Got an expected notification for the front notifications listener"); is(state, gFrontNotifications[gFrontNotificationsPos], "Got a notification for the front notifications listener"); gFrontNotificationsPos++; }, }; @@ -61,17 +62,18 @@ var gAllProgressListener = { gAllNotificationsPos++; }, onStatusChange(aBrowser, aWebProgress, aRequest, aStatus, aMessage) { var state = "onStatusChange"; ok(aBrowser == gTestBrowser, state + " notification came from the correct browser"); }, - onSecurityChange(aBrowser, aWebProgress, aRequest, aState) { + onSecurityChange(aBrowser, aWebProgress, aRequest, aOldState, aState, + aContentBlockingLogJSON) { var state = "onSecurityChange"; info("AllProgress: " + state + " 0x" + aState.toString(16)); ok(aBrowser == gTestBrowser, state + " notification came from the correct browser"); ok(gAllNotificationsPos < gAllNotifications.length, "Got an expected notification for the all notifications listener"); is(state, gAllNotifications[gAllNotificationsPos], "Got a notification for the all notifications listener"); gAllNotificationsPos++; }, };
--- a/browser/components/extensions/parent/ext-tabs.js +++ b/browser/components/extensions/parent/ext-tabs.js @@ -1196,17 +1196,18 @@ this.tabs = class extends ExtensionAPI { } if (pageSettings.footerRight !== null) { printSettings.footerStrRight = pageSettings.footerRight; } let printProgressListener = { onLocationChange(webProgress, request, location, flags) { }, onProgressChange(webProgress, request, curSelfProgress, maxSelfProgress, curTotalProgress, maxTotalProgress) { }, - onSecurityChange(webProgress, request, state) { }, + onSecurityChange(webProgress, request, oldState, state, + contentBlockingLogJSON) { }, onStateChange(webProgress, request, flags, status) { if ((flags & Ci.nsIWebProgressListener.STATE_STOP) && (flags & Ci.nsIWebProgressListener.STATE_IS_DOCUMENT)) { resolve(retval == 0 ? "saved" : "replaced"); } }, onStatusChange: function(webProgress, request, status, message) { if (status != 0) { resolve(retval == 0 ? "not_saved" : "not_replaced");
--- a/browser/components/shell/nsMacShellService.cpp +++ b/browser/components/shell/nsMacShellService.cpp @@ -186,17 +186,19 @@ nsMacShellService::OnStatusChange(nsIWeb const char16_t* aMessage) { return NS_OK; } NS_IMETHODIMP nsMacShellService::OnSecurityChange(nsIWebProgress* aWebProgress, nsIRequest* aRequest, - uint32_t aState) + uint32_t aOldState, + uint32_t aState, + const nsAString& aContentBlockingLogJSON) { return NS_OK; } NS_IMETHODIMP nsMacShellService::OnStateChange(nsIWebProgress* aWebProgress, nsIRequest* aRequest, uint32_t aStateFlags,
--- a/docshell/base/nsDocShell.cpp +++ b/docshell/base/nsDocShell.cpp @@ -7002,17 +7002,19 @@ nsDocShell::OnStatusChange(nsIWebProgres nsresult aStatus, const char16_t* aMessage) { MOZ_ASSERT_UNREACHABLE("notification excluded in AddProgressListener(...)"); return NS_OK; } NS_IMETHODIMP nsDocShell::OnSecurityChange(nsIWebProgress* aWebProgress, - nsIRequest* aRequest, uint32_t aState) + nsIRequest* aRequest, uint32_t aOldState, + uint32_t aState, + const nsAString& aContentBlockingLogJSON) { MOZ_ASSERT_UNREACHABLE("notification excluded in AddProgressListener(...)"); return NS_OK; } nsresult nsDocShell::EndPageLoad(nsIWebProgress* aProgress, nsIChannel* aChannel, nsresult aStatus)
--- a/docshell/base/nsDocShellTreeOwner.cpp +++ b/docshell/base/nsDocShellTreeOwner.cpp @@ -762,17 +762,19 @@ nsDocShellTreeOwner::OnStatusChange(nsIW const char16_t* aMessage) { return NS_OK; } NS_IMETHODIMP nsDocShellTreeOwner::OnSecurityChange(nsIWebProgress* aWebProgress, nsIRequest* aRequest, - uint32_t aState) + uint32_t aOldState, + uint32_t aState, + const nsAString& aContentBlockingLogJSON) { return NS_OK; } //***************************************************************************** // nsDocShellTreeOwner: Accessors //*****************************************************************************
--- a/dom/base/ContentBlockingLog.h +++ b/dom/base/ContentBlockingLog.h @@ -2,31 +2,46 @@ /* 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 mozilla_dom_ContentBlockingLog_h #define mozilla_dom_ContentBlockingLog_h +#include "mozilla/JSONWriter.h" #include "mozilla/Pair.h" #include "mozilla/UniquePtr.h" #include "nsClassHashtable.h" #include "nsHashKeys.h" +#include "nsReadableUtils.h" #include "nsTArray.h" namespace mozilla { namespace dom { class ContentBlockingLog final { // Each element is a pair of (type, blocked). The type values come from the // blocking types defined in nsIWebProgressListener. typedef nsTArray<mozilla::Pair<uint32_t, bool>> OriginLog; + struct StringWriteFunc : public JSONWriteFunc + { + nsAString& mBuffer; // The lifetime of the struct must be bound to the buffer + explicit StringWriteFunc(nsAString& aBuffer) + : mBuffer(aBuffer) + {} + + void Write(const char* aStr) override + { + mBuffer.Append(NS_ConvertUTF8toUTF16(aStr)); + } + }; + public: ContentBlockingLog() = default; ~ContentBlockingLog() = default; void RecordLog(const nsAString& aOrigin, uint32_t aType, bool aBlocked) { if (aOrigin.IsVoid()) { return; @@ -38,16 +53,47 @@ public: entry.OrInsert([=] { auto log(MakeUnique<OriginLog>()); log->AppendElement(mozilla::MakePair(aType, aBlocked)); return log.release(); }); } } + nsAutoString Stringify() + { + nsAutoString buffer; + + JSONWriter w(MakeUnique<StringWriteFunc>(buffer)); + w.Start(); + + for (auto iter = mLog.Iter(); !iter.Done(); iter.Next()) { + if (!iter.UserData()) { + w.StartArrayProperty(NS_ConvertUTF16toUTF8(iter.Key()).get(), w.SingleLineStyle); + w.EndArray(); + continue; + } + + w.StartArrayProperty(NS_ConvertUTF16toUTF8(iter.Key()).get(), w.SingleLineStyle); + for (auto& item: *iter.UserData()) { + w.StartArrayElement(w.SingleLineStyle); + { + w.IntElement(item.first()); + w.BoolElement(item.second()); + } + w.EndArray(); + } + w.EndArray(); + } + + w.End(); + + return buffer; + } + private: nsClassHashtable<nsStringHashKey, OriginLog> mLog; }; } // namespace dom } // namespace mozilla #endif
--- a/dom/browser-element/BrowserElementChildPreload.js +++ b/dom/browser-element/BrowserElementChildPreload.js @@ -1534,17 +1534,18 @@ BrowserElementChild.prototype = { } catch (e) {} sendAsyncMsg('error', { type: 'other' }); return; } } }, - onSecurityChange: function(webProgress, request, state) { + onSecurityChange: function(webProgress, request, oldState, state, + contentBlockingLogJSON) { if (webProgress != docShell) { return; } var securityStateDesc; if (state & Ci.nsIWebProgressListener.STATE_IS_SECURE) { securityStateDesc = 'secure'; }
--- a/dom/clients/manager/ClientNavigateOpChild.cpp +++ b/dom/clients/manager/ClientNavigateOpChild.cpp @@ -123,17 +123,18 @@ public: nsresult aStatus, const char16_t* aMessage) override { MOZ_CRASH("Unexpected notification."); return NS_OK; } NS_IMETHOD OnSecurityChange(nsIWebProgress* aWebProgress, nsIRequest* aRequest, - uint32_t aState) override + uint32_t aOldState, uint32_t aState, + const nsAString& aContentBlockingLogJSON) override { MOZ_CRASH("Unexpected notification."); return NS_OK; } NS_DECL_ISUPPORTS };
--- a/dom/clients/manager/ClientOpenWindowUtils.cpp +++ b/dom/clients/manager/ClientOpenWindowUtils.cpp @@ -128,17 +128,19 @@ public: { MOZ_ASSERT(false, "Unexpected notification."); return NS_OK; } NS_IMETHOD OnSecurityChange(nsIWebProgress* aWebProgress, nsIRequest* aRequest, - uint32_t aState) override + uint32_t aOldState, + uint32_t aState, + const nsAString& aContentBlockingLogJSON) override { MOZ_ASSERT(false, "Unexpected notification."); return NS_OK; } private: ~WebProgressListener() {
--- a/dom/html/HTMLFormElement.cpp +++ b/dom/html/HTMLFormElement.cpp @@ -2126,17 +2126,19 @@ HTMLFormElement::OnStatusChange(nsIWebPr { MOZ_ASSERT_UNREACHABLE("notification excluded in AddProgressListener(...)"); return NS_OK; } NS_IMETHODIMP HTMLFormElement::OnSecurityChange(nsIWebProgress* aWebProgress, nsIRequest* aRequest, - uint32_t state) + uint32_t aOldState, + uint32_t aState, + const nsAString& aContentBlockingLogJSON) { MOZ_ASSERT_UNREACHABLE("notification excluded in AddProgressListener(...)"); return NS_OK; } NS_IMETHODIMP_(int32_t) HTMLFormElement::IndexOfControl(nsIFormControl* aControl) {
--- a/dom/html/nsHTMLDNSPrefetch.cpp +++ b/dom/html/nsHTMLDNSPrefetch.cpp @@ -572,17 +572,19 @@ nsHTMLDNSPrefetch::nsDeferrals::OnStatus const char16_t* aMessage) { return NS_OK; } NS_IMETHODIMP nsHTMLDNSPrefetch::nsDeferrals::OnSecurityChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, - uint32_t state) + uint32_t aOldState, + uint32_t aState, + const nsAString& aContentBlockingLogJSON) { return NS_OK; } //////////// nsIObserver method NS_IMETHODIMP nsHTMLDNSPrefetch::nsDeferrals::Observe(nsISupports *subject,
--- a/dom/presentation/PresentationCallbacks.cpp +++ b/dom/presentation/PresentationCallbacks.cpp @@ -268,13 +268,15 @@ PresentationResponderLoadingCallback::On { // Do nothing. return NS_OK; } NS_IMETHODIMP PresentationResponderLoadingCallback::OnSecurityChange(nsIWebProgress* aWebProgress, nsIRequest* aRequest, - uint32_t state) + uint32_t aOldState, + uint32_t aState, + const nsAString& aContentBlockingLogJSON) { // Do nothing. return NS_OK; }
--- a/editor/composer/nsEditingSession.cpp +++ b/editor/composer/nsEditingSession.cpp @@ -808,17 +808,20 @@ nsEditingSession::OnStatusChange(nsIWebP /*--------------------------------------------------------------------------- OnSecurityChange ----------------------------------------------------------------------------*/ NS_IMETHODIMP nsEditingSession::OnSecurityChange(nsIWebProgress *aWebProgress, - nsIRequest *aRequest, uint32_t state) + nsIRequest *aRequest, + uint32_t aOldState, + uint32_t aState, + const nsAString& aContentBlockingLogJSON) { MOZ_ASSERT_UNREACHABLE("notification excluded in AddProgressListener(...)"); return NS_OK; } /*---------------------------------------------------------------------------
--- a/editor/composer/test/test_bug434998.xul +++ b/editor/composer/test/test_bug434998.xul @@ -82,17 +82,18 @@ https://bugzilla.mozilla.org/show_bug.cg onLocationChange : function(aWebProgress, aRequest, aLocation, aFlags) { }, onStatusChange : function(aWebProgress, aRequest, aStatus, aMessage) { }, - onSecurityChange : function(aWebProgress, aRequest, aState) + onSecurityChange : function(aWebProgress, aRequest, aOldState, aState, + aContentBlockingLogJSON) { }, mEditor: null }; var progress, progressListener;
--- a/editor/libeditor/tests/test_bug607584.xul +++ b/editor/libeditor/tests/test_bug607584.xul @@ -88,17 +88,18 @@ https://bugzilla.mozilla.org/show_bug.cg onLocationChange : function(aWebProgress, aRequest, aLocation, aFlags) { }, onStatusChange : function(aWebProgress, aRequest, aStatus, aMessage) { }, - onSecurityChange : function(aWebProgress, aRequest, aState) + onSecurityChange : function(aWebProgress, aRequest, aOldState, aState, + aContentBlockingLogJSON) { }, mEditor: null }; var progress, progressListener;
--- a/editor/libeditor/tests/test_bug616590.xul +++ b/editor/libeditor/tests/test_bug616590.xul @@ -77,17 +77,18 @@ https://bugzilla.mozilla.org/show_bug.cg onLocationChange : function(aWebProgress, aRequest, aLocation, aFlags) { }, onStatusChange : function(aWebProgress, aRequest, aStatus, aMessage) { }, - onSecurityChange : function(aWebProgress, aRequest, aState) + onSecurityChange : function(aWebProgress, aRequest, aOldState, aState, + aContentBlockingLogJSON) { }, mEditor: null }; var progress, progressListener;
--- a/editor/libeditor/tests/test_bug780908.xul +++ b/editor/libeditor/tests/test_bug780908.xul @@ -86,17 +86,18 @@ adapted from test_bug607584.xul by Kent onLocationChange : function(aWebProgress, aRequest, aLocation, aFlags) { }, onStatusChange : function(aWebProgress, aRequest, aStatus, aMessage) { }, - onSecurityChange : function(aWebProgress, aRequest, aState) + onSecurityChange : function(aWebProgress, aRequest, aOldState, aState, + aContentBlockingLogJSON) { }, mEditor: null }; var progress, progressListener;
--- a/layout/base/tests/chrome/printpreview_bug396024_helper.xul +++ b/layout/base/tests/chrome/printpreview_bug396024_helper.xul @@ -18,17 +18,18 @@ var SimpleTest = window.opener.wrappedJS var gWbp; function printpreview() { gWbp = window.frames[1].docShell.printPreview; var listener = { onLocationChange: function(webProgress, request, location, flags) { }, onProgressChange: function(webProgress, request, curSelfProgress, maxSelfProgress, curTotalProgress, maxTotalProgress) { }, - onSecurityChange: function(webProgress, request, state) { }, + onSecurityChange: function(webProgress, request, oldState, state, + contentBlockingLogJSON) { }, onStateChange: function(webProgress, request, stateFlags, status) { }, onStatusChange: function(webProgress, request, status, message) { }, QueryInterface: function(iid) { if (iid.equals(Ci.nsIWebProgressListener) || iid.equals(Ci.nsISupportsWeakReference)) return this; throw Cr.NS_NOINTERFACE; }
--- a/layout/base/tests/chrome/printpreview_bug482976_helper.xul +++ b/layout/base/tests/chrome/printpreview_bug482976_helper.xul @@ -18,17 +18,18 @@ var SimpleTest = window.opener.wrappedJS var gWbp; function printpreview() { gWbp = window.frames[1].docShell.printPreview; var listener = { onLocationChange: function(webProgress, request, location, flags) { }, onProgressChange: function(webProgress, request, curSelfProgress, maxSelfProgress, curTotalProgress, maxTotalProgress) { }, - onSecurityChange: function(webProgress, request, state) { }, + onSecurityChange: function(webProgress, request, oldState, state, + contentBlockingLogJSON) { }, onStateChange: function(webProgress, request, stateFlags, status) { }, onStatusChange: function(webProgress, request, status, message) { }, QueryInterface: function(iid) { if (iid.equals(Ci.nsIWebProgessListener) || iid.equals(Ci.nsISupportsWeakReference)) return this; throw Cr.NS_NOINTERFACE; }
--- a/layout/base/tests/chrome/printpreview_helper.xul +++ b/layout/base/tests/chrome/printpreview_helper.xul @@ -25,17 +25,18 @@ filePath = file.path; function printpreview() { gWbp = window.frames[1].docShell.printPreview; var listener = { onLocationChange: function(webProgress, request, location, flags) { }, onProgressChange: function(webProgress, request, curSelfProgress, maxSelfProgress, curTotalProgress, maxTotalProgress) { }, - onSecurityChange: function(webProgress, request, state) { }, + onSecurityChange: function(webProgress, request, oldState, state, + contentBlockingLogJSON) { }, onStateChange: function(webProgress, request, stateFlags, status) { }, onStatusChange: function(webProgress, request, status, message) { }, QueryInterface: function(iid) { if (iid.equals(Ci.nsIWebProgressListener) || iid.equals(Ci.nsISupportsWeakReference)) return this; throw Cr.NS_NOINTERFACE; }
--- a/layout/printing/ipc/RemotePrintJobChild.cpp +++ b/layout/printing/ipc/RemotePrintJobChild.cpp @@ -158,17 +158,20 @@ RemotePrintJobChild::OnStatusChange(nsIW Unused << SendStatusChange(aStatus); } return NS_OK; } NS_IMETHODIMP RemotePrintJobChild::OnSecurityChange(nsIWebProgress* aProgress, - nsIRequest* aRequest, uint32_t aState) + nsIRequest* aRequest, + uint32_t aState, + uint32_t aOldState, + const nsAString& aContentBlockingLogJSON) { return NS_OK; } // End of nsIWebProgressListener RemotePrintJobChild::~RemotePrintJobChild() {
--- a/layout/printing/nsPrintJob.cpp +++ b/layout/printing/nsPrintJob.cpp @@ -2111,17 +2111,19 @@ nsPrintJob::OnStatusChange(nsIWebProgres { MOZ_ASSERT_UNREACHABLE("notification excluded in AddProgressListener(...)"); return NS_OK; } NS_IMETHODIMP nsPrintJob::OnSecurityChange(nsIWebProgress* aWebProgress, nsIRequest* aRequest, - uint32_t aState) + uint32_t aState, + uint32_t aOldState, + const nsAString& aContentBlockingLogJSON) { MOZ_ASSERT_UNREACHABLE("notification excluded in AddProgressListener(...)"); return NS_OK; } //------------------------------------------------------- void
--- a/layout/tools/layout-debug/ui/content/layoutdebug.js +++ b/layout/tools/layout-debug/ui/content/layoutdebug.js @@ -72,17 +72,18 @@ nsLDBBrowserContentListener.prototype = this.setButtonEnabled(this.mBackButton, gBrowser.canGoBack); }, onStatusChange : function(aWebProgress, aRequest, aStatus, aMessage) { this.mStatusText.value = aMessage; }, - onSecurityChange : function(aWebProgress, aRequest, aState) + onSecurityChange : function(aWebProgress, aRequest, aOldState, aState, + aContentBlockingLogJSON) { }, // non-interface methods setButtonEnabled : function(aButtonElement, aEnabled) { if (aEnabled) aButtonElement.removeAttribute("disabled");
--- a/mobile/android/chrome/content/browser.js +++ b/mobile/android/chrome/content/browser.js @@ -4699,17 +4699,18 @@ Tab.prototype = { Services.obs.notifyObservers(this.browser, "Session:NotifyLocationChange"); } }, // Properties used to cache security state used to update the UI _state: null, _hostChanged: false, // onLocationChange will flip this bit - onSecurityChange: function(aWebProgress, aRequest, aState) { + onSecurityChange: function(aWebProgress, aRequest, aOldState, aState, + aContentBlockingLogJSON) { // Don't need to do anything if the data we use to update the UI hasn't changed if (this._state == aState && !this._hostChanged) return; this._state = aState; this._hostChanged = false; let identity = IdentityHandler.checkIdentity(aState, this.browser);
--- a/mobile/android/modules/geckoview/GeckoViewProgress.jsm +++ b/mobile/android/modules/geckoview/GeckoViewProgress.jsm @@ -247,17 +247,18 @@ class GeckoViewProgress extends GeckoVie type: "GeckoView:PageStop", success: isSuccess }; this.eventDispatcher.sendRequest(message); } } - onSecurityChange(aWebProgress, aRequest, aState) { + onSecurityChange(aWebProgress, aRequest, aOldState, aState, + aContentBlockingLogJSON) { debug `onSecurityChange`; // Don't need to do anything if the data we use to update the UI hasn't changed if (this._state === aState && !this._hostChanged) { return; } this._state = aState;
--- a/mobile/android/modules/geckoview/GeckoViewTrackingProtection.jsm +++ b/mobile/android/modules/geckoview/GeckoViewTrackingProtection.jsm @@ -15,17 +15,18 @@ class GeckoViewTrackingProtection extend const flags = Ci.nsIWebProgress.NOTIFY_SECURITY; this.progressFilter = Cc["@mozilla.org/appshell/component/browser-status-filter;1"] .createInstance(Ci.nsIWebProgress); this.progressFilter.addProgressListener(this, flags); this.browser.addProgressListener(this.progressFilter, flags); } - onSecurityChange(aWebProgress, aRequest, aState) { + onSecurityChange(aWebProgress, aRequest, aOldState, aState, + aContentBlockingLogJSON) { debug `onSecurityChange`; if (!(aState & Ci.nsIWebProgressListener.STATE_BLOCKED_TRACKING_CONTENT) || !aRequest || !(aRequest instanceof Ci.nsIClassifiedChannel)) { return; } let channel = aRequest.QueryInterface(Ci.nsIChannel);
--- a/netwerk/base/nsISecureBrowserUI.idl +++ b/netwerk/base/nsISecureBrowserUI.idl @@ -9,15 +9,40 @@ interface nsIDocShell; interface nsITransportSecurityInfo; [scriptable, uuid(718c662a-f810-4a80-a6c9-0b1810ecade2)] interface nsISecureBrowserUI : nsISupports { void init(in nsIDocShell docShell); + // A value composed of the Security State Flags and the Security + // Strength Flags defined in nsIWebProgressListener. + // Any undefined bits are reserved for future use. + // This represents the security state before the change. + readonly attribute unsigned long oldState; + // A value composed of the Security State Flags and the Security + // Strength Flags defined in nsIWebProgressListener. + // Any undefined bits are reserved for future use. + // This represents the security state after the change. readonly attribute unsigned long state; + // An optional JSON string representing a log of the content blocking + // events happened so far. This will be a JSON object containing keys + // representing origins that content blocking has acted on, with values + // being an array of items, each representing one action. Each action + // itself is an an array containing three elements, the first element + // being a blocking code from one of the Security State Flags above, and + // the second element being a boolean representing whether the origin + // was blocked (if true) or unblocked (if false) in that category, and + // the third element being the number of times that combination has been + // repeated consecutively. + // The reason JSON strings was chosen here was that we needed a format + // that is transferrable across processes in JS; and also the consumer + // of this data (browser-contentblocking.js) would be able to use the + // JSON.parse() API to parse out an object representation of the value. + readonly attribute AString contentBlockingLogJSON; + // Information about the connection security. readonly attribute nsITransportSecurityInfo secInfo; }; %{C++ #define NS_SECURE_BROWSER_UI_CONTRACTID "@mozilla.org/secure_browser_ui;1" %}
--- a/security/manager/ssl/nsSecureBrowserUIImpl.cpp +++ b/security/manager/ssl/nsSecureBrowserUIImpl.cpp @@ -58,16 +58,30 @@ nsSecureBrowserUIImpl::Init(nsIDocShell* if (NS_FAILED(rv)) { return rv; } return wp->AddProgressListener(this, nsIWebProgress::NOTIFY_LOCATION); } NS_IMETHODIMP +nsSecureBrowserUIImpl::GetOldState(uint32_t* aOldState) +{ + MOZ_ASSERT(NS_IsMainThread()); + NS_ENSURE_ARG(aOldState); + + MOZ_LOG(gSecureBrowserUILog, LogLevel::Debug, ("GetOldState %p", this)); + // Only sync our state with the docshell in GetState(). + MOZ_LOG(gSecureBrowserUILog, LogLevel::Debug, (" mOldState: %x", mOldState)); + + *aOldState = mOldState; + return NS_OK; +} + +NS_IMETHODIMP nsSecureBrowserUIImpl::GetState(uint32_t* aState) { MOZ_ASSERT(NS_IsMainThread()); NS_ENSURE_ARG(aState); MOZ_LOG(gSecureBrowserUILog, LogLevel::Debug, ("GetState %p", this)); // With respect to mixed content and tracking protection, we won't know when // the state of our document (or a subdocument) has changed, so we ask the @@ -75,16 +89,36 @@ nsSecureBrowserUIImpl::GetState(uint32_t CheckForBlockedContent(); MOZ_LOG(gSecureBrowserUILog, LogLevel::Debug, (" mState: %x", mState)); *aState = mState; return NS_OK; } NS_IMETHODIMP +nsSecureBrowserUIImpl::GetContentBlockingLogJSON(nsAString& aContentBlockingLogJSON) +{ + MOZ_ASSERT(NS_IsMainThread()); + + MOZ_LOG(gSecureBrowserUILog, LogLevel::Debug, ("GetContentBlockingLogJSON %p", this)); + aContentBlockingLogJSON.Truncate(); + nsCOMPtr<nsIDocShell> docShell = do_QueryReferent(mDocShell); + if (docShell) { + nsIDocument* doc = docShell->GetDocument(); + if (doc) { + aContentBlockingLogJSON = doc->GetContentBlockingLog()->Stringify(); + } + } + MOZ_LOG(gSecureBrowserUILog, LogLevel::Debug, + (" ContentBlockingLogJSON: %s", NS_ConvertUTF16toUTF8(aContentBlockingLogJSON).get())); + + return NS_OK; +} + +NS_IMETHODIMP nsSecureBrowserUIImpl::GetSecInfo(nsITransportSecurityInfo** result) { MOZ_ASSERT(NS_IsMainThread()); NS_ENSURE_ARG_POINTER(result); *result = mTopLevelSecurityInfo; NS_IF_ADDREF(*result); @@ -298,17 +332,17 @@ nsSecureBrowserUIImpl::OnLocationChange( return rv; } nsCOMPtr<nsISecurityEventSink> eventSink; NS_QueryNotificationCallbacks(channel, eventSink); if (NS_WARN_IF(!eventSink)) { return NS_ERROR_INVALID_ARG; } - ContentBlockingLog* contentBlockingLog = nullptr; + mozilla::dom::ContentBlockingLog* contentBlockingLog = nullptr; nsCOMPtr<nsIDocShell> docShell = do_QueryReferent(mDocShell); if (docShell) { nsIDocument* doc = docShell->GetDocument(); if (doc) { contentBlockingLog = doc->GetContentBlockingLog(); } } MOZ_LOG(gSecureBrowserUILog, LogLevel::Debug, @@ -348,13 +382,14 @@ nsSecureBrowserUIImpl::OnStatusChange(ns nsresult, const char16_t*) { MOZ_ASSERT_UNREACHABLE("Should have been excluded in AddProgressListener()"); return NS_OK; } nsresult -nsSecureBrowserUIImpl::OnSecurityChange(nsIWebProgress*, nsIRequest*, uint32_t) +nsSecureBrowserUIImpl::OnSecurityChange(nsIWebProgress*, nsIRequest*, uint32_t, + uint32_t, const nsAString&) { MOZ_ASSERT_UNREACHABLE("Should have been excluded in AddProgressListener()"); return NS_OK; }
--- a/toolkit/actors/PrintingChild.jsm +++ b/toolkit/actors/PrintingChild.jsm @@ -416,10 +416,11 @@ PrintingListener.prototype = { maxSelfProgress: aMaxSelfProgress, curTotalProgress: aCurTotalProgress, maxTotalProgress: aMaxTotalProgress, }); }, onLocationChange(aWebProgress, aRequest, aLocation, aFlags) {}, onStatusChange(aWebProgress, aRequest, aStatus, aMessage) {}, - onSecurityChange(aWebProgress, aRequest, aState) {}, + onSecurityChange(aWebProgress, aRequest, aOldState, aState, + aContentBlockingLogJSON) {}, };
--- a/toolkit/components/antitracking/test/browser/head.js +++ b/toolkit/components/antitracking/test/browser/head.js @@ -590,18 +590,19 @@ this.AntiTracking = { await AntiTracking._setupTest(win, options.cookieBehavior, options.blockingByContentBlocking, options.blockingByContentBlockingUI, options.blockingByContentBlockingRTUI, options.extraPrefs); let cookieBlocked = 0; let listener = { - onSecurityChange(webProgress, request, stateFlags, status) { - if (stateFlags & Ci.nsIWebProgressListener.STATE_COOKIES_BLOCKED_TRACKER) { + onSecurityChange(webProgress, request, oldState, state, + status, contentBlockingLogJSON) { + if (state & Ci.nsIWebProgressListener.STATE_COOKIES_BLOCKED_TRACKER) { ++cookieBlocked; } }, }; win.gBrowser.addProgressListener(listener); info("Creating a new tab"); let tab = BrowserTestUtils.addTab(win.gBrowser, TEST_TOP_PAGE);
--- a/toolkit/components/browser/nsWebBrowser.cpp +++ b/toolkit/components/browser/nsWebBrowser.cpp @@ -828,20 +828,23 @@ nsWebBrowser::OnStatusChange(nsIWebProgr aMessage); } return NS_OK; } NS_IMETHODIMP nsWebBrowser::OnSecurityChange(nsIWebProgress* aWebProgress, nsIRequest* aRequest, - uint32_t aState) + uint32_t aOldState, + uint32_t aState, + const nsAString& aContentBlockingLogJSON) { if (mProgressListener) { - return mProgressListener->OnSecurityChange(aWebProgress, aRequest, aState); + return mProgressListener->OnSecurityChange(aWebProgress, aRequest, aOldState, + aState, aContentBlockingLogJSON); } return NS_OK; } //***************************************************************************** // nsWebBrowser::nsIWebBrowserPersist //*****************************************************************************
--- a/toolkit/components/printing/content/printPreviewProgress.js +++ b/toolkit/components/printing/content/printPreviewProgress.js @@ -54,17 +54,18 @@ var progressListener = { if (docURLStr != docURL && dialog.title != null) { docURL = docURLStr; if (docTitle == "") dialog.title.value = docURLStr; } }, onLocationChange(aWebProgress, aRequest, aLocation, aFlags) {}, - onSecurityChange(aWebProgress, aRequest, state) {}, + onSecurityChange(aWebProgress, aRequest, aOldState, aState, + aContentBlockingLogJSON) {}, onStatusChange(aWebProgress, aRequest, aStatus, aMessage) { if (aMessage) dialog.title.setAttribute("value", aMessage); }, QueryInterface: ChromeUtils.generateQI(["nsIWebProgressListener", "nsISupportsWeakReference"]),
--- a/toolkit/components/printing/content/printProgress.js +++ b/toolkit/components/printing/content/printProgress.js @@ -139,17 +139,18 @@ var progressListener = { // we can ignore this notification }, onStatusChange(aWebProgress, aRequest, aStatus, aMessage) { if (aMessage != "") dialog.title.setAttribute("value", aMessage); }, - onSecurityChange(aWebProgress, aRequest, state) { + onSecurityChange(aWebProgress, aRequest, aOldState, aState, + aContentBlockingLogJSON) { // we can ignore this notification }, QueryInterface: ChromeUtils.generateQI(["nsIWebProgressListener", "nsISupportsWeakReference"]), }; function getString( stringId ) {
--- a/toolkit/components/printingui/ipc/PrintProgressDialogChild.cpp +++ b/toolkit/components/printingui/ipc/PrintProgressDialogChild.cpp @@ -95,17 +95,19 @@ PrintProgressDialogChild::OnStatusChange const char16_t* aMessage) { return NS_OK; } NS_IMETHODIMP PrintProgressDialogChild::OnSecurityChange(nsIWebProgress* aProgress, nsIRequest* aRequest, - uint32_t aState) + uint32_t aOldState, + uint32_t aState, + const nsAString& aContentBlockingLogJSON) { return NS_OK; } // nsIPrintProgressParams NS_IMETHODIMP PrintProgressDialogChild::GetDocTitle(nsAString& aDocTitle)
--- a/toolkit/components/printingui/nsPrintProgress.cpp +++ b/toolkit/components/printingui/nsPrintProgress.cpp @@ -239,17 +239,21 @@ NS_IMETHODIMP nsPrintProgress::OnStatusC nsCOMPtr<nsIWebProgressListener> progressListener = m_listenerList.SafeObjectAt(i); if (progressListener) progressListener->OnStatusChange(aWebProgress, aRequest, aStatus, aMessage); } return NS_OK; } -NS_IMETHODIMP nsPrintProgress::OnSecurityChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, uint32_t state) +NS_IMETHODIMP nsPrintProgress::OnSecurityChange(nsIWebProgress *aWebProgress, + nsIRequest *aRequest, + uint32_t aOldState, + uint32_t aState, + const nsAString& aContentBlockingLogJSON) { return NS_OK; } nsresult nsPrintProgress::ReleaseListeners() { m_listenerList.Clear();
--- a/toolkit/components/printingui/nsPrintingPromptService.cpp +++ b/toolkit/components/printingui/nsPrintingPromptService.cpp @@ -223,18 +223,21 @@ nsPrintingPromptService::OnStatusChange( } #endif return NS_OK; } NS_IMETHODIMP nsPrintingPromptService::OnSecurityChange(nsIWebProgress* aWebProgress, nsIRequest* aRequest, - uint32_t state) + uint32_t aOldState, + uint32_t aState, + const nsAString& aContentBlockingLogJSON) { #if !defined(XP_MACOSX) if (mWebProgressListener) { return mWebProgressListener->OnSecurityChange( - aWebProgress, aRequest, state); + aWebProgress, aRequest, aOldState, aState, + aContentBlockingLogJSON); } #endif return NS_OK; }
--- a/toolkit/components/statusfilter/nsBrowserStatusFilter.cpp +++ b/toolkit/components/statusfilter/nsBrowserStatusFilter.cpp @@ -260,22 +260,25 @@ nsBrowserStatusFilter::OnStatusChange(ns mDelayedStatus = true; return NS_OK; } NS_IMETHODIMP nsBrowserStatusFilter::OnSecurityChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, - uint32_t aState) + uint32_t aOldState, + uint32_t aState, + const nsAString& aContentBlockingLogJSON) { if (!mListener) return NS_OK; - return mListener->OnSecurityChange(aWebProgress, aRequest, aState); + return mListener->OnSecurityChange(aWebProgress, aRequest, aOldState, + aState, aContentBlockingLogJSON); } //----------------------------------------------------------------------------- // nsBrowserStatusFilter::nsIWebProgressListener2 //----------------------------------------------------------------------------- NS_IMETHODIMP nsBrowserStatusFilter::OnProgressChange64(nsIWebProgress *aWebProgress, nsIRequest *aRequest,
--- a/toolkit/components/url-classifier/tests/mochitest/test_threathit_report.html +++ b/toolkit/components/url-classifier/tests/mochitest/test_threathit_report.html @@ -189,17 +189,18 @@ function testOnWindow(aTestData) { (async function() { await new Promise(rs => whenDelayedStartupFinished(win, rs)); let expected; let browser = win.gBrowser.selectedBrowser; let wp = win.gBrowser.contentWindow.docShell.QueryInterface(Ci.nsIWebProgress); let progressListener = { - onSecurityChange(aWebProgress, aRequest, aState) { + onSecurityChange(aWebProgress, aRequest, aOldState, aState, + aContentBlockingLogJSON) { expected = aTestData.reportUrl; }, QueryInterface: ChromeUtils.generateQI(["nsISupportsWeakReference"]), }; wp.addProgressListener(progressListener, wp.NOTIFY_SECURITY); await BrowserTestUtils.loadURI(browser, aTestData.url); await BrowserTestUtils.waitForContentEvent(browser, "DOMContentLoaded");
--- a/toolkit/modules/RemoteSecurityUI.jsm +++ b/toolkit/modules/RemoteSecurityUI.jsm @@ -2,24 +2,30 @@ // 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/. var EXPORTED_SYMBOLS = ["RemoteSecurityUI"]; function RemoteSecurityUI() { this._secInfo = null; + this._oldState = 0; this._state = 0; + this._contentBlockingLogJSON = ""; } RemoteSecurityUI.prototype = { QueryInterface: ChromeUtils.generateQI([Ci.nsISecureBrowserUI]), // nsISecureBrowserUI + get oldState() { return this._oldState; }, get state() { return this._state; }, + get contentBlockingLogJSON() { return this._contentBlockingLogJSON; }, get tooltipText() { return ""; }, get secInfo() { return this._secInfo; }, - _update(aSecInfo, aState) { + _update(aSecInfo, aOldState, aState, aContentBlockingLogJSON) { this._secInfo = aSecInfo; + this._oldState = aOldState; this._state = aState; + this._contentBlockingLogJSON = aContentBlockingLogJSON; }, };
--- a/toolkit/modules/RemoteWebProgress.jsm +++ b/toolkit/modules/RemoteWebProgress.jsm @@ -104,27 +104,27 @@ RemoteWebProgressManager.prototype = { }); }, removeProgressListener(aListener) { this._progressListeners = this._progressListeners.filter(l => l.listener != aListener); }, - _fixSecInfoAndState(aSecInfo, aState) { + _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, aState]; + return deserialized; }, setCurrentURI(aURI) { // This function is simpler than nsDocShell::SetCurrentURI since // it doesn't have to deal with child docshells. let remoteWebNav = this._browser._remoteWebNavigationImpl; remoteWebNav._currentURI = aURI; @@ -235,29 +235,33 @@ RemoteWebProgressManager.prototype = { this._callProgressListeners( Ci.nsIWebProgress.NOTIFY_LOCATION, "onLocationChange", webProgress, request, location, flags ); break; case "Content:SecurityChange": - let [secInfo, state] = this._fixSecInfoAndState(json.secInfo, json.state); + let secInfo = this._fixSecInfo(json.secInfo); + let oldState = json.oldState; + let state = json.state; + let contentBlockingLogJSON = json.contentBlockingLogJSON; if (isTopLevel) { // 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); + this._browser._securityUI._update(secInfo, oldState, state, + contentBlockingLogJSON); } this._callProgressListeners( Ci.nsIWebProgress.NOTIFY_SECURITY, "onSecurityChange", webProgress, - request, state + request, oldState, state, contentBlockingLogJSON ); break; case "Content:StatusChange": this._callProgressListeners( Ci.nsIWebProgress.NOTIFY_STATUS, "onStatusChange", webProgress, request, json.status, json.message );
--- a/toolkit/modules/WebProgressChild.jsm +++ b/toolkit/modules/WebProgressChild.jsm @@ -208,22 +208,25 @@ class WebProgressChild { let secInfo = this.mm.docShell.securityUI.secInfo; if (secInfo) { return serializationHelper.serializeToString(secInfo); } return null; } - onSecurityChange(aWebProgress, aRequest, aState) { + onSecurityChange(aWebProgress, aRequest, aOldState, aState, + aContentBlockingLogJSON) { let json = this._setupJSON(aWebProgress, aRequest); let objects = this._setupObjects(aWebProgress, aRequest); + json.oldState = aOldState; json.state = aState; json.secInfo = this.getSecInfoAsString(); + json.contentBlockingLogJSON = aContentBlockingLogJSON; json.matchedList = null; if (aRequest && aRequest instanceof Ci.nsIClassifiedChannel) { json.matchedList = aRequest.matchedList; } this._send("Content:SecurityChange", json, objects); }
--- a/toolkit/mozapps/downloads/nsHelperAppDlg.js +++ b/toolkit/mozapps/downloads/nsHelperAppDlg.js @@ -65,17 +65,18 @@ nsUnknownContentTypeDialogProgressListen onStateChange(aWebProgress, aRequest, aStateFlags, aStatus) { }, onLocationChange(aWebProgress, aRequest, aLocation, aFlags) { }, - onSecurityChange(aWebProgress, aRequest, state) { + onSecurityChange(aWebProgress, aRequest, aOldState, aState, + aContentBlockingLogJSON) { }, onRefreshAttempted(aWebProgress, aURI, aDelay, aSameURI) { return true; }, }; // /////////////////////////////////////////////////////////////////////////////
--- a/toolkit/mozapps/extensions/content/extensions.js +++ b/toolkit/mozapps/extensions/content/extensions.js @@ -2130,17 +2130,18 @@ var gDiscoverView = { (!this.homepageURL.schemeIs("https") || aLocation.schemeIs("https"))) return; // Canceling the request will send an error to onStateChange which will show // the error page aRequest.cancel(Cr.NS_BINDING_ABORTED); }, - onSecurityChange(aWebProgress, aRequest, aState) { + onSecurityChange(aWebProgress, aRequest, aOldState, aState, + aContentBlockingLogJSON) { // Don't care about security if the page is not https if (!this.homepageURL.schemeIs("https")) return; // If the request was secure then it is ok if (aState & Ci.nsIWebProgressListener.STATE_IS_SECURE) return;
--- a/uriloader/base/nsDocLoader.cpp +++ b/uriloader/base/nsDocLoader.cpp @@ -1468,19 +1468,22 @@ NS_IMETHODIMP nsDocLoader::OnSecurityCha ContentBlockingLog* aContentBlockingLog) { // // Fire progress notifications out to any registered nsIWebProgressListeners. // nsCOMPtr<nsIRequest> request = do_QueryInterface(aContext); nsIWebProgress* webProgress = static_cast<nsIWebProgress*>(this); + nsAutoString contentBlockingLogJSON( + aContentBlockingLog ? aContentBlockingLog->Stringify() : EmptyString()); NOTIFY_LISTENERS(nsIWebProgress::NOTIFY_SECURITY, - listener->OnSecurityChange(webProgress, request, aState); + listener->OnSecurityChange(webProgress, request, aOldState, aState, + contentBlockingLogJSON); ); // Pass the notification up to the parent... if (mParent) { mParent->OnSecurityChange(aContext, aOldState, aState, aContentBlockingLog); } return NS_OK; }
--- a/uriloader/base/nsIWebProgressListener.idl +++ b/uriloader/base/nsIWebProgressListener.idl @@ -469,20 +469,35 @@ interface nsIWebProgressListener : nsISu * security transitions (eg HTTP -> HTTPS, HTTPS -> HTTP, FOO -> HTTPS) and * after document load completion. It might also be called if an error * occurs during network loading. * * @param aWebProgress * The nsIWebProgress instance that fired the notification. * @param aRequest * The nsIRequest that has new security state. + * @param aOldState + * A value composed of the Security State Flags and the Security + * Strength Flags listed above. Any undefined bits are reserved for + * future use. This represents the security state before the change. * @param aState * A value composed of the Security State Flags and the Security * Strength Flags listed above. Any undefined bits are reserved for - * future use. + * future use. This represents the security state after the change. + * @param aContentBlockingLog + * An optional JSON string representing a log of the content blocking + * events happened so far. This will be a JSON object containing keys + * representing origins that content blocking has acted on, with values + * being an array of items, each representing one action. Each action + * itself is an an array containing two elements, the first element + * being a blocking code from one of the Security State Flags above, and + * the second element being a boolean representing whether the origin + * was blocked (if true) or unblocked (if false) in that category. * * NOTE: These notifications will only occur if a security package is * installed. */ void onSecurityChange(in nsIWebProgress aWebProgress, in nsIRequest aRequest, - in unsigned long aState); + in unsigned long aOldState, + in unsigned long aState, + in AString aContentBlockingLogJSON); };
--- a/uriloader/prefetch/nsOfflineCacheUpdateService.cpp +++ b/uriloader/prefetch/nsOfflineCacheUpdateService.cpp @@ -217,17 +217,19 @@ nsOfflineCachePendingUpdate::OnStatusCha { MOZ_ASSERT_UNREACHABLE("notification excluded in AddProgressListener(...)"); return NS_OK; } NS_IMETHODIMP nsOfflineCachePendingUpdate::OnSecurityChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, - uint32_t state) + uint32_t aOldState, + uint32_t aState, + const nsAString& aContentBlockingLogJSON) { MOZ_ASSERT_UNREACHABLE("notification excluded in AddProgressListener(...)"); return NS_OK; } //----------------------------------------------------------------------------- // nsOfflineCacheUpdateService::nsISupports //-----------------------------------------------------------------------------
--- a/uriloader/prefetch/nsPrefetchService.cpp +++ b/uriloader/prefetch/nsPrefetchService.cpp @@ -1023,17 +1023,19 @@ nsPrefetchService::OnStatusChange(nsIWeb { MOZ_ASSERT_UNREACHABLE("notification excluded in AddProgressListener(...)"); return NS_OK; } NS_IMETHODIMP nsPrefetchService::OnSecurityChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, - uint32_t state) + uint32_t aOldState, + uint32_t aState, + const nsAString& aContentBlockingLogJSON) { MOZ_ASSERT_UNREACHABLE("notification excluded in AddProgressListener(...)"); return NS_OK; } //----------------------------------------------------------------------------- // nsPrefetchService::nsIObserver //-----------------------------------------------------------------------------
--- a/xpfe/appshell/nsChromeTreeOwner.cpp +++ b/xpfe/appshell/nsChromeTreeOwner.cpp @@ -494,17 +494,19 @@ nsChromeTreeOwner::OnStatusChange(nsIWeb return NS_OK; } NS_IMETHODIMP nsChromeTreeOwner::OnSecurityChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, - uint32_t state) + uint32_t aOldState, + uint32_t aState, + const nsAString& aContentBlockingLogJSON) { return NS_OK; } //***************************************************************************** // nsChromeTreeOwner: Helpers //*****************************************************************************
--- a/xpfe/appshell/nsWebShellWindow.cpp +++ b/xpfe/appshell/nsWebShellWindow.cpp @@ -671,17 +671,19 @@ nsWebShellWindow::OnStatusChange(nsIWebP { MOZ_ASSERT_UNREACHABLE("notification excluded in AddProgressListener(...)"); return NS_OK; } NS_IMETHODIMP nsWebShellWindow::OnSecurityChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, - uint32_t state) + uint32_t aOldState, + uint32_t aState, + const nsAString& aContentBlockingLogJSON) { MOZ_ASSERT_UNREACHABLE("notification excluded in AddProgressListener(...)"); return NS_OK; } /** * ExecuteCloseHandler - Run the close handler, if any.