☠☠ backed out by 9201fb4f420d ☠ ☠ | |
author | Christoph Kerschbaumer <ckerschb@christophkerschbaumer.com> |
Tue, 22 Oct 2019 08:53:47 +0000 | |
changeset 498536 | 8705284b50d4905110df9b1fab7f00d9d77d06e6 |
parent 498535 | 141755ff04e1b75522dcf5209784df636a573984 |
child 498537 | 32edc29b094cb26a46d31116980a5e780de4a02f |
push id | 98505 |
push user | btara@mozilla.com |
push date | Tue, 22 Oct 2019 09:02:39 +0000 |
treeherder | autoland@8705284b50d4 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | jkt, farre, valentin |
bugs | 1584993 |
milestone | 72.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/dom/base/Document.cpp +++ b/dom/base/Document.cpp @@ -3281,31 +3281,16 @@ nsresult Document::InitCSP(nsIChannel* a mSandboxFlags |= cspSandboxFlags; if (needNewNullPrincipal) { principal = NullPrincipal::CreateWithInheritedAttributes(principal); SetPrincipals(principal, principal); } - // ----- Enforce frame-ancestor policy on any applied policies - nsCOMPtr<nsIDocShell> docShell(mDocumentContainer); - if (docShell) { - bool safeAncestry = false; - - // PermitsAncestry sends violation reports when necessary - rv = mCSP->PermitsAncestry(docShell, &safeAncestry); - - if (NS_FAILED(rv) || !safeAncestry) { - MOZ_LOG(gCspPRLog, LogLevel::Debug, - ("CSP doesn't like frame's ancestry, not loading.")); - // stop! ERROR page! - aChannel->Cancel(NS_ERROR_CSP_FRAME_ANCESTOR_VIOLATION); - } - } ApplySettingsFromCSP(false); return NS_OK; } nsresult Document::InitFeaturePolicy(nsIChannel* aChannel) { MOZ_ASSERT(mFeaturePolicy, "we should only call init once"); mFeaturePolicy->ResetDeclaredPolicy();
--- a/dom/interfaces/security/nsIContentSecurityPolicy.idl +++ b/dom/interfaces/security/nsIContentSecurityPolicy.idl @@ -1,18 +1,18 @@ /* 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 "nsISerializable.idl" #include "nsIContentPolicy.idl" interface nsIURI; -interface nsIDocShell; interface nsIEventTarget; +interface nsILoadInfo; interface nsIPrincipal; interface nsICSPEventListener; webidl Element; webidl Document; /** * nsIContentSecurityPolicy @@ -270,24 +270,24 @@ interface nsIContentSecurityPolicy : nsI /** * Verifies ancestry as permitted by the policy. * * NOTE: Calls to this may trigger violation reports when queried, so this * value should not be cached. * - * @param docShell - * containing the protected resource + * @param aLoadInfo + * The loadinfo of the channel containing the protected resource * @return * true if the frame's ancestors are all allowed by policy (except for * report-only policies, which will send reports and then return true * here when violated). */ - boolean permitsAncestry(in nsIDocShell docShell); + boolean permitsAncestry(in nsILoadInfo aLoadInfo); /** * Checks if a specific directive permits loading of a URI. * * NOTE: Calls to this may trigger violation reports when queried, so the * return value should not be cached. *
new file mode 100644 --- /dev/null +++ b/dom/security/DOMSecurityManager.cpp @@ -0,0 +1,202 @@ +/* -*- 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 "DOMSecurityManager.h" +#include "nsCSPContext.h" +#include "mozilla/dom/WindowGlobalParent.h" + +#include "nsIMultiPartChannel.h" +#include "nsIObserverService.h" +#include "nsIHttpProtocolHandler.h" + +using namespace mozilla; + +namespace { +StaticRefPtr<DOMSecurityManager> gDOMSecurityManager; +} // namespace + +static nsresult GetHttpChannelHelper(nsIChannel* aChannel, + nsIHttpChannel** aHttpChannel) { + nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aChannel); + if (httpChannel) { + httpChannel.forget(aHttpChannel); + return NS_OK; + } + + nsCOMPtr<nsIMultiPartChannel> multipart = do_QueryInterface(aChannel); + if (!multipart) { + *aHttpChannel = nullptr; + return NS_OK; + } + + nsCOMPtr<nsIChannel> baseChannel; + nsresult rv = multipart->GetBaseChannel(getter_AddRefs(baseChannel)); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + + httpChannel = do_QueryInterface(baseChannel); + httpChannel.forget(aHttpChannel); + + return NS_OK; +} + +NS_INTERFACE_MAP_BEGIN(DOMSecurityManager) + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIObserver) + NS_INTERFACE_MAP_ENTRY(nsIObserver) +NS_INTERFACE_MAP_END + +NS_IMPL_ADDREF(DOMSecurityManager) +NS_IMPL_RELEASE(DOMSecurityManager) + +/* static */ +void DOMSecurityManager::Initialize() { + MOZ_ASSERT(!gDOMSecurityManager); + + MOZ_ASSERT(NS_IsMainThread()); + + if (!XRE_IsParentProcess()) { + return; + } + + RefPtr<DOMSecurityManager> service = new DOMSecurityManager(); + + nsCOMPtr<nsIObserverService> obs = services::GetObserverService(); + if (NS_WARN_IF(!obs)) { + return; + } + + obs->AddObserver(service, NS_HTTP_ON_EXAMINE_RESPONSE_TOPIC, false); + obs->AddObserver(service, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false); + gDOMSecurityManager = service.forget(); +} + +/* static */ +void DOMSecurityManager::Shutdown() { + MOZ_ASSERT(NS_IsMainThread()); + + if (!gDOMSecurityManager) { + return; + } + + RefPtr<DOMSecurityManager> service = gDOMSecurityManager.forget(); + + nsCOMPtr<nsIObserverService> obs = services::GetObserverService(); + if (NS_WARN_IF(!obs)) { + return; + } + + obs->RemoveObserver(service, NS_HTTP_ON_EXAMINE_RESPONSE_TOPIC); + obs->RemoveObserver(service, NS_XPCOM_SHUTDOWN_OBSERVER_ID); +} + +NS_IMETHODIMP +DOMSecurityManager::Observe(nsISupports* aSubject, const char* aTopic, + const char16_t* aData) { + if (!strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID)) { + Shutdown(); + return NS_OK; + } + + MOZ_ASSERT(!strcmp(aTopic, NS_HTTP_ON_EXAMINE_RESPONSE_TOPIC)); + + nsCOMPtr<nsIChannel> channel = do_QueryInterface(aSubject); + if (NS_WARN_IF(!channel)) { + return NS_OK; + } + + nsresult rv = ParseCSPAndEnforceFrameAncestorCheck(channel); + if (NS_FAILED(rv)) { + return rv; + } + + return NS_OK; +} + +nsresult DOMSecurityManager::ParseCSPAndEnforceFrameAncestorCheck( + nsIChannel* aChannel) { + MOZ_ASSERT(aChannel); + + // CSP can only hang off an http channel, if this channel is not + // an http channel then there is nothing to do here. + nsCOMPtr<nsIHttpChannel> httpChannel; + nsresult rv = GetHttpChannelHelper(aChannel, getter_AddRefs(httpChannel)); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + + if (!httpChannel) { + return NS_OK; + } + + nsCOMPtr<nsILoadInfo> loadInfo = aChannel->LoadInfo(); + nsContentPolicyType contentType = loadInfo->GetExternalContentPolicyType(); + // frame-ancestor check only makes sense for subdocument loads, if this is + // not a load of such type, there is nothing to do here. + if (contentType != nsIContentPolicy::TYPE_SUBDOCUMENT) { + return NS_OK; + } + + nsAutoCString tCspHeaderValue, tCspROHeaderValue; + + Unused << httpChannel->GetResponseHeader( + NS_LITERAL_CSTRING("content-security-policy"), tCspHeaderValue); + + Unused << httpChannel->GetResponseHeader( + NS_LITERAL_CSTRING("content-security-policy-report-only"), + tCspROHeaderValue); + + // if there are no CSP values, then there is nothing to do here. + if (tCspHeaderValue.IsEmpty() && tCspROHeaderValue.IsEmpty()) { + return NS_OK; + } + + NS_ConvertASCIItoUTF16 cspHeaderValue(tCspHeaderValue); + NS_ConvertASCIItoUTF16 cspROHeaderValue(tCspROHeaderValue); + + RefPtr<nsCSPContext> csp = new nsCSPContext(); + nsCOMPtr<nsIPrincipal> resultPrincipal; + rv = nsContentUtils::GetSecurityManager()->GetChannelResultPrincipal( + aChannel, getter_AddRefs(resultPrincipal)); + NS_ENSURE_SUCCESS(rv, rv); + nsCOMPtr<nsIURI> selfURI; + aChannel->GetURI(getter_AddRefs(selfURI)); + + nsCOMPtr<nsIReferrerInfo> referrerInfo = httpChannel->GetReferrerInfo(); + nsAutoString referrerSpec; + referrerInfo->GetComputedReferrerSpec(referrerSpec); + uint64_t innerWindowID = loadInfo->GetInnerWindowID(); + + rv = csp->SetRequestContextWithPrincipal(resultPrincipal, selfURI, + referrerSpec, innerWindowID); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + + // ----- if there's a full-strength CSP header, apply it. + if (!cspHeaderValue.IsEmpty()) { + rv = CSP_AppendCSPFromHeader(csp, cspHeaderValue, false); + NS_ENSURE_SUCCESS(rv, rv); + } + + // ----- if there's a report-only CSP header, apply it. + if (!cspROHeaderValue.IsEmpty()) { + rv = CSP_AppendCSPFromHeader(csp, cspROHeaderValue, true); + NS_ENSURE_SUCCESS(rv, rv); + } + + // ----- Enforce frame-ancestor policy on any applied policies + bool safeAncestry = false; + // PermitsAncestry sends violation reports when necessary + rv = csp->PermitsAncestry(loadInfo, &safeAncestry); + + if (NS_FAILED(rv) || !safeAncestry) { + // stop! ERROR page! + aChannel->Cancel(NS_ERROR_CSP_FRAME_ANCESTOR_VIOLATION); + } + + return NS_OK; +}
new file mode 100644 --- /dev/null +++ b/dom/security/DOMSecurityManager.h @@ -0,0 +1,31 @@ +/* -*- 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_DOMSecurityManager_h +#define mozilla_dom_DOMSecurityManager_h + +#include "nsIObserver.h" + +class DOMSecurityManager final : public nsIObserver { + public: + NS_DECL_ISUPPORTS + NS_DECL_NSIOBSERVER + + static void Initialize(); + + private: + DOMSecurityManager() = default; + ~DOMSecurityManager() = default; + + // Only enforces the frame-anecstor check which needs to happen in + // the parent because we can only access the window global in the + // parent. The actual CSP gets parsed and applied in content. + nsresult ParseCSPAndEnforceFrameAncestorCheck(nsIChannel* aChannel); + + static void Shutdown(); +}; + +#endif /* mozilla_dom_DOMSecurityManager_h */
--- a/dom/security/moz.build +++ b/dom/security/moz.build @@ -8,16 +8,17 @@ with Files('*'): BUG_COMPONENT = ('Core', 'DOM: Security') TEST_DIRS += ['test'] DIRS += [ 'featurepolicy' ] EXPORTS.mozilla.dom += [ 'CSPEvalChecker.h', + 'DOMSecurityManager.h', 'FramingChecker.h', 'nsContentSecurityManager.h', 'nsContentSecurityUtils.h', 'nsCSPContext.h', 'nsCSPService.h', 'nsCSPUtils.h', 'nsMixedContentBlocker.h', 'PolicyTokenizer.h', @@ -31,16 +32,17 @@ EXPORTS += [ 'nsContentSecurityManager.h', 'nsContentSecurityUtils.h', 'nsMixedContentBlocker.h', 'ReferrerInfo.h', ] UNIFIED_SOURCES += [ 'CSPEvalChecker.cpp', + 'DOMSecurityManager.cpp', 'FramingChecker.cpp', 'nsContentSecurityManager.cpp', 'nsContentSecurityUtils.cpp', 'nsCSPContext.cpp', 'nsCSPParser.cpp', 'nsCSPService.cpp', 'nsCSPUtils.cpp', 'nsMixedContentBlocker.cpp',
--- a/dom/security/nsCSPContext.cpp +++ b/dom/security/nsCSPContext.cpp @@ -11,18 +11,16 @@ #include "nsContentPolicyUtils.h" #include "nsContentUtils.h" #include "nsCSPContext.h" #include "nsCSPParser.h" #include "nsCSPService.h" #include "nsError.h" #include "nsIAsyncVerifyRedirectCallback.h" #include "nsIClassInfoImpl.h" -#include "nsIDocShell.h" -#include "nsIDocShellTreeItem.h" #include "mozilla/dom/Document.h" #include "nsIHttpChannel.h" #include "nsIInterfaceRequestor.h" #include "nsIInterfaceRequestorUtils.h" #include "nsIObjectInputStream.h" #include "nsIObjectOutputStream.h" #include "nsIObserver.h" #include "nsIObserverService.h" @@ -1517,89 +1515,62 @@ nsresult nsCSPContext::AsyncReportViolat } } NS_DispatchToMainThread(task.forget()); return NS_OK; } /** - * Based on the given docshell, determines if this CSP context allows the + * Based on the given loadinfo, determines if this CSP context allows the * ancestry. * * In order to determine the URI of the parent document (one causing the load - * of this protected document), this function obtains the docShellTreeItem, - * then walks up the hierarchy until it finds a privileged (chrome) tree item. - * Getting the a tree item's URI looks like this in pseudocode: - * - * nsIDocShellTreeItem->GetDocument()->GetDocumentURI(); - * - * aDocShell is the docShell for the protected document. + * of this protected document), this function traverses all Browsing Contexts + * until it reaches the top level browsing context. */ NS_IMETHODIMP -nsCSPContext::PermitsAncestry(nsIDocShell* aDocShell, +nsCSPContext::PermitsAncestry(nsILoadInfo* aLoadInfo, bool* outPermitsAncestry) { + MOZ_ASSERT(XRE_IsParentProcess(), "frame-ancestor check only in parent"); + nsresult rv; - // Can't check ancestry without a docShell. - if (aDocShell == nullptr) { - return NS_ERROR_FAILURE; - } + *outPermitsAncestry = true; - *outPermitsAncestry = true; + RefPtr<mozilla::dom::BrowsingContext> ctx; + aLoadInfo->GetBrowsingContext(getter_AddRefs(ctx)); // extract the ancestry as an array nsCOMArray<nsIURI> ancestorsArray; - - nsCOMPtr<nsIInterfaceRequestor> ir(do_QueryInterface(aDocShell)); - nsCOMPtr<nsIDocShellTreeItem> treeItem(do_GetInterface(ir)); - nsCOMPtr<nsIDocShellTreeItem> parentTreeItem; - nsCOMPtr<nsIURI> currentURI; nsCOMPtr<nsIURI> uriClone; - // iterate through each docShell parent item - while (NS_SUCCEEDED( - treeItem->GetInProcessParent(getter_AddRefs(parentTreeItem))) && - parentTreeItem != nullptr) { - // stop when reaching chrome - if (parentTreeItem->ItemType() == nsIDocShellTreeItem::typeChrome) { - break; - } - - Document* doc = parentTreeItem->GetDocument(); - NS_ASSERTION(doc, - "Could not get Document from nsIDocShellTreeItem in " - "nsCSPContext::PermitsAncestry"); - NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE); - - currentURI = doc->GetDocumentURI(); + while (ctx) { + WindowGlobalParent* window = ctx->Canonical()->GetCurrentWindowGlobal(); + if (window) { + nsCOMPtr<nsIURI> currentURI = window->GetDocumentURI(); + if (currentURI) { + nsAutoCString spec; + currentURI->GetSpec(spec); + // delete the userpass from the URI. + rv = NS_MutateURI(currentURI) + .SetRef(EmptyCString()) + .SetUserPass(EmptyCString()) + .Finalize(uriClone); - if (currentURI) { - // delete the userpass from the URI. - rv = NS_MutateURI(currentURI) - .SetRef(EmptyCString()) - .SetUserPass(EmptyCString()) - .Finalize(uriClone); - - // If setUserPass fails for some reason, just return a clone of the - // current URI - if (NS_FAILED(rv)) { - rv = NS_GetURIWithoutRef(currentURI, getter_AddRefs(uriClone)); - NS_ENSURE_SUCCESS(rv, rv); + // If setUserPass fails for some reason, just return a clone of the + // current URI + if (NS_FAILED(rv)) { + rv = NS_GetURIWithoutRef(currentURI, getter_AddRefs(uriClone)); + NS_ENSURE_SUCCESS(rv, rv); + } + ancestorsArray.AppendElement(uriClone); } - - if (CSPCONTEXTLOGENABLED()) { - CSPCONTEXTLOG(("nsCSPContext::PermitsAncestry, found ancestor: %s", - uriClone->GetSpecOrDefault().get())); - } - ancestorsArray.AppendElement(uriClone); } - - // next ancestor - treeItem = parentTreeItem; + ctx = ctx->GetParent(); } nsAutoString violatedDirective; // Now that we've got the ancestry chain in ancestorsArray, time to check // them against any CSP. // NOTE: the ancestors are not allowed to be sent cross origin; this is a // restriction not placed on subresource loads.
--- a/dom/security/test/csp/mochitest.ini +++ b/dom/security/test/csp/mochitest.ini @@ -252,19 +252,17 @@ prefs = [test_bug885433.html] [test_bug888172.html] [test_bug1505412.html] skip-if = !debug [test_evalscript.html] [test_evalscript_blocked_by_strict_dynamic.html] [test_evalscript_allowed_by_strict_dynamic.html] [test_frameancestors.html] -skip-if = fission [test_frameancestors_userpass.html] -skip-if = fission [test_inlinescript.html] [test_inlinestyle.html] [test_invalid_source_expression.html] [test_bug836922_npolicies.html] skip-if = verify [test_bug886164.html] [test_redirects.html] [test_bug910139.html]
--- a/dom/security/test/csp/test_frameancestors.html +++ b/dom/security/test/csp/test_frameancestors.html @@ -46,20 +46,24 @@ var framesThatShouldLoad = { // abb2_block "frame-ancestors b" (outer frame and test harness) // // so that results in 2 extra violation notifications due to the test harness. // expected = 6, total = 8 // // Number of tests that pass for this file should be 12 (8 violations 4 loads) var expectedViolationsLeft = 8; +// CSP frame-ancestor checks happen in the parent, hence we have to +// proxy the csp violation notifications. +SpecialPowers.registerObservers("csp-on-violate-policy"); + // This is used to watch the blocked data bounce off CSP and allowed data // get sent out to the wire. function examiner() { - SpecialPowers.addObserver(this, "csp-on-violate-policy"); + SpecialPowers.addObserver(this, "specialpowers-csp-on-violate-policy"); } examiner.prototype = { observe(subject, topic, data) { // subject should be an nsURI... though could be null since CSP // prohibits cross-origin URI reporting during frame ancestors checks. if (subject && !SpecialPowers.can_QI(subject)) return; @@ -76,26 +80,26 @@ examiner.prototype = { if (asciiSpec.includes("test_frameancestors.html")) { return; } } catch (ex) { // was not an nsIURI, so it was probably a cross-origin report. } - if (topic === "csp-on-violate-policy") { + if (topic === "specialpowers-csp-on-violate-policy") { //these were blocked... record that they were blocked window.frameBlocked(asciiSpec, data); } }, // must eventually call this to remove the listener, // or mochitests might get borked. remove() { - SpecialPowers.removeObserver(this, "csp-on-violate-policy"); + SpecialPowers.removeObserver(this, "specialpowers-csp-on-violate-policy"); } } // called when a frame is loaded // -- if it's not enumerated above, it should not load! var frameLoaded = function(testname, uri) { //test already complete.... forget it... remember the first result. if (window.framesThatShouldLoad[testname] != -1)
--- a/dom/security/test/csp/test_frameancestors_userpass.html +++ b/dom/security/test/csp/test_frameancestors_userpass.html @@ -17,20 +17,24 @@ var framesThatShouldLoad = { frame_a: -1, /* frame a allowed */ frame_b: -1, /* frame b allowed */ }; // Number of tests that pass for this file should be 1 var expectedViolationsLeft = 1; +// CSP frame-ancestor checks happen in the parent, hence we have to +// proxy the csp violation notifications. +SpecialPowers.registerObservers("csp-on-violate-policy"); + // This is used to watch the blocked data bounce off CSP and allowed data // get sent out to the wire. function examiner() { - SpecialPowers.addObserver(this, "csp-on-violate-policy"); + SpecialPowers.addObserver(this, "specialpowers-csp-on-violate-policy"); } examiner.prototype = { observe(subject, topic, data) { // subject should be an nsURI... though could be null since CSP // prohibits cross-origin URI reporting during frame ancestors checks. if (subject && !SpecialPowers.can_QI(subject)) return; @@ -46,27 +50,26 @@ examiner.prototype = { // can cause this test to over-succeed (but only in specific cases). if (asciiSpec.includes("test_frameancestors_userpass.html")) { return; } } catch (ex) { // was not an nsIURI, so it was probably a cross-origin report. } - - if (topic === "csp-on-violate-policy") { + if (topic === "specialpowers-csp-on-violate-policy") { //these were blocked... record that they were blocked window.frameBlocked(asciiSpec, data); } }, // must eventually call this to remove the listener, // or mochitests might get borked. remove() { - SpecialPowers.removeObserver(this, "csp-on-violate-policy"); + SpecialPowers.removeObserver(this, "specialpowers-csp-on-violate-policy"); } } // called when a frame is loaded // -- if it's not enumerated above, it should not load! var frameLoaded = function(testname, uri) { //test already complete.... forget it... remember the first result. if (window.framesThatShouldLoad[testname] != -1)
--- a/dom/security/test/csp/test_report_uri_missing_in_report_only_header.html +++ b/dom/security/test/csp/test_report_uri_missing_in_report_only_header.html @@ -16,17 +16,26 @@ https://bugzilla.mozilla.org/show_bug.cg <iframe id="cspframe"></iframe> <pre id="test"> <script class="testbody" type="text/javascript"> var stringBundleService = SpecialPowers.Cc["@mozilla.org/intl/stringbundle;1"] .getService(SpecialPowers.Ci.nsIStringBundleService); var localizer = stringBundleService.createBundle("chrome://global/locale/security/csp.properties"); var warningMsg = localizer.formatStringFromName("reportURInotInReportOnlyHeader", [window.location.origin]); + +// Since Bug 1584993 we parse the CSP in the parent too, hence the +// same error message appears twice in the console. +var callCleanUpOnce = false; + function cleanup() { + if (callCleanUpOnce) { + return; + } + callCleanUpOnce = true; SpecialPowers.postConsoleSentinel(); SimpleTest.finish(); } SpecialPowers.registerConsoleListener(function ConsoleMsgListener(aMsg) { if (aMsg.message.indexOf(warningMsg) > -1) { ok(true, "report-uri not specified in Report-Only should throw a CSP warning."); SimpleTest.executeSoon(cleanup);
--- a/layout/build/nsLayoutStatics.cpp +++ b/layout/build/nsLayoutStatics.cpp @@ -104,16 +104,17 @@ #include "mozilla/EventDispatcher.h" #include "mozilla/IMEStateManager.h" #include "mozilla/dom/HTMLVideoElement.h" #include "ThirdPartyUtil.h" #include "TouchManager.h" #include "DecoderDoctorLogger.h" #include "MediaDecoder.h" #include "mozilla/ClearSiteData.h" +#include "mozilla/dom/DOMSecurityManager.h" #include "mozilla/EditorController.h" #include "mozilla/Fuzzyfox.h" #include "mozilla/HTMLEditorController.h" #include "mozilla/ServoBindings.h" #include "mozilla/StaticPresData.h" #include "mozilla/dom/Document.h" #include "mozilla/dom/IPCBlobInputStreamStorage.h" #include "mozilla/dom/WebIDLGlobalNameHash.h" @@ -303,16 +304,18 @@ nsresult nsLayoutStatics::Initialize() { } nsThreadManager::InitializeShutdownObserver(); mozilla::Fuzzyfox::Start(); ClearSiteData::Initialize(); + DOMSecurityManager::Initialize(); + // Reporting API. ReportingHeader::Initialize(); if (XRE_IsParentProcess()) { InitializeQuotaManager(); InitializeLocalStorage(); }
--- a/testing/specialpowers/content/SpecialPowersChild.jsm +++ b/testing/specialpowers/content/SpecialPowersChild.jsm @@ -2250,16 +2250,35 @@ SpecialPowersChild.prototype._proxiedObs "specialpowers-http-notify-request", uri ); }, "specialpowers-service-worker-shutdown": function(aMessage) { Services.obs.notifyObservers(null, "specialpowers-service-worker-shutdown"); }, + + "specialpowers-csp-on-violate-policy": function(aMessage) { + let subject = null; + + try { + subject = Services.io.newURI(aMessage.data.subject); + } catch (ex) { + // if it's not a valid URI it must be an nsISupportsCString + subject = Cc["@mozilla.org/supports-cstring;1"].createInstance( + Ci.nsISupportsCString + ); + subject.data = aMessage.data.subject; + } + Services.obs.notifyObservers( + subject, + "specialpowers-csp-on-violate-policy", + aMessage.data.data + ); + }, }; SpecialPowersChild.prototype.permissionObserverProxy = { // 'this' in permChangedObserverProxy is the permChangedObserverProxy // object itself. The '_specialPowersAPI' will be set to the 'SpecialPowersChild' // object to call the member function in SpecialPowersChild. _specialPowersAPI: null, observe(aSubject, aTopic, aData) {
--- a/testing/specialpowers/content/SpecialPowersParent.jsm +++ b/testing/specialpowers/content/SpecialPowersParent.jsm @@ -155,17 +155,34 @@ class SpecialPowersParent extends JSWind // We need to ensure that it looks the same as a real permission, // so we fake these properties. msg.permission = { principal: { originAttributes: {}, }, type: permission.type, }; - // fall through + this._self.sendAsyncMessage("specialpowers-" + aTopic, msg); + return; + case "csp-on-violate-policy": + // the subject is either an nsIURI or an nsISupportsCString + let subject = null; + if (aSubject instanceof Ci.nsIURI) { + subject = aSubject.asciiSpec; + } else if (aSubject instanceof Ci.nsISupportsCString) { + subject = aSubject.data; + } else { + throw new Error("Subject must be nsIURI or nsISupportsCString"); + } + msg = { + subject, + data: aData, + }; + this._self.sendAsyncMessage("specialpowers-" + aTopic, msg); + return; default: this._self.sendAsyncMessage("specialpowers-" + aTopic, msg); } }, }; this.init();
--- a/testing/web-platform/meta/content-security-policy/frame-ancestors/frame-ancestors-from-serviceworker.https.html.ini +++ b/testing/web-platform/meta/content-security-policy/frame-ancestors/frame-ancestors-from-serviceworker.https.html.ini @@ -1,5 +1,4 @@ [frame-ancestors-from-serviceworker.https.html] - expected: TIMEOUT [A 'frame-ancestors' CSP directive set from a serviceworker response with a value 'none' should block rendering.] - expected: TIMEOUT + expected: FAIL