diff --git a/browser/actors/ClickHandlerChild.jsm b/browser/actors/ClickHandlerChild.jsm index 869de8d9de57..76846588f844 100644 --- a/browser/actors/ClickHandlerChild.jsm +++ b/browser/actors/ClickHandlerChild.jsm @@ -14,6 +14,8 @@ ChromeUtils.defineModuleGetter(this, "PrivateBrowsingUtils", "resource://gre/modules/PrivateBrowsingUtils.jsm"); ChromeUtils.defineModuleGetter(this, "WebNavigationFrames", "resource://gre/modules/WebNavigationFrames.jsm"); +ChromeUtils.defineModuleGetter(this, "E10SUtils", + "resource://gre/modules/E10SUtils.jsm"); class ClickHandlerChild extends ActorChild { handleEvent(event) { @@ -48,6 +50,12 @@ class ClickHandlerChild extends ActorChild { } } + // Bug 965637, query the CSP from the doc instead of the Principal + let csp = ownerDoc.nodePrincipal.csp; + if (csp) { + csp = E10SUtils.serializeCSP(csp); + } + let frameOuterWindowID = WebNavigationFrames.getFrameId(ownerDoc.defaultView); let json = { button: event.button, shiftKey: event.shiftKey, @@ -55,6 +63,7 @@ class ClickHandlerChild extends ActorChild { altKey: event.altKey, href: null, title: null, frameOuterWindowID, referrerPolicy, triggeringPrincipal: principal, + csp, originAttributes: principal ? principal.originAttributes : {}, isContentWindowPrivate: PrivateBrowsingUtils.isContentWindowPrivate(ownerDoc.defaultView)}; diff --git a/browser/actors/ContextMenuChild.jsm b/browser/actors/ContextMenuChild.jsm index f2ce9673eb8d..9a7c628c0cac 100644 --- a/browser/actors/ContextMenuChild.jsm +++ b/browser/actors/ContextMenuChild.jsm @@ -766,6 +766,9 @@ class ContextMenuChild extends ActorChild { context.target = node; context.principal = context.target.ownerDocument.nodePrincipal; + // Bug 965637, query the CSP from the doc instead of the Principal + context.csp = E10SUtils.serializeCSP(context.target.ownerDocument.nodePrincipal.csp); + context.frameOuterWindowID = WebNavigationFrames.getFrameId(context.target.ownerGlobal); // Check if we are in a synthetic document (stand alone image, video, etc.). diff --git a/browser/base/content/browser.js b/browser/base/content/browser.js index 9885b34ecf43..013f0c116681 100644 --- a/browser/base/content/browser.js +++ b/browser/base/content/browser.js @@ -1056,6 +1056,7 @@ function _loadURI(browser, uri, params = {}) { referrerInfo, postData, userContextId, + csp, } = params || {}; if (!triggeringPrincipal) { @@ -1085,6 +1086,7 @@ function _loadURI(browser, uri, params = {}) { } let loadURIOptions = { triggeringPrincipal, + csp, loadFlags: flags, referrerInfo, postData, @@ -1119,6 +1121,7 @@ function _loadURI(browser, uri, params = {}) { remoteType: requiredRemoteType, postData, newFrameloader, + csp: csp ? gSerializationHelper.serializeToString(csp) : null, }; if (userContextId) { @@ -1688,6 +1691,7 @@ var gBrowserInit = { userContextId: window.arguments[6], triggeringPrincipal: window.arguments[8] || Services.scriptSecurityManager.getSystemPrincipal(), allowInheritPrincipal: window.arguments[9], + csp: window.arguments[10], }); } catch (e) {} } else if (window.arguments.length >= 3) { @@ -1700,6 +1704,7 @@ var gBrowserInit = { // [7]: originPrincipal (nsIPrincipal) // [8]: triggeringPrincipal (nsIPrincipal) // [9]: allowInheritPrincipal (bool) + // [10]: csp (nsIContentSecurityPolicy) let referrerURI = window.arguments[2]; if (typeof(referrerURI) == "string") { try { @@ -1719,7 +1724,7 @@ var gBrowserInit = { window.arguments[7], !!window.arguments[7], window.arguments[8], // TODO fix allowInheritPrincipal to default to false. // Default to true unless explicitly set to false because of bug 1475201. - window.arguments[9] !== false); + window.arguments[9] !== false, window.arguments[10]); window.focus(); } else { // Note: loadOneOrMoreURIs *must not* be called if window.arguments.length >= 3. @@ -2438,7 +2443,7 @@ function BrowserTryToCloseWindow() { function loadURI(uri, referrer, postData, allowThirdPartyFixup, referrerPolicy, userContextId, originPrincipal, forceAboutBlankViewerInCurrent, - triggeringPrincipal, allowInheritPrincipal = false) { + triggeringPrincipal, allowInheritPrincipal = false, csp = null) { if (!triggeringPrincipal) { throw new Error("Must load with a triggering Principal"); } @@ -2452,6 +2457,7 @@ function loadURI(uri, referrer, postData, allowThirdPartyFixup, referrerPolicy, userContextId, originPrincipal, triggeringPrincipal, + csp, forceAboutBlankViewerInCurrent, allowInheritPrincipal, }); @@ -4663,7 +4669,7 @@ var XULBrowserWindow = { }, // Check whether this URI should load in the current process - shouldLoadURI(aDocShell, aURI, aReferrer, aHasPostData, aTriggeringPrincipal) { + shouldLoadURI(aDocShell, aURI, aReferrer, aHasPostData, aTriggeringPrincipal, aCsp) { if (!gMultiProcessBrowser) return true; @@ -4680,7 +4686,7 @@ var XULBrowserWindow = { // XXX: Do we want to complain if we have post data but are still // redirecting the load? Perhaps a telemetry probe? Theoretically we // shouldn't do this, as it throws out data. See bug 1348018. - E10SUtils.redirectLoad(aDocShell, aURI, aReferrer, aTriggeringPrincipal, false); + E10SUtils.redirectLoad(aDocShell, aURI, aReferrer, aTriggeringPrincipal, false, null, aCsp); return false; } @@ -5396,7 +5402,7 @@ nsBrowserAccess.prototype = { aIsExternal, aForceNotRemote = false, aUserContextId = Ci.nsIScriptSecurityManager.DEFAULT_USER_CONTEXT_ID, aOpenerWindow = null, aOpenerBrowser = null, - aTriggeringPrincipal = null, aNextTabParentId = 0, aName = "") { + aTriggeringPrincipal = null, aNextTabParentId = 0, aName = "", aCsp = null) { let win, needToFocusWin; // try the current window. if we're in a popup, fall back on the most recent browser window @@ -5432,6 +5438,7 @@ nsBrowserAccess.prototype = { openerBrowser: aOpenerBrowser, nextTabParentId: aNextTabParentId, name: aName, + csp: aCsp, }); let browser = win.gBrowser.getBrowserForTab(tab); @@ -5491,6 +5498,8 @@ nsBrowserAccess.prototype = { if (aOpener && aOpener.document) { referrerPolicy = aOpener.document.referrerPolicy; } + // Bug 965637, query the CSP from the doc instead of the Principal + let csp = aTriggeringPrincipal.csp; let isPrivate = aOpener ? PrivateBrowsingUtils.isContentWindowPrivate(aOpener) : PrivateBrowsingUtils.isWindowPrivate(window); @@ -5529,7 +5538,8 @@ nsBrowserAccess.prototype = { let browser = this._openURIInNewTab(aURI, referrer, referrerPolicy, isPrivate, isExternal, forceNotRemote, userContextId, - openerWindow, null, aTriggeringPrincipal); + openerWindow, null, aTriggeringPrincipal, + 0, "", csp); if (browser) newWindow = browser.contentWindow; break; @@ -5541,6 +5551,7 @@ nsBrowserAccess.prototype = { Ci.nsIWebNavigation.LOAD_FLAGS_NONE; gBrowser.loadURI(aURI.spec, { triggeringPrincipal: aTriggeringPrincipal, + csp, flags: loadflags, referrerURI: referrer, referrerPolicy, @@ -5588,7 +5599,7 @@ nsBrowserAccess.prototype = { isExternal, false, userContextId, null, aParams.openerBrowser, aParams.triggeringPrincipal, - aNextTabParentId, aName); + aNextTabParentId, aName, aParams.csp); }, isTabContentWindow(aWindow) { @@ -6140,6 +6151,9 @@ function handleLinkClick(event, href, linkNode) { let frameOuterWindowID = WebNavigationFrames.getFrameId(doc.defaultView); + // Bug 965637, query the CSP from the doc instead of the Principal + let csp = doc.nodePrincipal.csp; + urlSecurityCheck(href, doc.nodePrincipal); let params = { charset: doc.characterSet, @@ -6149,6 +6163,7 @@ function handleLinkClick(event, href, linkNode) { noReferrer: BrowserUtils.linkHasNoReferrer(linkNode), originPrincipal: doc.nodePrincipal, triggeringPrincipal: doc.nodePrincipal, + csp, frameOuterWindowID, }; diff --git a/browser/base/content/nsContextMenu.js b/browser/base/content/nsContextMenu.js index 17dcd8e95e14..6c9a239d230a 100644 --- a/browser/base/content/nsContextMenu.js +++ b/browser/base/content/nsContextMenu.js @@ -10,6 +10,7 @@ var {XPCOMUtils} = ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm"); var {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm"); XPCOMUtils.defineLazyModuleGetters(this, { + E10SUtils: "resource://gre/modules/E10SUtils.jsm", SpellCheckHelper: "resource://gre/modules/InlineSpellChecker.jsm", LoginHelper: "resource://gre/modules/LoginHelper.jsm", LoginManagerContextMenu: "resource://gre/modules/LoginManagerContextMenu.jsm", @@ -231,6 +232,8 @@ nsContextMenu.prototype = { // Everything after this isn't sent directly from ContextMenu this.ownerDoc = this.target.ownerDocument; + this.csp = E10SUtils.deserializeCSP(context.csp); + // Remember the CSS selectors corresponding to clicked node. gContextMenuContentData // can be null if the menu was triggered by tests in which case use an empty array. this.targetSelectors = gContextMenuContentData @@ -777,6 +780,7 @@ nsContextMenu.prototype = { let params = { charset: gContextMenuContentData.charSet, originPrincipal: this.principal, triggeringPrincipal: this.principal, + csp: this.csp, referrerURI: gContextMenuContentData.documentURIObject, referrerPolicy: gContextMenuContentData.referrerPolicy, frameOuterWindowID: gContextMenuContentData.frameOuterWindowID, diff --git a/browser/base/content/tab-content.js b/browser/base/content/tab-content.js index ebc19c5b69e9..925efde25e0f 100644 --- a/browser/base/content/tab-content.js +++ b/browser/base/content/tab-content.js @@ -34,9 +34,9 @@ var WebBrowserChrome = { }, // Check whether this URI should load in the current process - shouldLoadURI(aDocShell, aURI, aReferrer, aHasPostData, aTriggeringPrincipal) { + shouldLoadURI(aDocShell, aURI, aReferrer, aHasPostData, aTriggeringPrincipal, aCsp) { if (!E10SUtils.shouldLoadURI(aDocShell, aURI, aReferrer, aHasPostData)) { - E10SUtils.redirectLoad(aDocShell, aURI, aReferrer, aTriggeringPrincipal, false); + E10SUtils.redirectLoad(aDocShell, aURI, aReferrer, aTriggeringPrincipal, false, null, aCsp); return false; } @@ -48,8 +48,8 @@ var WebBrowserChrome = { }, // Try to reload the currently active or currently loading page in a new process. - reloadInFreshProcess(aDocShell, aURI, aReferrer, aTriggeringPrincipal, aLoadFlags) { - E10SUtils.redirectLoad(aDocShell, aURI, aReferrer, aTriggeringPrincipal, true, aLoadFlags); + reloadInFreshProcess(aDocShell, aURI, aReferrer, aTriggeringPrincipal, aLoadFlags, aCsp) { + E10SUtils.redirectLoad(aDocShell, aURI, aReferrer, aTriggeringPrincipal, true, aLoadFlags, aCsp); return true; }, }; diff --git a/browser/base/content/tabbrowser.js b/browser/base/content/tabbrowser.js index 132fe683f234..0aff03b7ce6b 100644 --- a/browser/base/content/tabbrowser.js +++ b/browser/base/content/tabbrowser.js @@ -1401,6 +1401,7 @@ window._gBrowser = { var aNextTabParentId; var aFocusUrlBar; var aName; + var aCsp; if (arguments.length == 2 && typeof arguments[1] == "object" && !(arguments[1] instanceof Ci.nsIURI)) { @@ -1429,6 +1430,7 @@ window._gBrowser = { aNextTabParentId = params.nextTabParentId; aFocusUrlBar = params.focusUrlBar; aName = params.name; + aCsp = params.csp; } // all callers of loadOneTab need to pass a valid triggeringPrincipal. @@ -1465,6 +1467,7 @@ window._gBrowser = { nextTabParentId: aNextTabParentId, focusUrlBar: aFocusUrlBar, name: aName, + csp: aCsp, }); if (!bgLoad) this.selectedTab = tab; @@ -1481,6 +1484,7 @@ window._gBrowser = { replace, targetTab, triggeringPrincipal, + csp, userContextId, } = {}) { if (!aURIs.length) { @@ -1538,6 +1542,7 @@ window._gBrowser = { flags, postData: postDatas && postDatas[0], triggeringPrincipal, + csp, }); } catch (e) { // Ignore failure in case a URI is wrong, so we can continue @@ -1553,6 +1558,7 @@ window._gBrowser = { userContextId, triggeringPrincipal, bulkOrderedOpen: multiple, + csp, }; if (newIndex > -1) { params.index = newIndex; @@ -1573,6 +1579,7 @@ window._gBrowser = { userContextId, triggeringPrincipal, bulkOrderedOpen: true, + csp, }; if (targetTabIndex > -1) { params.index = ++tabNum; @@ -2311,6 +2318,7 @@ window._gBrowser = { userContextId, recordExecution, replayExecution, + csp, } = {}) { // all callers of addTab that pass a params object need to pass // a valid triggeringPrincipal. @@ -2627,6 +2635,7 @@ window._gBrowser = { referrerPolicy, !noReferrer, referrerURI), charset, postData, + csp, }); } catch (ex) { Cu.reportError(ex); diff --git a/browser/base/content/utilityOverlay.js b/browser/base/content/utilityOverlay.js index 12cac041e018..73edb093d5cf 100644 --- a/browser/base/content/utilityOverlay.js +++ b/browser/base/content/utilityOverlay.js @@ -319,6 +319,7 @@ function openLinkIn(url, where, params) { var aIndicateErrorPageLoad = params.indicateErrorPageLoad; var aPrincipal = params.originPrincipal; var aTriggeringPrincipal = params.triggeringPrincipal; + var aCsp = params.csp; var aForceAboutBlankViewerInCurrent = params.forceAboutBlankViewerInCurrent; var aResolveOnNewTabCreated = params.resolveOnNewTabCreated; @@ -430,6 +431,8 @@ function openLinkIn(url, where, params) { sa.appendElement(userContextIdSupports); sa.appendElement(aPrincipal); sa.appendElement(aTriggeringPrincipal); + sa.appendElement(null); // allowInheritPrincipal + sa.appendElement(aCsp); const sourceWindow = (w || window); let win; @@ -548,6 +551,7 @@ function openLinkIn(url, where, params) { "init"); targetBrowser.loadURI(url, { triggeringPrincipal: aTriggeringPrincipal, + csp: aCsp, referrerInfo: new ReferrerInfo( aReferrerPolicy, !aNoReferrer, aReferrerURI), flags, @@ -582,6 +586,7 @@ function openLinkIn(url, where, params) { originPrincipal: aPrincipal, triggeringPrincipal: aTriggeringPrincipal, allowInheritPrincipal: aAllowInheritPrincipal, + csp: aCsp, focusUrlBar, }); targetBrowser = tabUsedForLoad.linkedBrowser; diff --git a/browser/components/extensions/parent/ext-windows.js b/browser/components/extensions/parent/ext-windows.js index 7812b69d8146..e1b3bb06bf0e 100644 --- a/browser/components/extensions/parent/ext-windows.js +++ b/browser/components/extensions/parent/ext-windows.js @@ -226,6 +226,8 @@ this.windows = class extends ExtensionAPI { args.appendElement(context.principal); // originPrincipal - not important. args.appendElement(principal); // triggeringPrincipal args.appendElement(Cc["@mozilla.org/supports-PRBool;1"].createInstance(Ci.nsISupportsPRBool)); // allowInheritPrincipal + // Bug 965637, query the CSP from the doc instead of the Principal + args.appendElement(principal.csp); // csp let features = ["chrome"]; diff --git a/browser/components/sessionstore/ContentRestore.jsm b/browser/components/sessionstore/ContentRestore.jsm index 8c912872a387..40c8a2aaaa95 100644 --- a/browser/components/sessionstore/ContentRestore.jsm +++ b/browser/components/sessionstore/ContentRestore.jsm @@ -214,6 +214,7 @@ ContentRestoreInternal.prototype = { let postData = loadArguments.postData ? E10SUtils.makeInputStream(loadArguments.postData) : null; let triggeringPrincipal = E10SUtils.deserializePrincipal(loadArguments.triggeringPrincipal, () => Services.scriptSecurityManager.createNullPrincipal({})); + let csp = loadArguments.csp ? E10SUtils.deserializeCSP(loadArguments.csp) : null; if (loadArguments.userContextId) { webNavigation.setOriginAttributesBeforeLoading({ userContextId: loadArguments.userContextId }); @@ -223,6 +224,7 @@ ContentRestoreInternal.prototype = { loadFlags: loadArguments.flags, referrerInfo, postData, + csp, }; webNavigation.loadURI(loadArguments.uri, loadURIOptions); } else if (tabData.userTypedValue && tabData.userTypedClear) { diff --git a/browser/modules/ContentClick.jsm b/browser/modules/ContentClick.jsm index 6d90a4713f72..4430c21341f0 100644 --- a/browser/modules/ContentClick.jsm +++ b/browser/modules/ContentClick.jsm @@ -13,6 +13,8 @@ ChromeUtils.defineModuleGetter(this, "PlacesUIUtils", "resource:///modules/PlacesUIUtils.jsm"); ChromeUtils.defineModuleGetter(this, "PrivateBrowsingUtils", "resource://gre/modules/PrivateBrowsingUtils.jsm"); +ChromeUtils.defineModuleGetter(this, "E10SUtils", + "resource://gre/modules/E10SUtils.jsm"); var ContentClick = { // Listeners are added in BrowserGlue.jsm @@ -76,6 +78,7 @@ var ContentClick = { isContentWindowPrivate: json.isContentWindowPrivate, originPrincipal: json.originPrincipal, triggeringPrincipal: json.triggeringPrincipal, + csp: json.csp ? E10SUtils.deserializeCSP(json.csp) : null, frameOuterWindowID: json.frameOuterWindowID, }; diff --git a/caps/nsIPrincipal.idl b/caps/nsIPrincipal.idl index 60eeed2758b8..609cf4069185 100644 --- a/caps/nsIPrincipal.idl +++ b/caps/nsIPrincipal.idl @@ -151,12 +151,13 @@ interface nsIPrincipal : nsISerializable in boolean allowIfInheritsPrincipal); /** - * A Content Security Policy associated with this principal. - * Use this function to query the associated CSP with this principal. - * Please *only* use this function to *set* a CSP when you know exactly what you are doing. + * A Content Security Policy associated with this principal. Use this function to + * query the associated CSP with this principal, but please *only* use this + * function to *set* a CSP when you know exactly what you are doing. * Most likely you want to call ensureCSP instead of setCSP. */ - [noscript] attribute nsIContentSecurityPolicy csp; + readonly attribute nsIContentSecurityPolicy csp; + [noscript] void setCsp(in nsIContentSecurityPolicy aCsp); /* * Use this function to query a CSP associated with this principal. diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp index 0399ee6822d1..0fa2d6e92a5c 100644 --- a/docshell/base/nsDocShell.cpp +++ b/docshell/base/nsDocShell.cpp @@ -3916,6 +3916,7 @@ nsresult nsDocShell::LoadURI(const nsAString& aURI, loadState->SetHeadersStream(aLoadURIOptions.mHeaders); loadState->SetBaseURI(aLoadURIOptions.mBaseURI); loadState->SetTriggeringPrincipal(aLoadURIOptions.mTriggeringPrincipal); + loadState->SetCsp(aLoadURIOptions.mCsp); loadState->SetForceAllowDataURI(forceAllowDataURI); if (fixupInfo) { @@ -4558,6 +4559,13 @@ nsDocShell::Reload(uint32_t aReloadFlags) { bool loadReplace = false; nsIPrincipal* triggeringPrincipal = doc->NodePrincipal(); + // Currently the NodePrincipal holds the CSP for that document, + // after Bug 965637 we can query the CSP directly from the doc + // instead of doc->NodePrincipal(). + nsCOMPtr csp; + rv = doc->NodePrincipal()->GetCsp(getter_AddRefs(csp)); + NS_ENSURE_SUCCESS(rv, rv); + nsAutoString contentTypeHint; doc->GetContentType(contentTypeHint); @@ -4600,6 +4608,7 @@ nsDocShell::Reload(uint32_t aReloadFlags) { loadState->SetLoadReplace(loadReplace); loadState->SetTriggeringPrincipal(triggeringPrincipal); loadState->SetPrincipalToInherit(triggeringPrincipal); + loadState->SetCsp(csp); loadState->SetLoadFlags(flags); loadState->SetTypeHint(NS_ConvertUTF16toUTF8(contentTypeHint)); loadState->SetLoadType(loadType); @@ -5790,13 +5799,21 @@ nsDocShell::ForceRefreshURI(nsIURI* aURI, nsIPrincipal* aPrincipal, principal = doc->NodePrincipal(); } loadState->SetTriggeringPrincipal(principal); + // Currently the principal (NodePrincipal) holds the CSP for that + // document, after Bug 965637 we can query the CSP directly from + // the doc instead of the principal. + nsCOMPtr csp; + nsresult rv = principal->GetCsp(getter_AddRefs(csp)); + NS_ENSURE_SUCCESS(rv, rv); + loadState->SetCsp(csp); + loadState->SetPrincipalIsExplicit(true); /* Check if this META refresh causes a redirection * to another site. */ bool equalUri = false; - nsresult rv = aURI->Equals(mCurrentURI, &equalUri); + rv = aURI->Equals(mCurrentURI, &equalUri); if (NS_SUCCEEDED(rv) && (!equalUri) && aMetaRefresh && aDelay <= REFRESH_REDIRECT_TIMER) { /* It is a META refresh based redirection within the threshold time @@ -6350,7 +6367,7 @@ nsDocShell::OnStateChange(nsIWebProgress* aProgress, nsIRequest* aRequest, // from the channel and store it in session history. // Pass false for aCloneChildren, since we're creating // a new DOM here. - AddToSessionHistory(uri, wcwgChannel, nullptr, nullptr, false, + AddToSessionHistory(uri, wcwgChannel, nullptr, nullptr, nullptr, false, getter_AddRefs(mLSHE)); SetCurrentURI(uri, aRequest, true, 0); // Save history state of the previous page @@ -6855,6 +6872,13 @@ nsresult nsDocShell::EndPageLoad(nsIWebProgress* aProgress, LoadURIOptions loadURIOptions; loadURIOptions.mTriggeringPrincipal = triggeringPrincipal; + // Currently we query the CSP from the triggeringPrincipal within + // the loadInfo. After Bug 965637, we can query the CSP from the + // loadInfo, which internally queries the CSP from the Client. + nsCOMPtr csp; + nsresult rv = triggeringPrincipal->GetCsp(getter_AddRefs(csp)); + NS_ENSURE_SUCCESS(rv, rv); + loadURIOptions.mCsp = csp; loadURIOptions.mPostData = newPostData; return LoadURI(newSpecW, loadURIOptions); } @@ -8079,7 +8103,7 @@ nsresult nsDocShell::CreateContentViewer(const nsACString& aContentType, if (failedURI) { errorOnLocationChangeNeeded = OnNewURI(failedURI, failedChannel, triggeringPrincipal, nullptr, - mLoadType, false, false, false); + mLoadType, nullptr, false, false, false); } // Be sure to have a correct mLSHE, it may have been cleared by @@ -8737,6 +8761,7 @@ nsresult nsDocShell::PerformRetargeting(nsDocShellLoadState* aLoadState, // LoadReplace will always be false due to asserts above, skip setting // it. loadState->SetTriggeringPrincipal(aLoadState->TriggeringPrincipal()); + loadState->SetCsp(aLoadState->Csp()); loadState->SetInheritPrincipal( aLoadState->HasLoadFlags(INTERNAL_LOAD_FLAGS_INHERIT_PRINCIPAL)); // Explicit principal because we do not want any guesses as to what the @@ -8942,12 +8967,21 @@ nsresult nsDocShell::MaybeHandleSameDocumentNavigation( * recorded in session and global history. */ nsCOMPtr newURITriggeringPrincipal, newURIPrincipalToInherit; + nsCOMPtr newCsp; if (mOSHE) { newURITriggeringPrincipal = mOSHE->GetTriggeringPrincipal(); newURIPrincipalToInherit = mOSHE->GetPrincipalToInherit(); + newCsp = mOSHE->GetCsp(); } else { newURITriggeringPrincipal = aLoadState->TriggeringPrincipal(); newURIPrincipalToInherit = doc->NodePrincipal(); + // This is a same-document navigation hence we query the CSP + // from the current document. Please note that currently the + // NodePrincipal holds the CSP for that document, after + // Bug 965637 we can query the CSP directly from + // the doc instead of the NodePrincipal. + nsresult rv = doc->NodePrincipal()->GetCsp(getter_AddRefs(newCsp)); + NS_ENSURE_SUCCESS(rv, rv); } // Pass true for aCloneSHChildren, since we're not // changing documents here, so all of our subframes are @@ -8958,7 +8992,7 @@ nsresult nsDocShell::MaybeHandleSameDocumentNavigation( // Anyway, aCloneSHChildren param is simply reflecting // doSameDocumentNavigation in this scope. OnNewURI(aLoadState->URI(), nullptr, newURITriggeringPrincipal, - newURIPrincipalToInherit, mLoadType, true, true, true); + newURIPrincipalToInherit, mLoadType, newCsp, true, true, true); nsCOMPtr postData; uint32_t cacheKey = 0; @@ -9327,7 +9361,7 @@ nsresult nsDocShell::InternalLoad(nsDocShellLoadState* aLoadState, } rv = browserChrome3->ShouldLoadURI( this, aLoadState->URI(), referrer, !!aLoadState->PostDataStream(), - aLoadState->TriggeringPrincipal(), &shouldLoad); + aLoadState->TriggeringPrincipal(), aLoadState->Csp(), &shouldLoad); if (NS_SUCCEEDED(rv) && !shouldLoad) { return NS_OK; } @@ -9914,6 +9948,36 @@ nsresult nsDocShell::DoURILoad(nsDocShellLoadState* aLoadState, // holds upgrade-insecure-requests. nsCOMPtr csp; aLoadState->TriggeringPrincipal()->GetCsp(getter_AddRefs(csp)); + +#ifdef DEBUG + { + // After Bug 965637 we move the CSP from the Principal into the Client, + // hence we need an explicit CSP argument passed to docshell. Let's make + // sure the explicit CSP is the same as the CSP on the Principal. + uint32_t principalCSPCount = 0; + if (csp) { + csp->GetPolicyCount(&principalCSPCount); + } + + nsCOMPtr argsCSP = aLoadState->Csp(); + uint32_t argCSPCount = 0; + if (argsCSP) { + argsCSP->GetPolicyCount(&argCSPCount); + } + + MOZ_ASSERT(principalCSPCount == argCSPCount, + "Different PolicyCount for CSP as arg and Principal"); + + nsAutoString principalPolicyStr, argPolicyStr; + for (uint32_t i = 0; i < principalCSPCount; ++i) { + csp->GetPolicyString(i, principalPolicyStr); + argsCSP->GetPolicyString(i, argPolicyStr); + MOZ_ASSERT(principalPolicyStr.Equals(argPolicyStr), + "Different PolicyStr for CSP as arg and Principal"); + } + } +#endif + if (csp) { bool upgradeInsecureRequests = false; csp->GetUpgradeInsecureRequests(&upgradeInsecureRequests); @@ -10544,6 +10608,7 @@ void nsDocShell::SetupReferrerInfoFromChannel(nsIChannel* aChannel) { bool nsDocShell::OnNewURI(nsIURI* aURI, nsIChannel* aChannel, nsIPrincipal* aTriggeringPrincipal, nsIPrincipal* aPrincipalToInherit, uint32_t aLoadType, + nsIContentSecurityPolicy* aCsp, bool aFireOnLocationChange, bool aAddToGlobalHistory, bool aCloneSHChildren) { MOZ_ASSERT(aURI, "uri is null"); @@ -10719,7 +10784,7 @@ bool nsDocShell::OnNewURI(nsIURI* aURI, nsIChannel* aChannel, * rootDocShell */ (void)AddToSessionHistory(aURI, aChannel, aTriggeringPrincipal, - aPrincipalToInherit, aCloneSHChildren, + aPrincipalToInherit, aCsp, aCloneSHChildren, getter_AddRefs(mLSHE)); } } else if (mSessionHistory && mLSHE && mURIResultedInDocument) { @@ -10805,7 +10870,7 @@ bool nsDocShell::OnLoadingSite(nsIChannel* aChannel, bool aFireOnLocationChange, NS_ENSURE_TRUE(uri, false); // Pass false for aCloneSHChildren, since we're loading a new page here. - return OnNewURI(uri, aChannel, nullptr, nullptr, mLoadType, + return OnNewURI(uri, aChannel, nullptr, nullptr, mLoadType, nullptr, aFireOnLocationChange, aAddToGlobalHistory, false); } @@ -11010,11 +11075,17 @@ nsDocShell::AddState(JS::Handle aData, const nsAString& aTitle, bool scrollRestorationIsManual = mOSHE->GetScrollRestorationIsManual(); + // Currently the NodePrincipal holds the CSP for that document, + // after Bug 965637 we can query the CSP directly from + // the doc instead of the NodePrincipal. + nsCOMPtr csp; + document->NodePrincipal()->GetCsp(getter_AddRefs(csp)); + // Since we're not changing which page we have loaded, pass // true for aCloneChildren. rv = AddToSessionHistory(newURI, nullptr, document->NodePrincipal(), // triggeringPrincipal - nullptr, true, getter_AddRefs(newSHEntry)); + nullptr, csp, true, getter_AddRefs(newSHEntry)); NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_TRUE(newSHEntry, NS_ERROR_FAILURE); @@ -11187,6 +11258,7 @@ bool nsDocShell::ShouldAddToSessionHistory(nsIURI* aURI, nsIChannel* aChannel) { nsresult nsDocShell::AddToSessionHistory(nsIURI* aURI, nsIChannel* aChannel, nsIPrincipal* aTriggeringPrincipal, nsIPrincipal* aPrincipalToInherit, + nsIContentSecurityPolicy* aCsp, bool aCloneChildren, nsISHEntry** aNewEntry) { MOZ_ASSERT(aURI, "uri is null"); @@ -11253,6 +11325,7 @@ nsresult nsDocShell::AddToSessionHistory(nsIURI* aURI, nsIChannel* aChannel, uint32_t cacheKey = 0; nsCOMPtr triggeringPrincipal = aTriggeringPrincipal; nsCOMPtr principalToInherit = aPrincipalToInherit; + nsCOMPtr csp = aCsp; bool expired = false; bool discardLayoutState = false; nsCOMPtr cacheChannel; @@ -11292,6 +11365,14 @@ nsresult nsDocShell::AddToSessionHistory(nsIURI* aURI, nsIChannel* aChannel, if (!triggeringPrincipal) { triggeringPrincipal = loadInfo->TriggeringPrincipal(); } + if (!csp && triggeringPrincipal) { + // Currently if no CSP is passed explicitly we query the CSP from + // the triggeringPrincipal from within the loadinfo. After Bug 965637, + // we can query the CSP from the loadInfo directly in case the CSP is + // not passed explicitly. Internally the loadinfo queries the CSP + // from the Client. + triggeringPrincipal->GetCsp(getter_AddRefs(csp)); + } loadInfo->GetResultPrincipalURI(getter_AddRefs(resultPrincipalURI)); @@ -11321,7 +11402,7 @@ nsresult nsDocShell::AddToSessionHistory(nsIURI* aURI, nsIChannel* aChannel, cacheKey, // CacheKey mContentTypeHint, // Content-type triggeringPrincipal, // Channel or provided principal - principalToInherit, mHistoryID, mDynamicallyCreated); + principalToInherit, csp, mHistoryID, mDynamicallyCreated); entry->SetOriginalURI(originalURI); entry->SetResultPrincipalURI(resultPrincipalURI); @@ -11439,6 +11520,7 @@ nsresult nsDocShell::LoadHistoryEntry(nsISHEntry* aEntry, uint32_t aLoadType) { aEntry->GetContentType(contentType); nsCOMPtr triggeringPrincipal = aEntry->GetTriggeringPrincipal(); nsCOMPtr principalToInherit = aEntry->GetPrincipalToInherit(); + nsCOMPtr csp = aEntry->GetCsp(); nsCOMPtr referrerInfo = aEntry->GetReferrerInfo(); // Calling CreateAboutBlankContentViewer can set mOSHE to null, and if @@ -11532,6 +11614,7 @@ nsresult nsDocShell::LoadHistoryEntry(nsISHEntry* aEntry, uint32_t aLoadType) { loadState->SetFirstParty(true); loadState->SetSrcdocData(srcdoc); loadState->SetBaseURI(baseURI); + loadState->SetCsp(csp); rv = InternalLoad(loadState, nullptr, // No nsIDocShell @@ -12346,7 +12429,8 @@ class OnLinkClickEvent : public Runnable { nsIInputStream* aPostDataStream, nsIInputStream* aHeadersDataStream, bool aNoOpenerImplied, bool aIsUserTriggered, bool aIsTrusted, - nsIPrincipal* aTriggeringPrincipal); + nsIPrincipal* aTriggeringPrincipal, + nsIContentSecurityPolicy* aCsp); NS_IMETHOD Run() override { nsAutoPopupStatePusher popupStatePusher(mPopupState); @@ -12362,7 +12446,7 @@ class OnLinkClickEvent : public Runnable { mHandler->OnLinkClickSync(mContent, mURI, mTargetSpec, mFileName, mPostDataStream, mHeadersDataStream, mNoOpenerImplied, nullptr, nullptr, - mIsUserTriggered, mTriggeringPrincipal); + mIsUserTriggered, mTriggeringPrincipal, mCsp); } return NS_OK; } @@ -12380,16 +12464,15 @@ class OnLinkClickEvent : public Runnable { bool mIsUserTriggered; bool mIsTrusted; nsCOMPtr mTriggeringPrincipal; + nsCOMPtr mCsp; }; -OnLinkClickEvent::OnLinkClickEvent(nsDocShell* aHandler, nsIContent* aContent, - nsIURI* aURI, const nsAString& aTargetSpec, - const nsAString& aFileName, - nsIInputStream* aPostDataStream, - nsIInputStream* aHeadersDataStream, - bool aNoOpenerImplied, bool aIsUserTriggered, - bool aIsTrusted, - nsIPrincipal* aTriggeringPrincipal) +OnLinkClickEvent::OnLinkClickEvent( + nsDocShell* aHandler, nsIContent* aContent, nsIURI* aURI, + const nsAString& aTargetSpec, const nsAString& aFileName, + nsIInputStream* aPostDataStream, nsIInputStream* aHeadersDataStream, + bool aNoOpenerImplied, bool aIsUserTriggered, bool aIsTrusted, + nsIPrincipal* aTriggeringPrincipal, nsIContentSecurityPolicy* aCsp) : mozilla::Runnable("OnLinkClickEvent"), mHandler(aHandler), mURI(aURI), @@ -12402,16 +12485,15 @@ OnLinkClickEvent::OnLinkClickEvent(nsDocShell* aHandler, nsIContent* aContent, mNoOpenerImplied(aNoOpenerImplied), mIsUserTriggered(aIsUserTriggered), mIsTrusted(aIsTrusted), - mTriggeringPrincipal(aTriggeringPrincipal) {} + mTriggeringPrincipal(aTriggeringPrincipal), + mCsp(aCsp) {} NS_IMETHODIMP -nsDocShell::OnLinkClick(nsIContent* aContent, nsIURI* aURI, - const nsAString& aTargetSpec, - const nsAString& aFileName, - nsIInputStream* aPostDataStream, - nsIInputStream* aHeadersDataStream, - bool aIsUserTriggered, bool aIsTrusted, - nsIPrincipal* aTriggeringPrincipal) { +nsDocShell::OnLinkClick( + nsIContent* aContent, nsIURI* aURI, const nsAString& aTargetSpec, + const nsAString& aFileName, nsIInputStream* aPostDataStream, + nsIInputStream* aHeadersDataStream, bool aIsUserTriggered, bool aIsTrusted, + nsIPrincipal* aTriggeringPrincipal, nsIContentSecurityPolicy* aCsp) { #ifndef ANDROID MOZ_ASSERT(aTriggeringPrincipal, "Need a valid triggeringPrincipal"); #endif @@ -12452,10 +12534,10 @@ nsDocShell::OnLinkClick(nsIContent* aContent, nsIURI* aURI, target = aTargetSpec; } - nsCOMPtr ev = - new OnLinkClickEvent(this, aContent, aURI, target, aFileName, - aPostDataStream, aHeadersDataStream, noOpenerImplied, - aIsUserTriggered, aIsTrusted, aTriggeringPrincipal); + nsCOMPtr ev = new OnLinkClickEvent( + this, aContent, aURI, target, aFileName, aPostDataStream, + aHeadersDataStream, noOpenerImplied, aIsUserTriggered, aIsTrusted, + aTriggeringPrincipal, aCsp); return DispatchToTabGroup(TaskCategory::UI, ev.forget()); } @@ -12466,14 +12548,12 @@ static bool IsElementAnchorOrArea(nsIContent* aContent) { } NS_IMETHODIMP -nsDocShell::OnLinkClickSync(nsIContent* aContent, nsIURI* aURI, - const nsAString& aTargetSpec, - const nsAString& aFileName, - nsIInputStream* aPostDataStream, - nsIInputStream* aHeadersDataStream, - bool aNoOpenerImplied, nsIDocShell** aDocShell, - nsIRequest** aRequest, bool aIsUserTriggered, - nsIPrincipal* aTriggeringPrincipal) { +nsDocShell::OnLinkClickSync( + nsIContent* aContent, nsIURI* aURI, const nsAString& aTargetSpec, + const nsAString& aFileName, nsIInputStream* aPostDataStream, + nsIInputStream* aHeadersDataStream, bool aNoOpenerImplied, + nsIDocShell** aDocShell, nsIRequest** aRequest, bool aIsUserTriggered, + nsIPrincipal* aTriggeringPrincipal, nsIContentSecurityPolicy* aCsp) { // Initialize the DocShell / Request if (aDocShell) { *aDocShell = nullptr; @@ -12524,6 +12604,14 @@ nsDocShell::OnLinkClickSync(nsIContent* aContent, nsIURI* aURI, nsCOMPtr triggeringPrincipal = aTriggeringPrincipal ? aTriggeringPrincipal : aContent->NodePrincipal(); + nsCOMPtr csp = aCsp; + if (!csp) { + // Currently, if no csp is passed explicitly we fall back to querying the + // CSP from the NodePrincipal(). After Bug 965637 we can fall back to + // querying the CSP from the document (aContent->OwnerDoc()). + aContent->NodePrincipal()->GetCsp(getter_AddRefs(csp)); + } + uint32_t flags = INTERNAL_LOAD_FLAGS_NONE; if (IsElementAnchorOrArea(aContent)) { MOZ_ASSERT(aContent->IsHTMLElement()); @@ -12635,6 +12723,7 @@ nsDocShell::OnLinkClickSync(nsIContent* aContent, nsIURI* aURI, loadState->SetReferrerInfo(referrerInfo); loadState->SetTriggeringPrincipal(triggeringPrincipal); loadState->SetPrincipalToInherit(aContent->NodePrincipal()); + loadState->SetCsp(csp); loadState->SetLoadFlags(flags); loadState->SetTarget(aTargetSpec); loadState->SetTypeHint(NS_ConvertUTF16toUTF8(typeHint)); diff --git a/docshell/base/nsDocShell.h b/docshell/base/nsDocShell.h index 2082c9715914..6060ae8ea634 100644 --- a/docshell/base/nsDocShell.h +++ b/docshell/base/nsDocShell.h @@ -217,14 +217,16 @@ class nsDocShell final : public nsDocLoader, nsIInputStream* aPostDataStream, nsIInputStream* aHeadersDataStream, bool aIsUserTriggered, bool aIsTrusted, - nsIPrincipal* aTriggeringPrincipal) override; + nsIPrincipal* aTriggeringPrincipal, + nsIContentSecurityPolicy* aCsp) override; NS_IMETHOD OnLinkClickSync( nsIContent* aContent, nsIURI* aURI, const nsAString& aTargetSpec, const nsAString& aFileName, nsIInputStream* aPostDataStream = 0, nsIInputStream* aHeadersDataStream = 0, bool aNoOpenerImplied = false, nsIDocShell** aDocShell = 0, nsIRequest** aRequest = 0, bool aIsUserTriggered = false, - nsIPrincipal* aTriggeringPrincipal = nullptr) override; + nsIPrincipal* aTriggeringPrincipal = nullptr, + nsIContentSecurityPolicy* aCsp = nullptr) override; NS_IMETHOD OnOverLink(nsIContent* aContent, nsIURI* aURI, const nsAString& aTargetSpec) override; NS_IMETHOD OnLeaveLink() override; @@ -502,10 +504,15 @@ class nsDocShell final : public nsDocLoader, // children will be cloned onto the new entry. This should be // used when we aren't actually changing the document while adding // the new session history entry. - + // aCsp is the CSP to be used for the load. That is *not* the CSP + // that will be applied to subresource loads within that document + // but the CSP for the document load itself. E.g. if that CSP + // includes upgrade-insecure-requests, then the new top-level load + // will be upgraded to HTTPS. nsresult AddToSessionHistory(nsIURI* aURI, nsIChannel* aChannel, nsIPrincipal* aTriggeringPrincipal, nsIPrincipal* aPrincipalToInherit, + nsIContentSecurityPolicy* aCsp, bool aCloneChildren, nsISHEntry** aNewEntry); nsresult AddChildSHEntryToParent(nsISHEntry* aNewEntry, int32_t aChildOffset, @@ -570,11 +577,16 @@ class nsDocShell final : public nsDocLoader, // present, the owner should be gotten from it. // If OnNewURI calls AddToSessionHistory, it will pass its // aCloneSHChildren argument as aCloneChildren. + // aCsp is the CSP to be used for the load. That is *not* the CSP + // that will be applied to subresource loads within that document + // but the CSP for the document load itself. E.g. if that CSP + // includes upgrade-insecure-requests, then the new top-level load + // will be upgraded to HTTPS. bool OnNewURI(nsIURI* aURI, nsIChannel* aChannel, nsIPrincipal* aTriggeringPrincipal, nsIPrincipal* aPrincipalToInherit, uint32_t aLoadType, - bool aFireOnLocationChange, bool aAddToGlobalHistory, - bool aCloneSHChildren); + nsIContentSecurityPolicy* aCsp, bool aFireOnLocationChange, + bool aAddToGlobalHistory, bool aCloneSHChildren); // Helper method that is called when a new document (including any // sub-documents - ie. frames) has been completely loaded. diff --git a/docshell/base/nsDocShellLoadState.cpp b/docshell/base/nsDocShellLoadState.cpp index e3ec88aff8e6..1b4213712ac5 100644 --- a/docshell/base/nsDocShellLoadState.cpp +++ b/docshell/base/nsDocShellLoadState.cpp @@ -62,6 +62,7 @@ nsDocShellLoadState::nsDocShellLoadState(DocShellLoadStateInit& aLoadState) { mBaseURI = aLoadState.BaseURI(); mTriggeringPrincipal = aLoadState.TriggeringPrincipal(); mPrincipalToInherit = aLoadState.PrincipalToInherit(); + mCsp = aLoadState.Csp(); } nsDocShellLoadState::~nsDocShellLoadState() {} @@ -167,6 +168,12 @@ void nsDocShellLoadState::SetPrincipalToInherit( mPrincipalToInherit = aPrincipalToInherit; } +void nsDocShellLoadState::SetCsp(nsIContentSecurityPolicy* aCsp) { + mCsp = aCsp; +} + +nsIContentSecurityPolicy* nsDocShellLoadState::Csp() const { return mCsp; } + bool nsDocShellLoadState::InheritPrincipal() const { return mInheritPrincipal; } void nsDocShellLoadState::SetInheritPrincipal(bool aInheritPrincipal) { @@ -459,6 +466,7 @@ DocShellLoadStateInit nsDocShellLoadState::Serialize() { loadState.BaseURI() = mBaseURI; loadState.TriggeringPrincipal() = mTriggeringPrincipal; loadState.PrincipalToInherit() = mPrincipalToInherit; + loadState.Csp() = mCsp; loadState.Referrer() = mReferrerInfo->GetOriginalReferrer(); loadState.SendReferrer() = mReferrerInfo->GetSendReferrer(); loadState.ReferrerPolicy() = mReferrerInfo->GetReferrerPolicy(); diff --git a/docshell/base/nsDocShellLoadState.h b/docshell/base/nsDocShellLoadState.h index 2f57c3e10315..ac43145e55bf 100644 --- a/docshell/base/nsDocShellLoadState.h +++ b/docshell/base/nsDocShellLoadState.h @@ -13,6 +13,7 @@ #include "nsDocShellLoadTypes.h" #include "mozilla/net/ReferrerPolicy.h" +class nsIContentSecurityPolicy; class nsIInputStream; class nsISHEntry; class nsIURI; @@ -78,6 +79,10 @@ class nsDocShellLoadState final { void SetTriggeringPrincipal(nsIPrincipal* aTriggeringPrincipal); + nsIContentSecurityPolicy* Csp() const; + + void SetCsp(nsIContentSecurityPolicy* aCsp); + bool InheritPrincipal() const; void SetInheritPrincipal(bool aInheritPrincipal); @@ -226,6 +231,13 @@ class nsDocShellLoadState final { // SystemPrincipal as the triggeringPrincipal. nsCOMPtr mTriggeringPrincipal; + // The CSP of the load, that is, the CSP of the entity responsible for causing + // the load to occur. Most likely this is the CSP of the document that started + // the load. In case the entity starting the load did not use a CSP, then mCsp + // can be null. Please note that this is also the CSP that will be applied to + // the load in case the load encounters a server side redirect. + nsCOMPtr mCsp; + // If a refresh is caused by http-equiv="refresh" we want to set // aResultPrincipalURI, but we do not want to overwrite the channel's // ResultPrincipalURI, if it has already been set on the channel by a protocol diff --git a/docshell/base/nsDocShellTreeOwner.cpp b/docshell/base/nsDocShellTreeOwner.cpp index ee1b0a13e94c..c0500ea1bf35 100644 --- a/docshell/base/nsDocShellTreeOwner.cpp +++ b/docshell/base/nsDocShellTreeOwner.cpp @@ -906,6 +906,9 @@ nsDocShellTreeOwner::HandleEvent(Event* aEvent) { #endif LoadURIOptions loadURIOptions; loadURIOptions.mTriggeringPrincipal = triggeringPrincipal; + nsCOMPtr csp; + handler->GetCSP(dragEvent, getter_AddRefs(csp)); + loadURIOptions.mCsp = csp; webnav->LoadURI(url, loadURIOptions); } } diff --git a/docshell/base/nsILinkHandler.h b/docshell/base/nsILinkHandler.h index 8c1c90cf8b71..95dfb4bcfe20 100644 --- a/docshell/base/nsILinkHandler.h +++ b/docshell/base/nsILinkHandler.h @@ -10,6 +10,7 @@ #include "mozilla/EventForwards.h" class nsIContent; +class nsIContentSecurityPolicy; class nsIDocShell; class nsIInputStream; class nsIRequest; @@ -42,6 +43,11 @@ class nsILinkHandler : public nsISupports { * @param aIsTrusted false if the triggerer is an untrusted DOM event. * @param aTriggeringPrincipal, if not passed explicitly we fall back to * the document's principal. + * @param aCsp, the CSP to be used for the load, that is the CSP of the + * entity responsible for causing the load to occur. Most likely + * this is the CSP of the document that started the load. In case + * aCsp was not passed explicitly we fall back to using + * aContent's document's CSP if that document holds any. */ NS_IMETHOD OnLinkClick(nsIContent* aContent, nsIURI* aURI, const nsAString& aTargetSpec, @@ -49,7 +55,8 @@ class nsILinkHandler : public nsISupports { nsIInputStream* aPostDataStream, nsIInputStream* aHeadersDataStream, bool aIsUserTriggered, bool aIsTrusted, - nsIPrincipal* aTriggeringPrincipal) = 0; + nsIPrincipal* aTriggeringPrincipal, + nsIContentSecurityPolicy* aCsp) = 0; /** * Process a click on a link. @@ -70,6 +77,11 @@ class nsILinkHandler : public nsISupports { * @param aRequest the request that was opened * @param aTriggeringPrincipal, if not passed explicitly we fall back to * the document's principal. + * @param aCsp, the CSP to be used for the load, that is the CSP of the + * entity responsible for causing the load to occur. Most likely + * this is the CSP of the document that started the load. In case + * aCsp was not passed explicitly we fall back to using + * aContent's document's CSP if that document holds any. */ NS_IMETHOD OnLinkClickSync( nsIContent* aContent, nsIURI* aURI, const nsAString& aTargetSpec, @@ -77,7 +89,8 @@ class nsILinkHandler : public nsISupports { nsIInputStream* aHeadersDataStream = 0, bool aNoOpenerImplied = false, nsIDocShell** aDocShell = 0, nsIRequest** aRequest = 0, bool aIsUserTriggered = false, - nsIPrincipal* aTriggeringPrincipal = nullptr) = 0; + nsIPrincipal* aTriggeringPrincipal = nullptr, + nsIContentSecurityPolicy* aCsp = nullptr) = 0; /** * Process a mouse-over a link. diff --git a/docshell/shistory/nsISHEntry.idl b/docshell/shistory/nsISHEntry.idl index 66a637280025..2738a3fba0c4 100644 --- a/docshell/shistory/nsISHEntry.idl +++ b/docshell/shistory/nsISHEntry.idl @@ -11,6 +11,7 @@ #include "nsISupports.idl" +interface nsIContentSecurityPolicy; interface nsIMutableArray; interface nsILayoutHistoryState; interface nsIContentViewer; @@ -148,6 +149,13 @@ interface nsISHEntry : nsISupports */ [infallible] attribute nsIPrincipal principalToInherit; + /** + * Get the csp, if any, that was used for this document load. That + * is not the CSP that was applied to subresource loads within the + * document, but the CSP that was applied to this document load. + */ + [infallible] attribute nsIContentSecurityPolicy csp; + /** * Get/set data associated with this history state via a pushState() call, * serialized using structured clone. @@ -277,6 +285,7 @@ interface nsISHEntry : nsISupports in unsigned long cacheKey, in ACString contentType, in nsIPrincipal triggeringPrincipal, in nsIPrincipal principalToInherit, + in nsIContentSecurityPolicy aCsp, in nsIDRef docshellID, in boolean dynamicCreation); diff --git a/docshell/shistory/nsSHEntry.cpp b/docshell/shistory/nsSHEntry.cpp index 9cfbdb82c599..24e25e2a3dcc 100644 --- a/docshell/shistory/nsSHEntry.cpp +++ b/docshell/shistory/nsSHEntry.cpp @@ -8,6 +8,7 @@ #include +#include "nsIContentSecurityPolicy.h" #include "nsDocShellEditorData.h" #include "nsDocShellLoadTypes.h" #include "nsIContentViewer.h" @@ -384,7 +385,8 @@ nsSHEntry::Create(nsIURI* aURI, const nsAString& aTitle, nsILayoutHistoryState* aLayoutHistoryState, uint32_t aCacheKey, const nsACString& aContentType, nsIPrincipal* aTriggeringPrincipal, - nsIPrincipal* aPrincipalToInherit, const nsID& aDocShellID, + nsIPrincipal* aPrincipalToInherit, + nsIContentSecurityPolicy* aCsp, const nsID& aDocShellID, bool aDynamicCreation) { MOZ_ASSERT( aTriggeringPrincipal, @@ -401,6 +403,7 @@ nsSHEntry::Create(nsIURI* aURI, const nsAString& aTitle, mShared->mContentType = aContentType; mShared->mTriggeringPrincipal = aTriggeringPrincipal; mShared->mPrincipalToInherit = aPrincipalToInherit; + mShared->mCsp = aCsp; mShared->mDocShellID = aDocShellID; mShared->mDynamicallyCreated = aDynamicCreation; @@ -495,6 +498,18 @@ nsSHEntry::SetPrincipalToInherit(nsIPrincipal* aPrincipalToInherit) { return NS_OK; } +NS_IMETHODIMP +nsSHEntry::GetCsp(nsIContentSecurityPolicy** aCsp) { + NS_IF_ADDREF(*aCsp = mShared->mCsp); + return NS_OK; +} + +NS_IMETHODIMP +nsSHEntry::SetCsp(nsIContentSecurityPolicy* aCsp) { + mShared->mCsp = aCsp; + return NS_OK; +} + NS_IMETHODIMP nsSHEntry::GetBFCacheEntry(nsIBFCacheEntry** aEntry) { NS_IF_ADDREF(*aEntry = mShared); diff --git a/docshell/shistory/nsSHEntryShared.cpp b/docshell/shistory/nsSHEntryShared.cpp index 7f9af14e3d49..e7b2a15e68ef 100644 --- a/docshell/shistory/nsSHEntryShared.cpp +++ b/docshell/shistory/nsSHEntryShared.cpp @@ -70,6 +70,7 @@ already_AddRefed nsSHEntryShared::Duplicate( newEntry->mChildShells.AppendObjects(aEntry->mChildShells); newEntry->mTriggeringPrincipal = aEntry->mTriggeringPrincipal; newEntry->mPrincipalToInherit = aEntry->mPrincipalToInherit; + newEntry->mCsp = aEntry->mCsp; newEntry->mContentType.Assign(aEntry->mContentType); newEntry->mIsFrameNavigation = aEntry->mIsFrameNavigation; newEntry->mSaveLayoutState = aEntry->mSaveLayoutState; diff --git a/docshell/shistory/nsSHEntryShared.h b/docshell/shistory/nsSHEntryShared.h index 933d7675bb57..b23c1673dcce 100644 --- a/docshell/shistory/nsSHEntryShared.h +++ b/docshell/shistory/nsSHEntryShared.h @@ -80,6 +80,7 @@ class nsSHEntryShared final : public nsIBFCacheEntry, nsCOMArray mChildShells; nsCOMPtr mTriggeringPrincipal; nsCOMPtr mPrincipalToInherit; + nsCOMPtr mCsp; nsCString mContentType; uint32_t mCacheKey; diff --git a/docshell/shistory/nsSHistory.cpp b/docshell/shistory/nsSHistory.cpp index 2ebe5eab1e3d..70524b8d3b88 100644 --- a/docshell/shistory/nsSHistory.cpp +++ b/docshell/shistory/nsSHistory.cpp @@ -1496,6 +1496,8 @@ nsresult nsSHistory::InitiateLoad(nsISHEntry* aFrameEntry, aFrameEntry->GetTriggeringPrincipal(); loadState->SetTriggeringPrincipal(triggeringPrincipal); loadState->SetFirstParty(false); + nsCOMPtr csp = aFrameEntry->GetCsp(); + loadState->SetCsp(csp); // Time to initiate a document load return aFrameDS->LoadURI(loadState); diff --git a/dom/base/ContentAreaDropListener.jsm b/dom/base/ContentAreaDropListener.jsm index b31071dcbc6d..7cbb7f659475 100644 --- a/dom/base/ContentAreaDropListener.jsm +++ b/dom/base/ContentAreaDropListener.jsm @@ -200,6 +200,27 @@ ContentAreaDropListener.prototype = }, + getCSP: function(aEvent) + { + let sourceNode = aEvent.dataTransfer.mozSourceNode; + if (sourceNode && + (sourceNode.localName !== "browser" || + sourceNode.namespaceURI !== "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul")) { + // Use sourceNode's principal only if the sourceNode is not browser. + // + // If sourceNode is browser, the actual triggering principal may be + // differ than sourceNode's principal, since sourceNode's principal is + // top level document's one and the drag may be triggered from a frame + // with different principal. + if (sourceNode.nodePrincipal) { + // Currently we query the CSP from the nodePrincipal. After Bug 965637 we can + // query the CSP directly from the sourceNode. + return sourceNode.nodePrincipal.csp; + } + } + return null; + }, + canDropLink: function(aEvent, aAllowSameDocument) { if (this._eventTargetIsDisabled(aEvent)) diff --git a/dom/base/Location.cpp b/dom/base/Location.cpp index 9b7a84d54f5c..eec661ec7526 100644 --- a/dom/base/Location.cpp +++ b/dom/base/Location.cpp @@ -151,6 +151,15 @@ already_AddRefed Location::CheckURL( loadState->SetTriggeringPrincipal(triggeringPrincipal); + // Currently we query the CSP from the triggeringPrincipal, which is the + // doc->NodePrincipal() in case there is a doc. In that case we can query + // the CSP directly from the doc after Bug 965637. In case there is no doc, + // then we also do not need to query the CSP, because only documents can have + // a CSP attached. + nsCOMPtr csp; + triggeringPrincipal->GetCsp(getter_AddRefs(csp)); + loadState->SetCsp(csp); + if (sourceURI) { nsCOMPtr referrerInfo = new ReferrerInfo(sourceURI, referrerPolicy); diff --git a/dom/base/nsContentUtils.cpp b/dom/base/nsContentUtils.cpp index b8b34cc91f91..ff8c121c893a 100644 --- a/dom/base/nsContentUtils.cpp +++ b/dom/base/nsContentUtils.cpp @@ -5179,10 +5179,17 @@ void nsContentUtils::TriggerLink(nsIContent* aContent, fileName.SetIsVoid(true); // No actionable download attribute was found. } + // Currently we query the CSP from the triggeringPrincipal, which is + // aContent->NodePrincipal(). After Bug 965637 we can query the CSP + // directly from the doc instead (aContent->OwnerDoc()). + nsCOMPtr triggeringPrincipal = aContent->NodePrincipal(); + nsCOMPtr csp; + triggeringPrincipal->GetCsp(getter_AddRefs(csp)); + handler->OnLinkClick( aContent, aLinkURI, fileName.IsVoid() ? aTargetSpec : EmptyString(), fileName, nullptr, nullptr, EventStateManager::IsHandlingUserInput(), - aIsTrusted, aContent->NodePrincipal()); + aIsTrusted, triggeringPrincipal, csp); } } @@ -9812,6 +9819,15 @@ nsContentUtils::LookupCustomElementDefinition(Document* aDoc, nsAtom* aNameAtom, nsCOMPtr loadInfo = aChannel->LoadInfo(); nsCOMPtr triggeringPrincipal = loadInfo->TriggeringPrincipal(); + // Currently we query the CSP from the triggeringPrincipal within the + // loadInfo. After Bug 965637, we can query the CSP from the loadInfo, which + // internally queries the CSP from the Client. + nsCOMPtr csp; + if (triggeringPrincipal) { + rv = triggeringPrincipal->GetCsp(getter_AddRefs(csp)); + NS_ENSURE_SUCCESS(rv, false); + } + // Get the channel's load flags, and use them to generate nsIWebNavigation // load flags. We want to make sure to propagate the refresh and cache busting // flags. @@ -9829,7 +9845,7 @@ nsContentUtils::LookupCustomElementDefinition(Document* aDoc, nsAtom* aNameAtom, // Actually perform the cross process load bool reloadSucceeded = false; rv = wbc3->ReloadInFreshProcess(docShell, uri, referrer, triggeringPrincipal, - webnavLoadFlags, &reloadSucceeded); + webnavLoadFlags, csp, &reloadSucceeded); NS_ENSURE_SUCCESS(rv, false); return reloadSucceeded; diff --git a/dom/base/nsFrameLoader.cpp b/dom/base/nsFrameLoader.cpp index 5fdb746953e6..74b13ab2fe91 100644 --- a/dom/base/nsFrameLoader.cpp +++ b/dom/base/nsFrameLoader.cpp @@ -396,6 +396,13 @@ nsresult nsFrameLoader::ReallyStartLoadingInternal() { loadState->SetTriggeringPrincipal(mOwnerContent->NodePrincipal()); } + // Currently we query the CSP from the principal, but after + // Bug 1529877 we should query the CSP from within GetURL and + // store it as a member, similar to mTriggeringPrincipal. + nsCOMPtr csp; + loadState->TriggeringPrincipal()->GetCsp(getter_AddRefs(csp)); + loadState->SetCsp(csp); + nsCOMPtr referrer; nsAutoString srcdoc; diff --git a/dom/base/nsIDroppedLinkHandler.idl b/dom/base/nsIDroppedLinkHandler.idl index b58ee1c21d75..3dbfcbb296fb 100644 --- a/dom/base/nsIDroppedLinkHandler.idl +++ b/dom/base/nsIDroppedLinkHandler.idl @@ -4,6 +4,7 @@ #include "nsISupports.idl" #include "nsIPrincipal.idl" +#include "nsIContentSecurityPolicy.idl" webidl DragEvent; webidl DataTransfer; @@ -105,4 +106,9 @@ interface nsIDroppedLinkHandler : nsISupports * event and returns it. */ nsIPrincipal getTriggeringPrincipal(in DragEvent aEvent); + + /** + * Given a drop event aEvent, determines the CSP for the event and returns it. + */ + nsIContentSecurityPolicy getCSP(in DragEvent aEvent); }; diff --git a/dom/base/nsOpenURIInFrameParams.cpp b/dom/base/nsOpenURIInFrameParams.cpp index 7164bfd40f36..b809127faf48 100644 --- a/dom/base/nsOpenURIInFrameParams.cpp +++ b/dom/base/nsOpenURIInFrameParams.cpp @@ -73,6 +73,19 @@ nsOpenURIInFrameParams::SetTriggeringPrincipal( return NS_OK; } +NS_IMETHODIMP +nsOpenURIInFrameParams::GetCsp(nsIContentSecurityPolicy** aCsp) { + NS_IF_ADDREF(*aCsp = mCsp); + return NS_OK; +} + +NS_IMETHODIMP +nsOpenURIInFrameParams::SetCsp(nsIContentSecurityPolicy* aCsp) { + NS_ENSURE_TRUE(aCsp, NS_ERROR_INVALID_ARG); + mCsp = aCsp; + return NS_OK; +} + nsresult nsOpenURIInFrameParams::GetOpenerBrowser(Element** aOpenerBrowser) { RefPtr owner = mOpenerBrowser; owner.forget(aOpenerBrowser); diff --git a/dom/base/nsOpenURIInFrameParams.h b/dom/base/nsOpenURIInFrameParams.h index ff7c83e196a6..ca762e0008be 100644 --- a/dom/base/nsOpenURIInFrameParams.h +++ b/dom/base/nsOpenURIInFrameParams.h @@ -31,4 +31,5 @@ class nsOpenURIInFrameParams final : public nsIOpenURIInFrameParams { nsString mReferrer; uint32_t mReferrerPolicy; nsCOMPtr mTriggeringPrincipal; + nsCOMPtr mCsp; }; diff --git a/dom/bindings/Bindings.conf b/dom/bindings/Bindings.conf index 934616356f46..dbf5d667fc1d 100644 --- a/dom/bindings/Bindings.conf +++ b/dom/bindings/Bindings.conf @@ -1848,6 +1848,8 @@ def addExternalIface(iface, nativeType=None, headerFile=None, addExternalIface('Cookie', nativeType='nsICookie2', headerFile='nsICookie2.h', notflattened=True) +addExternalIface('ContentSecurityPolicy', nativeType='nsIContentSecurityPolicy', + notflattened=True) addExternalIface('HitRegionOptions', nativeType='nsISupports') addExternalIface('imgINotificationObserver', nativeType='imgINotificationObserver') addExternalIface('imgIRequest', nativeType='imgIRequest', notflattened=True) diff --git a/dom/clients/manager/ClientNavigateOpChild.cpp b/dom/clients/manager/ClientNavigateOpChild.cpp index 5f7a9b7544d8..1336ac78a414 100644 --- a/dom/clients/manager/ClientNavigateOpChild.cpp +++ b/dom/clients/manager/ClientNavigateOpChild.cpp @@ -230,6 +230,16 @@ RefPtr ClientNavigateOpChild::DoNavigate( nsCOMPtr referrerInfo = new ReferrerInfo(doc->GetDocumentURI(), doc->GetReferrerPolicy()); loadState->SetTriggeringPrincipal(principal); + + // Currently we query the CSP from the principal, which is the + // doc->NodePrincipal(). After Bug 965637 we can query the CSP + // from the doc directly. + if (principal) { + nsCOMPtr csp; + principal->GetCsp(getter_AddRefs(csp)); + loadState->SetCsp(csp); + } + loadState->SetReferrerInfo(referrerInfo); loadState->SetLoadType(LOAD_STOP_CONTENT); loadState->SetSourceDocShell(docShell); diff --git a/dom/interfaces/base/nsIBrowserDOMWindow.idl b/dom/interfaces/base/nsIBrowserDOMWindow.idl index 3b135e25b635..1de9b56bc0ff 100644 --- a/dom/interfaces/base/nsIBrowserDOMWindow.idl +++ b/dom/interfaces/base/nsIBrowserDOMWindow.idl @@ -9,6 +9,7 @@ interface mozIDOMWindowProxy; interface nsIDOMWindow; interface nsIURI; interface nsIPrincipal; +interface nsIContentSecurityPolicy; webidl Element; [scriptable, uuid(e774db14-79ac-4156-a7a3-aa3fd0a22c10)] @@ -18,6 +19,7 @@ interface nsIOpenURIInFrameParams : nsISupports attribute unsigned long referrerPolicy; readonly attribute boolean isPrivate; attribute nsIPrincipal triggeringPrincipal; + attribute nsIContentSecurityPolicy csp; // The browser or frame element in the parent process which holds the // opener window in the content process. May be null. diff --git a/dom/ipc/CSPMessageUtils.cpp b/dom/ipc/CSPMessageUtils.cpp new file mode 100644 index 000000000000..f2d910956fb5 --- /dev/null +++ b/dom/ipc/CSPMessageUtils.cpp @@ -0,0 +1,60 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "mozilla/dom/CSPMessageUtils.h" +#include "nsISerializable.h" +#include "nsSerializationHelper.h" + +namespace IPC { + +void ParamTraits::Write( + Message* aMsg, nsIContentSecurityPolicy* aParam) { + bool isNull = !aParam; + WriteParam(aMsg, isNull); + if (isNull) { + return; + } + + nsCString cspString; + nsresult rv = NS_SerializeToString(aParam, cspString); + if (NS_FAILED(rv)) { + MOZ_CRASH("Unable to serialize csp."); + return; + } + + WriteParam(aMsg, cspString); +} + +bool ParamTraits::Read( + const Message* aMsg, PickleIterator* aIter, + RefPtr* aResult) { + bool isNull; + if (!ReadParam(aMsg, aIter, &isNull)) { + return false; + } + + if (isNull) { + *aResult = nullptr; + return true; + } + + nsCString cspString; + if (!ReadParam(aMsg, aIter, &cspString)) { + return false; + } + + nsCOMPtr iSupports; + nsresult rv = NS_DeserializeObject(cspString, getter_AddRefs(iSupports)); + NS_ENSURE_SUCCESS(rv, false); + + nsCOMPtr csp = do_QueryInterface(iSupports); + NS_ENSURE_TRUE(csp, false); + + *aResult = csp.forget(); + return true; +} + +} // namespace IPC diff --git a/dom/ipc/CSPMessageUtils.h b/dom/ipc/CSPMessageUtils.h new file mode 100644 index 000000000000..fa8375946730 --- /dev/null +++ b/dom/ipc/CSPMessageUtils.h @@ -0,0 +1,25 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_dom_csp_message_utils_h__ +#define mozilla_dom_csp_message_utils_h__ + +#include "ipc/IPCMessageUtils.h" +#include "nsCOMPtr.h" +#include "nsIContentSecurityPolicy.h" + +namespace IPC { + +template <> +struct ParamTraits { + static void Write(Message* aMsg, nsIContentSecurityPolicy* aParam); + static bool Read(const Message* aMsg, PickleIterator* aIter, + RefPtr* aResult); +}; + +} // namespace IPC + +#endif // mozilla_dom_csp_message_utils_h__ diff --git a/dom/ipc/ContentChild.cpp b/dom/ipc/ContentChild.cpp index f2d2eebddd00..d3537a2b0397 100644 --- a/dom/ipc/ContentChild.cpp +++ b/dom/ipc/ContentChild.cpp @@ -755,15 +755,13 @@ ContentChild::ProvideWindow(mozIDOMWindowProxy* aParent, uint32_t aChromeFlags, aWindowIsNew, aReturn); } -static nsresult GetCreateWindowParams(mozIDOMWindowProxy* aParent, - nsDocShellLoadState* aLoadState, - nsACString& aBaseURIString, - float* aFullZoom, - uint32_t* aReferrerPolicy, - nsIPrincipal** aTriggeringPrincipal) { +static nsresult GetCreateWindowParams( + mozIDOMWindowProxy* aParent, nsDocShellLoadState* aLoadState, + nsACString& aBaseURIString, float* aFullZoom, uint32_t* aReferrerPolicy, + nsIPrincipal** aTriggeringPrincipal, nsIContentSecurityPolicy** aCsp) { *aFullZoom = 1.0f; - if (!aTriggeringPrincipal) { - NS_ERROR("aTriggeringPrincipal is null"); + if (!aTriggeringPrincipal || !aCsp) { + NS_ERROR("aTriggeringPrincipal || aCsp is null"); return NS_ERROR_FAILURE; } auto* opener = nsPIDOMWindowOuter::From(aParent); @@ -776,6 +774,15 @@ static nsresult GetCreateWindowParams(mozIDOMWindowProxy* aParent, nsCOMPtr doc = opener->GetDoc(); NS_ADDREF(*aTriggeringPrincipal = doc->NodePrincipal()); + + // Currently we query the CSP from the doc->NodePrincipal(). After + // Bug 965637 we can query the CSP from the doc directly. + nsCOMPtr csp; + doc->NodePrincipal()->GetCsp(getter_AddRefs(csp)); + if (csp) { + csp.forget(aCsp); + } + nsCOMPtr baseURI = doc->GetDocBaseURI(); if (!baseURI) { NS_ERROR("Document didn't return a base URI"); @@ -856,10 +863,11 @@ nsresult ContentChild::ProvideWindowCommon( nsAutoCString baseURIString; float fullZoom; nsCOMPtr triggeringPrincipal; + nsCOMPtr csp; uint32_t referrerPolicy = mozilla::net::RP_Unset; - rv = GetCreateWindowParams(aParent, aLoadState, baseURIString, &fullZoom, - &referrerPolicy, - getter_AddRefs(triggeringPrincipal)); + rv = GetCreateWindowParams( + aParent, aLoadState, baseURIString, &fullZoom, &referrerPolicy, + getter_AddRefs(triggeringPrincipal), getter_AddRefs(csp)); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } @@ -869,7 +877,7 @@ nsresult ContentChild::ProvideWindowCommon( Unused << SendCreateWindowInDifferentProcess( aTabOpener, aChromeFlags, aCalledFromJS, aPositionSpecified, aSizeSpecified, uriToLoad, features, baseURIString, fullZoom, name, - Principal(triggeringPrincipal), referrerPolicy); + Principal(triggeringPrincipal), csp, referrerPolicy); // We return NS_ERROR_ABORT, so that the caller knows that we've abandoned // the window open as far as it is concerned. @@ -1055,10 +1063,11 @@ nsresult ContentChild::ProvideWindowCommon( nsAutoCString baseURIString; float fullZoom; nsCOMPtr triggeringPrincipal; + nsCOMPtr csp; uint32_t referrerPolicy = mozilla::net::RP_Unset; - rv = GetCreateWindowParams(aParent, aLoadState, baseURIString, &fullZoom, - &referrerPolicy, - getter_AddRefs(triggeringPrincipal)); + rv = GetCreateWindowParams( + aParent, aLoadState, baseURIString, &fullZoom, &referrerPolicy, + getter_AddRefs(triggeringPrincipal), getter_AddRefs(csp)); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } @@ -1073,7 +1082,8 @@ nsresult ContentChild::ProvideWindowCommon( SendCreateWindow(aTabOpener, newChild, aChromeFlags, aCalledFromJS, aPositionSpecified, aSizeSpecified, uriToLoad, features, baseURIString, fullZoom, Principal(triggeringPrincipal), - referrerPolicy, std::move(resolve), std::move(reject)); + csp, referrerPolicy, std::move(resolve), + std::move(reject)); } // ======================= diff --git a/dom/ipc/ContentParent.cpp b/dom/ipc/ContentParent.cpp index 78ec77e275ca..d3d240c54b9b 100644 --- a/dom/ipc/ContentParent.cpp +++ b/dom/ipc/ContentParent.cpp @@ -132,6 +132,7 @@ #include "nsIClipboard.h" #include "nsICookie.h" #include "nsContentPermissionHelper.h" +#include "nsIContentSecurityPolicy.h" #include "nsIContentProcess.h" #include "nsICycleCollectorListener.h" #include "nsIDocShellTreeOwner.h" @@ -4606,7 +4607,7 @@ mozilla::ipc::IPCResult ContentParent::CommonCreateWindow( uint64_t aNextTabParentId, const nsString& aName, nsresult& aResult, nsCOMPtr& aNewTabParent, bool* aWindowIsNew, int32_t& aOpenLocation, nsIPrincipal* aTriggeringPrincipal, - uint32_t aReferrerPolicy, bool aLoadURI) + uint32_t aReferrerPolicy, bool aLoadURI, nsIContentSecurityPolicy* aCsp) { // The content process should never be in charge of computing whether or @@ -4690,6 +4691,7 @@ mozilla::ipc::IPCResult ContentParent::CommonCreateWindow( MOZ_ASSERT(aTriggeringPrincipal, "need a valid triggeringPrincipal"); params->SetTriggeringPrincipal(aTriggeringPrincipal); params->SetReferrerPolicy(aReferrerPolicy); + params->SetCsp(aCsp); RefPtr el; @@ -4806,8 +4808,8 @@ mozilla::ipc::IPCResult ContentParent::RecvCreateWindow( const bool& aPositionSpecified, const bool& aSizeSpecified, const OptionalURIParams& aURIToLoad, const nsCString& aFeatures, const nsCString& aBaseURI, const float& aFullZoom, - const IPC::Principal& aTriggeringPrincipal, const uint32_t& aReferrerPolicy, - CreateWindowResolver&& aResolve) { + const IPC::Principal& aTriggeringPrincipal, nsIContentSecurityPolicy* aCsp, + const uint32_t& aReferrerPolicy, CreateWindowResolver&& aResolve) { nsresult rv = NS_OK; CreatedWindowInfo cwi; @@ -4853,7 +4855,7 @@ mozilla::ipc::IPCResult ContentParent::RecvCreateWindow( aPositionSpecified, aSizeSpecified, uriToLoad, aFeatures, aBaseURI, aFullZoom, nextTabParentId, VoidString(), rv, newRemoteTab, &cwi.windowOpened(), openLocation, aTriggeringPrincipal, aReferrerPolicy, - /* aLoadUri = */ false); + /* aLoadUri = */ false, aCsp); if (!ipcResult) { return ipcResult; } @@ -4887,12 +4889,13 @@ mozilla::ipc::IPCResult ContentParent::RecvCreateWindowInDifferentProcess( const bool& aSizeSpecified, const OptionalURIParams& aURIToLoad, const nsCString& aFeatures, const nsCString& aBaseURI, const float& aFullZoom, const nsString& aName, - const IPC::Principal& aTriggeringPrincipal, + const IPC::Principal& aTriggeringPrincipal, nsIContentSecurityPolicy* aCsp, const uint32_t& aReferrerPolicy) { nsCOMPtr newRemoteTab; bool windowIsNew; nsCOMPtr uriToLoad = DeserializeURI(aURIToLoad); int32_t openLocation = nsIBrowserDOMWindow::OPEN_NEWWINDOW; + nsresult rv; mozilla::ipc::IPCResult ipcResult = CommonCreateWindow( aThisTab, /* aSetOpener = */ false, aChromeFlags, aCalledFromJS, @@ -4900,7 +4903,7 @@ mozilla::ipc::IPCResult ContentParent::RecvCreateWindowInDifferentProcess( aFullZoom, /* aNextTabParentId = */ 0, aName, rv, newRemoteTab, &windowIsNew, openLocation, aTriggeringPrincipal, aReferrerPolicy, - /* aLoadUri = */ true); + /* aLoadUri = */ true, aCsp); if (!ipcResult) { return ipcResult; } diff --git a/dom/ipc/ContentParent.h b/dom/ipc/ContentParent.h index 0db5c6963c31..e021dac56d68 100644 --- a/dom/ipc/ContentParent.h +++ b/dom/ipc/ContentParent.h @@ -519,7 +519,8 @@ class ContentParent final : public PContentParent, const OptionalURIParams& aURIToLoad, const nsCString& aFeatures, const nsCString& aBaseURI, const float& aFullZoom, const IPC::Principal& aTriggeringPrincipal, - const uint32_t& aReferrerPolicy, CreateWindowResolver&& aResolve); + nsIContentSecurityPolicy* aCsp, const uint32_t& aReferrerPolicy, + CreateWindowResolver&& aResolve); mozilla::ipc::IPCResult RecvCreateWindowInDifferentProcess( PBrowserParent* aThisTab, const uint32_t& aChromeFlags, @@ -528,7 +529,7 @@ class ContentParent final : public PContentParent, const nsCString& aFeatures, const nsCString& aBaseURI, const float& aFullZoom, const nsString& aName, const IPC::Principal& aTriggeringPrincipal, - const uint32_t& aReferrerPolicy); + nsIContentSecurityPolicy* aCsp, const uint32_t& aReferrerPolicy); static void BroadcastBlobURLRegistration( const nsACString& aURI, BlobImpl* aBlobImpl, nsIPrincipal* aPrincipal, @@ -696,7 +697,7 @@ class ContentParent final : public PContentParent, nsresult& aResult, nsCOMPtr& aNewTabParent, bool* aWindowIsNew, int32_t& aOpenLocation, nsIPrincipal* aTriggeringPrincipal, uint32_t aReferrerPolicy, - bool aLoadUri); + bool aLoadUri, nsIContentSecurityPolicy* aCsp); FORWARD_SHMEM_ALLOCATOR_TO(PContentParent) diff --git a/dom/ipc/DOMTypes.ipdlh b/dom/ipc/DOMTypes.ipdlh index e43a07f2112a..8c79c1f4f991 100644 --- a/dom/ipc/DOMTypes.ipdlh +++ b/dom/ipc/DOMTypes.ipdlh @@ -29,6 +29,7 @@ using mozilla::gfx::SurfaceFormat from "mozilla/gfx/Types.h"; using refcounted class nsIPrincipal from "mozilla/dom/PermissionMessageUtils.h"; using refcounted class mozilla::dom::BrowsingContext from "mozilla/dom/BrowsingContext.h"; using refcounted class nsIURI from "mozilla/ipc/URIUtils.h"; +using refcounted class nsIContentSecurityPolicy from "mozilla/dom/CSPMessageUtils.h"; namespace mozilla { namespace dom { @@ -219,6 +220,13 @@ struct DocShellLoadStateInit nsCString TypeHint; nsString FileName; bool IsFromProcessingFrameAttributes; + // The Content Security Policy of the load, that is, the CSP of the entity + // responsible for causing the load to occur. Most likely this is the CSP + // of the document that started the load. In case the entity starting the + // load did not use a CSP, then Csp can be null. Please note that this is + // also the CSP that will be applied to the load in case the load + // encounters a server side redirect. + nsIContentSecurityPolicy Csp; // Fields missing due to lack of need or serialization // nsCOMPtr mSHEntry; // nsCOMPtr mSourceDocShell; diff --git a/dom/ipc/MemoryReportRequest.cpp b/dom/ipc/MemoryReportRequest.cpp index c931550096c5..99f45760b076 100644 --- a/dom/ipc/MemoryReportRequest.cpp +++ b/dom/ipc/MemoryReportRequest.cpp @@ -4,7 +4,9 @@ * 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 "nsMemoryReporterManager.h" #include "MemoryReportRequest.h" +#include "mozilla/ipc/FileDescriptorUtils.h" namespace mozilla { namespace dom { diff --git a/dom/ipc/PContent.ipdl b/dom/ipc/PContent.ipdl index 9dae42b57c4b..1c1ff9b13b65 100644 --- a/dom/ipc/PContent.ipdl +++ b/dom/ipc/PContent.ipdl @@ -1138,6 +1138,7 @@ parent: nsCString aBaseURI, float aFullZoom, Principal aTriggeringPrincipal, + nsIContentSecurityPolicy aCsp, uint32_t aReferrerPolicy) returns (CreatedWindowInfo window); @@ -1153,6 +1154,7 @@ parent: float aFullZoom, nsString aName, Principal aTriggeringPrincipal, + nsIContentSecurityPolicy aCsp, uint32_t aReferrerPolicy); /** diff --git a/dom/ipc/moz.build b/dom/ipc/moz.build index f848c5485f57..01bb967e60ac 100644 --- a/dom/ipc/moz.build +++ b/dom/ipc/moz.build @@ -38,6 +38,7 @@ EXPORTS.mozilla.dom += [ 'ContentProcess.h', 'ContentProcessManager.h', 'CPOWManagerGetter.h', + 'CSPMessageUtils.h', 'DocShellMessageUtils.h', 'FilePickerParent.h', 'JSWindowActorChild.h', @@ -75,6 +76,7 @@ UNIFIED_SOURCES += [ 'ContentParent.cpp', 'ContentProcess.cpp', 'ContentProcessManager.cpp', + 'CSPMessageUtils.cpp', 'DocShellMessageUtils.cpp', 'FilePickerParent.cpp', 'JSWindowActorChild.cpp', diff --git a/dom/plugins/base/nsPluginInstanceOwner.cpp b/dom/plugins/base/nsPluginInstanceOwner.cpp index b634a8347416..3e2bc722192e 100644 --- a/dom/plugins/base/nsPluginInstanceOwner.cpp +++ b/dom/plugins/base/nsPluginInstanceOwner.cpp @@ -443,10 +443,15 @@ NS_IMETHODIMP nsPluginInstanceOwner::GetURL( NullPrincipal::CreateWithInheritedAttributes(content->NodePrincipal()); } + // Currently we query the CSP from the NodePrincipal. After Bug 965637 + // we can query the CSP from the doc directly (content->OwerDoc()). + nsCOMPtr csp; + content->NodePrincipal()->GetCsp(getter_AddRefs(csp)); + rv = lh->OnLinkClick(content, uri, unitarget, VoidString(), aPostStream, headersDataStream, /* isUserTriggered */ false, - /* isTrusted */ true, triggeringPrincipal); + /* isTrusted */ true, triggeringPrincipal, csp); return rv; } diff --git a/dom/webidl/LoadURIOptions.webidl b/dom/webidl/LoadURIOptions.webidl index b8673c4b7ab5..d80513244411 100644 --- a/dom/webidl/LoadURIOptions.webidl +++ b/dom/webidl/LoadURIOptions.webidl @@ -2,6 +2,7 @@ * 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/. */ +interface ContentSecurityPolicy; interface Principal; interface URI; interface InputStream; @@ -17,6 +18,15 @@ dictionary LoadURIOptions { */ Principal? triggeringPrincipal = null; + /** + * The CSP to be used for the load. That is *not* the CSP that will + * be applied to subresource loads within that document but the CSP + * for the document load itself. E.g. if that CSP includes + * upgrade-insecure-requests, then the new top-level load will + * be upgraded to HTTPS. + */ + ContentSecurityPolicy? csp = null; + /** * Flags modifying load behaviour. This parameter is a bitwise * combination of the load flags defined in nsIWebNavigation.idl. diff --git a/mobile/android/chrome/geckoview/GeckoViewNavigationChild.js b/mobile/android/chrome/geckoview/GeckoViewNavigationChild.js index f212533324f1..d46fc3a7e548 100644 --- a/mobile/android/chrome/geckoview/GeckoViewNavigationChild.js +++ b/mobile/android/chrome/geckoview/GeckoViewNavigationChild.js @@ -77,19 +77,11 @@ class GeckoViewNavigationChild extends GeckoViewChildModule { } // nsIWebBrowserChrome - shouldLoadURI(aDocShell, aURI, aReferrer, aHasPostData, aTriggeringPrincipal) { + shouldLoadURI(aDocShell, aURI, aReferrer, aHasPostData, aTriggeringPrincipal, aCsp) { debug `shouldLoadURI ${aURI.displaySpec}`; - // We currently only support one remoteType, "web", so we only need to bail out - // if we want to load this URI in the parent. - // const remoteType = E10SUtils.getRemoteTypeForURIObject(aURI, true); - // if (!remoteType) { - // E10SUtils.redirectLoad(aDocShell, aURI, aReferrer, aTriggeringPrincipal, false); - // return false; - // } - if (!E10SUtils.shouldLoadURI(aDocShell, aURI, aReferrer, aHasPostData)) { - E10SUtils.redirectLoad(aDocShell, aURI, aReferrer, aTriggeringPrincipal, false); + E10SUtils.redirectLoad(aDocShell, aURI, aReferrer, aTriggeringPrincipal, false, null, aCsp); return false; } @@ -103,9 +95,9 @@ class GeckoViewNavigationChild extends GeckoViewChildModule { } // nsIWebBrowserChrome - reloadInFreshProcess(aDocShell, aURI, aReferrer, aTriggeringPrincipal, aLoadFlags) { + reloadInFreshProcess(aDocShell, aURI, aReferrer, aTriggeringPrincipal, aLoadFlags, aCsp) { debug `reloadInFreshProcess ${aURI.displaySpec}`; - E10SUtils.redirectLoad(aDocShell, aURI, aReferrer, aTriggeringPrincipal, true, aLoadFlags); + E10SUtils.redirectLoad(aDocShell, aURI, aReferrer, aTriggeringPrincipal, true, aLoadFlags, aCsp); return true; } diff --git a/taskcluster/ci/searchfox/kind.yml b/taskcluster/ci/searchfox/kind.yml index ee415e5919a0..02468dd8d294 100644 --- a/taskcluster/ci/searchfox/kind.yml +++ b/taskcluster/ci/searchfox/kind.yml @@ -51,6 +51,7 @@ jobs: - linux64-node - linux64-rust - linux64-cbindgen + - linux64-nasm macosx64-searchfox/debug: description: "MacOS X x64 Debug Cross-compile Searchfox" @@ -86,6 +87,7 @@ jobs: - linux64-node - linux64-rust-macos - linux64-cbindgen + - linux64-nasm win64-searchfox/debug: description: "Win64 Searchfox Debug (clang-cl)" @@ -155,3 +157,4 @@ jobs: - linux64-cbindgen - linux64-sccache - linux64-node + - linux64-nasm diff --git a/toolkit/actors/WebNavigationChild.jsm b/toolkit/actors/WebNavigationChild.jsm index 025cd0218e60..cdec098183f8 100644 --- a/toolkit/actors/WebNavigationChild.jsm +++ b/toolkit/actors/WebNavigationChild.jsm @@ -40,10 +40,8 @@ class WebNavigationChild extends ActorChild { histogram.add("WebNavigation:LoadURI", Services.telemetry.msSystemNow() - message.data.requestTime); - this.loadURI(message.data.uri, message.data.flags, - message.data.referrerInfo, - message.data.postData, message.data.headers, - message.data.baseURI, message.data.triggeringPrincipal); + this.loadURI(message.data); + break; case "WebNavigation:SetOriginAttributes": this.setOriginAttributes(message.data.originAttributes); @@ -83,7 +81,18 @@ class WebNavigationChild extends ActorChild { this._wrapURIChangeCall(() => this.webNavigation.gotoIndex(index)); } - loadURI(uri, flags, referrerInfo, postData, headers, baseURI, triggeringPrincipal) { + loadURI(params) { + let { + uri, + flags, + referrerInfo, + postData, + headers, + baseURI, + triggeringPrincipal, + csp, + } = params || {}; + if (AppConstants.MOZ_CRASHREPORTER && CrashReporter.enabled) { let annotation = uri; try { @@ -109,9 +118,13 @@ class WebNavigationChild extends ActorChild { this._assert(false, "Unable to deserialize passed triggering principal", new Error().lineNumber); return Services.scriptSecurityManager.getSystemPrincipal({}); }); + if (csp) { + csp = E10SUtils.deserializeCSP(csp); + } let loadURIOptions = { triggeringPrincipal, + csp, loadFlags: flags, referrerInfo: E10SUtils.deserializeReferrerInfo(referrerInfo), postData, diff --git a/toolkit/components/browser/nsIWebBrowserChrome3.idl b/toolkit/components/browser/nsIWebBrowserChrome3.idl index b40fd39312b1..36fa9c4290ef 100644 --- a/toolkit/components/browser/nsIWebBrowserChrome3.idl +++ b/toolkit/components/browser/nsIWebBrowserChrome3.idl @@ -9,6 +9,7 @@ interface nsIDocShell; interface nsIInputStream; interface nsIRunnable; interface nsIPrincipal; +interface nsIContentSecurityPolicy; webidl Node; @@ -52,12 +53,16 @@ interface nsIWebBrowserChrome3 : nsIWebBrowserChrome2 * boundaries. * @param aTriggeringPrincipal * The principal that initiated the load of aURI. + * @param aCsp + * The CSP to be used for that load. That is the CSP that e.g. upgrades + * the load to HTTPS in case upgrade-insecure-requests is set. */ - bool shouldLoadURI(in nsIDocShell aDocShell, - in nsIURI aURI, - in nsIURI aReferrer, - in boolean aHasPostData, - in nsIPrincipal aTriggeringPrincipal); + bool shouldLoadURI(in nsIDocShell aDocShell, + in nsIURI aURI, + in nsIURI aReferrer, + in boolean aHasPostData, + in nsIPrincipal aTriggeringPrincipal, + in nsIContentSecurityPolicy aCsp); bool shouldLoadURIInThisProcess(in nsIURI aURI); @@ -67,10 +72,14 @@ interface nsIWebBrowserChrome3 : nsIWebBrowserChrome2 * * @param aDocShell * The docshell performing the load. + * @param aCsp + * The CSP to be used for that load. That is the CSP that e.g. upgrades + * the load to HTTPS in case upgrade-insecure-requests is set. */ bool reloadInFreshProcess(in nsIDocShell aDocShell, in nsIURI aURI, in nsIURI aReferrer, in nsIPrincipal aTriggeringPrincipal, - in uint32_t aLoadFlags); + in uint32_t aLoadFlags, + in nsIContentSecurityPolicy aCsp); }; diff --git a/toolkit/components/remotebrowserutils/RemoteWebNavigation.jsm b/toolkit/components/remotebrowserutils/RemoteWebNavigation.jsm index 674bf540e1f3..bc6b64b0e98d 100644 --- a/toolkit/components/remotebrowserutils/RemoteWebNavigation.jsm +++ b/toolkit/components/remotebrowserutils/RemoteWebNavigation.jsm @@ -98,6 +98,7 @@ RemoteWebNavigation.prototype = { baseURI: aLoadURIOptions.baseURI ? aLoadURIOptions.baseURI.spec : null, triggeringPrincipal: E10SUtils.serializePrincipal( aLoadURIOptions.triggeringPrincipal || Services.scriptSecurityManager.createNullPrincipal({})), + csp: aLoadURIOptions.csp ? E10SUtils.serializeCSP(aLoadURIOptions.csp) : null, requestTime: Services.telemetry.msSystemNow(), }); }, diff --git a/toolkit/components/windowwatcher/nsWindowWatcher.cpp b/toolkit/components/windowwatcher/nsWindowWatcher.cpp index 278f1e01fd99..e4f5dc0e0ff7 100644 --- a/toolkit/components/windowwatcher/nsWindowWatcher.cpp +++ b/toolkit/components/windowwatcher/nsWindowWatcher.cpp @@ -1084,6 +1084,15 @@ nsresult nsWindowWatcher::OpenWindowInternal( } } + // Currently we query the CSP from the subjectPrincipal. After Bug 965637 + // we should query the CSP from the doc, similar to the referrerInfo above. + if (subjectPrincipal && loadState) { + nsCOMPtr csp; + rv = subjectPrincipal->GetCsp(getter_AddRefs(csp)); + NS_ENSURE_SUCCESS(rv, rv); + loadState->SetCsp(csp); + } + if (isNewToplevelWindow) { // Notify observers that the window is open and ready. // The window has not yet started to load a document. diff --git a/toolkit/modules/DateTimePickerPanel.jsm b/toolkit/modules/DateTimePickerPanel.jsm index cf5ee2f86bf7..a23f68cfa1ca 100644 --- a/toolkit/modules/DateTimePickerPanel.jsm +++ b/toolkit/modules/DateTimePickerPanel.jsm @@ -99,7 +99,7 @@ var DateTimePickerPanel = class { initPicker(detail) { // TODO: When bug 1376616 lands, replace this.setGregorian with // mozIntl.Locale for setting calendar to Gregorian - const locale = this.setGregorian(Services.locale.appLocaleAsBCP47); + const locale = this.setGregorian(Services.locale.regionalPrefsLocales[0]); const dir = Services.intl.getLocaleInfo(locale).direction; switch (this.type) { @@ -125,8 +125,7 @@ var DateTimePickerPanel = class { case "date": { const { year, month, day } = detail.value; - const { firstDayOfWeek, weekends } = - this.getCalendarInfo(locale); + const { firstDayOfWeek, weekends } = this.getCalendarInfo(locale); const monthStrings = this.getDisplayNames( locale, [ "dates/gregorian/months/january", diff --git a/toolkit/modules/E10SUtils.jsm b/toolkit/modules/E10SUtils.jsm index b2a836f9fe24..a91b16fe51a8 100644 --- a/toolkit/modules/E10SUtils.jsm +++ b/toolkit/modules/E10SUtils.jsm @@ -106,6 +106,46 @@ var E10SUtils = { return useCrossOriginOpenerPolicy; }, + /** + * Serialize csp data. + * + * @param {nsIContentSecurity} csp. The csp to serialize. + * @return {String} The base64 encoded csp data. + */ + serializeCSP(csp) { + let serializedCSP = null; + + try { + if (csp) { + serializedCSP = serializationHelper.serializeToString(csp); + } + } catch (e) { + debug(`Failed to serialize csp '${csp}' ${e}`); + } + return serializedCSP; + }, + + /** + * Deserialize a base64 encoded csp (serialized with + * Utils::serializeCSP). + * + * @param {String} csp_b64 A base64 encoded serialized csp. + * @return {nsIContentSecurityPolicy} A deserialized csp. + */ + deserializeCSP(csp_b64) { + if (!csp_b64) + return null; + + try { + let csp = serializationHelper.deserializeObject(csp_b64); + csp.QueryInterface(Ci.nsIContentSecurityPolicy); + return csp; + } catch (e) { + debug(`Failed to deserialize csp_b64 '${csp_b64}' ${e}`); + } + return null; + }, + canLoadURIInRemoteType(aURL, aRemoteType = DEFAULT_REMOTE_TYPE, aPreferredRemoteType = undefined) { // We need a strict equality here because the value of `NOT_REMOTE` is @@ -462,7 +502,7 @@ var E10SUtils = { return this.shouldLoadURIInThisProcess(aURI); }, - redirectLoad(aDocShell, aURI, aReferrer, aTriggeringPrincipal, aFreshProcess, aFlags) { + redirectLoad(aDocShell, aURI, aReferrer, aTriggeringPrincipal, aFreshProcess, aFlags, aCsp) { // Retarget the load to the correct process let messageManager = aDocShell.messageManager; let sessionHistory = aDocShell.QueryInterface(Ci.nsIWebNavigation).sessionHistory; @@ -473,6 +513,7 @@ var E10SUtils = { flags: aFlags || Ci.nsIWebNavigation.LOAD_FLAGS_NONE, referrer: aReferrer ? aReferrer.spec : null, triggeringPrincipal: this.serializePrincipal(aTriggeringPrincipal || Services.scriptSecurityManager.createNullPrincipal({})), + csp: aCsp ? this.serializeCSP(aCsp) : null, reloadInFreshProcess: !!aFreshProcess, }, historyIndex: sessionHistory.legacySHistory.requestedIndex, diff --git a/toolkit/modules/sessionstore/SessionHistory.jsm b/toolkit/modules/sessionstore/SessionHistory.jsm index ddda6b669610..dbe241a615eb 100644 --- a/toolkit/modules/sessionstore/SessionHistory.jsm +++ b/toolkit/modules/sessionstore/SessionHistory.jsm @@ -224,6 +224,10 @@ var SessionHistoryInternal = { entry.triggeringPrincipal_base64 = E10SUtils.serializePrincipal(shEntry.triggeringPrincipal); } + if (shEntry.csp) { + entry.csp = E10SUtils.serializeCSP(shEntry.csp); + } + entry.docIdentifier = shEntry.BFCacheEntry.ID; if (shEntry.stateData != null) { @@ -460,6 +464,9 @@ var SessionHistoryInternal = { if (entry.principalToInherit_base64) { shEntry.principalToInherit = E10SUtils.deserializePrincipal(entry.principalToInherit_base64); } + if (entry.csp) { + shEntry.csp = E10SUtils.deserializeCSP(entry.csp); + } if (entry.children) { for (var i = 0; i < entry.children.length; i++) { diff --git a/xpfe/appshell/nsContentTreeOwner.cpp b/xpfe/appshell/nsContentTreeOwner.cpp index d2c8f21715a4..a2b9e6f0d4b1 100644 --- a/xpfe/appshell/nsContentTreeOwner.cpp +++ b/xpfe/appshell/nsContentTreeOwner.cpp @@ -362,7 +362,8 @@ NS_IMETHODIMP nsContentTreeOwner::OnBeforeLinkTraversal( NS_IMETHODIMP nsContentTreeOwner::ShouldLoadURI( nsIDocShell* aDocShell, nsIURI* aURI, nsIURI* aReferrer, bool aHasPostData, - nsIPrincipal* aTriggeringPrincipal, bool* _retval) { + nsIPrincipal* aTriggeringPrincipal, nsIContentSecurityPolicy* aCsp, + bool* _retval) { NS_ENSURE_STATE(mXULWindow); nsCOMPtr xulBrowserWindow; @@ -371,7 +372,7 @@ NS_IMETHODIMP nsContentTreeOwner::ShouldLoadURI( if (xulBrowserWindow) return xulBrowserWindow->ShouldLoadURI(aDocShell, aURI, aReferrer, aHasPostData, aTriggeringPrincipal, - _retval); + aCsp, _retval); *_retval = true; return NS_OK; @@ -386,7 +387,8 @@ NS_IMETHODIMP nsContentTreeOwner::ShouldLoadURIInThisProcess(nsIURI* aURI, NS_IMETHODIMP nsContentTreeOwner::ReloadInFreshProcess( nsIDocShell* aDocShell, nsIURI* aURI, nsIURI* aReferrer, - nsIPrincipal* aTriggeringPrincipal, uint32_t aLoadFlags, bool* aRetVal) { + nsIPrincipal* aTriggeringPrincipal, uint32_t aLoadFlags, + nsIContentSecurityPolicy* aCsp, bool* aRetVal) { NS_WARNING("Cannot reload in fresh process from a nsContentTreeOwner!"); *aRetVal = false; return NS_OK; diff --git a/xpfe/appshell/nsIXULBrowserWindow.idl b/xpfe/appshell/nsIXULBrowserWindow.idl index c9dac4981102..981dedb875e2 100644 --- a/xpfe/appshell/nsIXULBrowserWindow.idl +++ b/xpfe/appshell/nsIXULBrowserWindow.idl @@ -14,6 +14,7 @@ interface nsIDocShell; interface nsITabParent; interface nsIPrincipal; interface mozIDOMWindowProxy; +interface nsIContentSecurityPolicy; webidl Element; webidl Node; @@ -61,12 +62,16 @@ interface nsIXULBrowserWindow : nsISupports * boundaries. * @param aTriggeringPrincipal * The principal that initiated the load of aURI. + * @param aCsp + * The CSP to be used for that load. That is the CSP that e.g. upgrades + * the load to HTTPS in case upgrade-insecure-requests is set */ bool shouldLoadURI(in nsIDocShell aDocShell, in nsIURI aURI, in nsIURI aReferrer, in boolean aHasPostData, - in nsIPrincipal aTriggeringPrincipal); + in nsIPrincipal aTriggeringPrincipal, + in nsIContentSecurityPolicy aCsp); /** * Show/hide a tooltip (when the user mouses over a link, say). */