зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1584993: Make CSP frame-ancestors work with fission enabled. r=jkt,farre,valentin
Differential Revision: https://phabricator.services.mozilla.com/D49147 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
9549d17872
Коммит
61c17da3e9
|
@ -3286,21 +3286,6 @@ nsresult Document::InitCSP(nsIChannel* aChannel) {
|
|||
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;
|
||||
}
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
#include "nsIContentPolicy.idl"
|
||||
|
||||
interface nsIURI;
|
||||
interface nsIDocShell;
|
||||
interface nsIEventTarget;
|
||||
interface nsILoadInfo;
|
||||
interface nsIPrincipal;
|
||||
interface nsICSPEventListener;
|
||||
|
||||
|
@ -275,14 +275,14 @@ interface nsIContentSecurityPolicy : nsISerializable
|
|||
* 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);
|
||||
|
||||
|
||||
/**
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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 */
|
|
@ -13,6 +13,7 @@ DIRS += [ 'featurepolicy' ]
|
|||
|
||||
EXPORTS.mozilla.dom += [
|
||||
'CSPEvalChecker.h',
|
||||
'DOMSecurityManager.h',
|
||||
'FramingChecker.h',
|
||||
'nsContentSecurityManager.h',
|
||||
'nsContentSecurityUtils.h',
|
||||
|
@ -36,6 +37,7 @@ EXPORTS += [
|
|||
|
||||
UNIFIED_SOURCES += [
|
||||
'CSPEvalChecker.cpp',
|
||||
'DOMSecurityManager.cpp',
|
||||
'FramingChecker.cpp',
|
||||
'nsContentSecurityManager.cpp',
|
||||
'nsContentSecurityUtils.cpp',
|
||||
|
|
|
@ -16,8 +16,6 @@
|
|||
#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"
|
||||
|
@ -1522,79 +1520,52 @@ nsresult nsCSPContext::AsyncReportViolation(
|
|||
}
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
nsresult rv;
|
||||
MOZ_ASSERT(XRE_IsParentProcess(), "frame-ancestor check only in parent");
|
||||
|
||||
// Can't check ancestry without a docShell.
|
||||
if (aDocShell == nullptr) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
nsresult rv;
|
||||
|
||||
*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;
|
||||
}
|
||||
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);
|
||||
|
||||
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();
|
||||
|
||||
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;
|
||||
|
|
|
@ -257,9 +257,7 @@ skip-if = !debug
|
|||
[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]
|
||||
|
|
|
@ -51,10 +51,14 @@ var framesThatShouldLoad = {
|
|||
// 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) {
|
||||
|
@ -81,7 +85,7 @@ examiner.prototype = {
|
|||
}
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
|
@ -90,7 +94,7 @@ examiner.prototype = {
|
|||
// 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");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -22,10 +22,14 @@ var framesThatShouldLoad = {
|
|||
// 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) {
|
||||
|
@ -51,8 +55,7 @@ examiner.prototype = {
|
|||
// 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);
|
||||
}
|
||||
|
@ -61,7 +64,7 @@ examiner.prototype = {
|
|||
// 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");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -21,13 +21,23 @@ 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]);
|
||||
|
||||
function cleanup() {
|
||||
SpecialPowers.postConsoleSentinel();
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
// Since Bug 1584993 we parse the CSP in the parent too, hence the
|
||||
// same error message appears twice in the console.
|
||||
var recordConsoleMsgOnce = false;
|
||||
|
||||
SpecialPowers.registerConsoleListener(function ConsoleMsgListener(aMsg) {
|
||||
if (aMsg.message.indexOf(warningMsg) > -1) {
|
||||
if (recordConsoleMsgOnce) {
|
||||
return;
|
||||
}
|
||||
recordConsoleMsgOnce = true;
|
||||
|
||||
ok(true, "report-uri not specified in Report-Only should throw a CSP warning.");
|
||||
SimpleTest.executeSoon(cleanup);
|
||||
return;
|
||||
|
|
|
@ -109,6 +109,7 @@
|
|||
#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"
|
||||
|
@ -308,6 +309,8 @@ nsresult nsLayoutStatics::Initialize() {
|
|||
|
||||
ClearSiteData::Initialize();
|
||||
|
||||
DOMSecurityManager::Initialize();
|
||||
|
||||
// Reporting API.
|
||||
ReportingHeader::Initialize();
|
||||
|
||||
|
|
|
@ -2255,6 +2255,25 @@ SpecialPowersChild.prototype._proxiedObservers = {
|
|||
"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 = {
|
||||
|
|
|
@ -160,7 +160,24 @@ class SpecialPowersParent extends JSWindowActorParent {
|
|||
},
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче