| Index: third_party/WebKit/Source/core/frame/csp/ContentSecurityPolicy.cpp
|
| diff --git a/third_party/WebKit/Source/core/frame/csp/ContentSecurityPolicy.cpp b/third_party/WebKit/Source/core/frame/csp/ContentSecurityPolicy.cpp
|
| index b12b47f5c52ab889159ba2a33ddd2556c8935d08..4216d8cb9a891b8c0ef88f2693a2f05b0fd380c7 100644
|
| --- a/third_party/WebKit/Source/core/frame/csp/ContentSecurityPolicy.cpp
|
| +++ b/third_party/WebKit/Source/core/frame/csp/ContentSecurityPolicy.cpp
|
| @@ -48,6 +48,7 @@
|
| #include "core/loader/DocumentLoader.h"
|
| #include "core/loader/FrameLoaderClient.h"
|
| #include "core/loader/PingLoader.h"
|
| +#include "core/workers/WorkerGlobalScope.h"
|
| #include "platform/RuntimeEnabledFeatures.h"
|
| #include "platform/json/JSONValues.h"
|
| #include "platform/network/ContentSecurityPolicyParsers.h"
|
| @@ -1040,7 +1041,7 @@ void ContentSecurityPolicy::upgradeInsecureRequests() {
|
| m_insecureRequestPolicy |= kUpgradeInsecureRequests;
|
| }
|
|
|
| -static String stripURLForUseInReport(Document* document,
|
| +static String stripURLForUseInReport(ExecutionContext* context,
|
| const KURL& url,
|
| RedirectStatus redirectStatus,
|
| const String& effectiveDirective) {
|
| @@ -1053,7 +1054,7 @@ static String stripURLForUseInReport(Document* document,
|
| // (and, by extension, in plugin documents), strip cross-origin 'frame-src'
|
| // and 'object-src' violations down to an origin. https://crbug.com/633306
|
| bool canSafelyExposeURL =
|
| - document->getSecurityOrigin()->canRequest(url) ||
|
| + context->getSecurityOrigin()->canRequest(url) ||
|
| (redirectStatus == RedirectStatus::NoRedirect &&
|
| !equalIgnoringCase(effectiveDirective,
|
| ContentSecurityPolicy::FrameSrc) &&
|
| @@ -1072,7 +1073,7 @@ static String stripURLForUseInReport(Document* document,
|
|
|
| static void gatherSecurityPolicyViolationEventData(
|
| SecurityPolicyViolationEventInit& init,
|
| - Document* document,
|
| + ExecutionContext* context,
|
| const String& directiveText,
|
| const String& effectiveDirective,
|
| const KURL& blockedURL,
|
| @@ -1089,7 +1090,7 @@ static void gatherSecurityPolicyViolationEventData(
|
| init.setDocumentURI(blockedURL.getString());
|
| init.setBlockedURI(blockedURL.getString());
|
| } else {
|
| - init.setDocumentURI(document->url().getString());
|
| + init.setDocumentURI(context->url().getString());
|
| switch (violationType) {
|
| case ContentSecurityPolicy::InlineViolation:
|
| init.setBlockedURI("inline");
|
| @@ -1099,11 +1100,11 @@ static void gatherSecurityPolicyViolationEventData(
|
| break;
|
| case ContentSecurityPolicy::URLViolation:
|
| init.setBlockedURI(stripURLForUseInReport(
|
| - document, blockedURL, redirectStatus, effectiveDirective));
|
| + context, blockedURL, redirectStatus, effectiveDirective));
|
| break;
|
| }
|
| }
|
| - init.setReferrer(document->referrer());
|
| +
|
| init.setViolatedDirective(effectiveDirective);
|
| init.setEffectiveDirective(effectiveDirective);
|
| init.setOriginalPolicy(header);
|
| @@ -1115,13 +1116,20 @@ static void gatherSecurityPolicyViolationEventData(
|
| init.setColumnNumber(0);
|
| init.setStatusCode(0);
|
|
|
| - if (!SecurityOrigin::isSecure(document->url()) && document->loader())
|
| - init.setStatusCode(document->loader()->response().httpStatusCode());
|
| + // TODO(mkwst): We only have referrer and status code information for
|
| + // Documents. It would be nice to get them for Workers as well.
|
| + if (context->isDocument()) {
|
| + Document* document = toDocument(context);
|
| + DCHECK(document);
|
| + init.setReferrer(document->referrer());
|
| + if (!SecurityOrigin::isSecure(context->url()) && document->loader())
|
| + init.setStatusCode(document->loader()->response().httpStatusCode());
|
| + }
|
|
|
| - std::unique_ptr<SourceLocation> location = SourceLocation::capture(document);
|
| + std::unique_ptr<SourceLocation> location = SourceLocation::capture(context);
|
| if (location->lineNumber()) {
|
| KURL source = KURL(ParsedURLString, location->url());
|
| - init.setSourceFile(stripURLForUseInReport(document, source, redirectStatus,
|
| + init.setSourceFile(stripURLForUseInReport(context, source, redirectStatus,
|
| effectiveDirective));
|
| init.setLineNumber(location->lineNumber());
|
| init.setColumnNumber(location->columnNumber());
|
| @@ -1156,21 +1164,22 @@ void ContentSecurityPolicy::reportViolation(
|
| return;
|
| }
|
|
|
| - ASSERT((m_executionContext && !contextFrame) ||
|
| + DCHECK((m_executionContext && !contextFrame) ||
|
| (equalIgnoringCase(effectiveDirective,
|
| ContentSecurityPolicy::FrameAncestors) &&
|
| contextFrame));
|
|
|
| - // FIXME: Support sending reports from worker.
|
| - Document* document =
|
| - contextFrame ? contextFrame->document() : this->document();
|
| - if (!document)
|
| - return;
|
| -
|
| SecurityPolicyViolationEventInit violationData;
|
| +
|
| + // If we're processing 'frame-ancestors', use |contextFrame|'s execution
|
| + // context to gather data. Otherwise, use the policy's execution context.
|
| + ExecutionContext* relevantContext =
|
| + contextFrame ? contextFrame->document() : m_executionContext;
|
| + DCHECK(relevantContext);
|
| gatherSecurityPolicyViolationEventData(
|
| - violationData, document, directiveText, effectiveDirective, blockedURL,
|
| - header, redirectStatus, headerType, violationType, contextLine);
|
| + violationData, relevantContext, directiveText, effectiveDirective,
|
| + blockedURL, header, redirectStatus, headerType, violationType,
|
| + contextLine);
|
|
|
| // TODO(mkwst): Obviously, we shouldn't hit this check, as extension-loaded
|
| // resources should be allowed regardless. We apparently do, however, so
|
| @@ -1178,7 +1187,31 @@ void ContentSecurityPolicy::reportViolation(
|
| // https://crbug.com/524356 for detail.
|
| if (!violationData.sourceFile().isEmpty() &&
|
| SchemeRegistry::schemeShouldBypassContentSecurityPolicy(
|
| - KURL(ParsedURLString, violationData.sourceFile()).protocol()))
|
| + KURL(ParsedURLString, violationData.sourceFile()).protocol())) {
|
| + return;
|
| + }
|
| +
|
| + postViolationReport(violationData, contextFrame, reportEndpoints);
|
| +
|
| + // Fire a violation event if we're working within an execution context (e.g.
|
| + // we're not processing 'frame-ancestors').
|
| + if (m_executionContext) {
|
| + m_executionContext->postTask(
|
| + BLINK_FROM_HERE,
|
| + createSameThreadTask(&ContentSecurityPolicy::dispatchViolationEvents,
|
| + wrapPersistent(this), violationData,
|
| + wrapPersistent(element)));
|
| + }
|
| +}
|
| +
|
| +void ContentSecurityPolicy::postViolationReport(
|
| + const SecurityPolicyViolationEventInit& violationData,
|
| + LocalFrame* contextFrame,
|
| + const Vector<String>& reportEndpoints) {
|
| + // TODO(mkwst): Support POSTing violation reports from a Worker.
|
| + Document* document =
|
| + contextFrame ? contextFrame->document() : this->document();
|
| + if (!document)
|
| return;
|
|
|
| // We need to be careful here when deciding what information to send to the
|
| @@ -1233,41 +1266,42 @@ void ContentSecurityPolicy::reportViolation(
|
| // document's URL.
|
| DCHECK(!contextFrame || !m_executionContext);
|
| DCHECK(!contextFrame ||
|
| - equalIgnoringCase(effectiveDirective, FrameAncestors));
|
| + equalIgnoringCase(violationData.effectiveDirective(),
|
| + FrameAncestors));
|
| KURL url =
|
| contextFrame
|
| - ? frame->document()->completeURLWithOverride(endpoint, blockedURL)
|
| + ? frame->document()->completeURLWithOverride(
|
| + endpoint, KURL(ParsedURLString, violationData.blockedURI()))
|
| : completeURL(endpoint);
|
| PingLoader::sendViolationReport(
|
| frame, url, report, PingLoader::ContentSecurityPolicyViolationReport);
|
| }
|
| }
|
| -
|
| - document->postTask(
|
| - BLINK_FROM_HERE,
|
| - createSameThreadTask(&ContentSecurityPolicy::dispatchViolationEvents,
|
| - wrapPersistent(this), violationData,
|
| - wrapPersistent(element), wrapPersistent(document)));
|
| }
|
|
|
| void ContentSecurityPolicy::dispatchViolationEvents(
|
| const SecurityPolicyViolationEventInit& violationData,
|
| - Element* element,
|
| - Document* document) {
|
| - // If the document is detached or closed (thus clearing its event queue)
|
| + Element* element) {
|
| + // If the context is detached or closed (thus clearing its event queue)
|
| // between the violation occuring and this event dispatch, exit early.
|
| - if (!document->domWindow() || !document->domWindow()->getEventQueue())
|
| + EventQueue* queue = m_executionContext->getEventQueue();
|
| + if (!queue)
|
| return;
|
|
|
| SecurityPolicyViolationEvent* event = SecurityPolicyViolationEvent::create(
|
| EventTypeNames::securitypolicyviolation, violationData);
|
| DCHECK(event->bubbles());
|
| - if (element && element->isConnected() && element->document() == document) {
|
| - event->setTarget(element);
|
| - document->domWindow()->getEventQueue()->enqueueEvent(event);
|
| - } else {
|
| - document->domWindow()->enqueueDocumentEvent(event);
|
| +
|
| + if (m_executionContext->isDocument()) {
|
| + Document* document = toDocument(m_executionContext);
|
| + if (element && element->isConnected() && element->document() == document)
|
| + event->setTarget(element);
|
| + else
|
| + event->setTarget(document);
|
| + } else if (m_executionContext->isWorkerGlobalScope()) {
|
| + event->setTarget(toWorkerGlobalScope(m_executionContext));
|
| }
|
| + queue->enqueueEvent(event);
|
| }
|
|
|
| void ContentSecurityPolicy::reportMixedContent(const KURL& mixedURL,
|
|
|