Abstract logic to log console messages and send CSP violation reports into a client
authordbates@webkit.org <dbates@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 8 May 2018 03:51:10 +0000 (03:51 +0000)
committerdbates@webkit.org <dbates@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 8 May 2018 03:51:10 +0000 (03:51 +0000)
https://bugs.webkit.org/show_bug.cgi?id=185393
<rdar://problem/40036053>

Reviewed by Brent Fulgham.

Source/WebCore:

First pass at adding infrastructure to supporting CSP reporting from NetworkProcess and workers.
Replaces the existing ContentSecurityPolicy constructor that takes a Frame with one that
takes a ContentSecurityPolicyClient to delegate to for logging and sending reports. We will look
to remove ContentSecurityPolicy constructor that takes a ScriptExecutionContext in a follow up.

Standardize on instantiating a ContentSecurityPolicy with the full URL to resource that it protects
instead of taking only the SecurityOrigin of this URL. By taking the full URL the ContentSecurityPolicy
object is now capable of resolving a relative report URL without needing a Document/ScriptExecutionContext.

We are underutilizing the CSPInfo struct and ContentSecurityPolicyClient::willSendCSPViolationReport()
delegate callback in this patch. We will make use of this functionality in a subsequent patch to
support collecting script state (e.g. source line number) when reporting CSP violations in worker
threads. We also no longer go through the unnecessary motions to try to collect script state for a
frame-ancestors violation (since DocumentLoader extends ContentSecurityPolicyClient and does not
implement ContentSecurityPolicyClient::willSendCSPViolationReport()). The frame-ancestors directive
is checked before a document is parsed and executes script; => there will never be any script state
to collect; => it is not necessary to try to collect it as we currently do.

* Sources.txt: Add file ContentSecurityPolicyClient.cpp. See the remarks for ContentSecurityPolicyClient.cpp
below on why we have this file.
* WebCore.xcodeproj/project.pbxproj: Add files ContentSecurityPolicyClient.{h, cpp}.
* dom/Document.cpp:
(WebCore::Document::initSecurityContext): Pass the URL of the protected document.
* loader/DocumentLoader.cpp:
(WebCore::DocumentLoader::responseReceived): Ditto.
(WebCore::DocumentLoader::addConsoleMessage): Added.
(WebCore::DocumentLoader::sendCSPViolationReport): Added.
(WebCore::DocumentLoader::dispatchSecurityPolicyViolationEvent): Added.
* loader/DocumentLoader.h:
* loader/FrameLoaderClient.h: Fix typo in comment.
* loader/WorkerThreadableLoader.cpp:
(WebCore::WorkerThreadableLoader::MainThreadBridge::MainThreadBridge): Pass the URL of the worker script.
* page/csp/ContentSecurityPolicy.cpp:
(WebCore::ContentSecurityPolicy::ContentSecurityPolicy): Added overload that takes a URL&& and an optional
ContentSecurityPolicyClient*.
(WebCore::ContentSecurityPolicy::deprecatedURLForReporting const): Extracted and simplified stripURLForUseInReport()
into this member function.
(WebCore::ContentSecurityPolicy::reportViolation const): Modified to make use of the client, if we have
one and removed code for handling a ContentSecurityPolicy that was instantiated with a Frame.
(WebCore::ContentSecurityPolicy::logToConsole const): Ditto.
(WebCore::stripURLForUseInReport): Deleted; incorporated into ContentSecurityPolicy::deprecatedURLForReporting().
* page/csp/ContentSecurityPolicy.h:
* page/csp/ContentSecurityPolicyClient.cpp: Added. This file exists so that we can define the virtual
destructor out-of-line and export this abstract class so as to avoid the need for the vtable to be
defined in the translation unit of each derived class.
* page/csp/ContentSecurityPolicyClient.h: Added.
* page/csp/ContentSecurityPolicySource.cpp:
(WebCore::ContentSecurityPolicySource::operator SecurityOriginData const): Added.
* page/csp/ContentSecurityPolicySource.h:
* workers/WorkerGlobalScope.cpp:
(WebCore::WorkerGlobalScope::WorkerGlobalScope): Instantiate the ContentSecurityPolicy object with the
URL of the worker script.

Source/WebKit:

For now, build a URL from the source origin associated with the NetworkResourceLoader
and pass this to the ContentSecurityPolicy constructor.

Additionally, make NetworkLoadChecker::contentSecurityPolicy() non-const since it returns
a non-const pointer to a ContentSecurityPolicy object; => callers can mutate this object
right from under NetworkLoadChecker. Making this non-const makes this clear to a reader.
Also remove the mutable keyword from the definition of NetworkLoadChecker::m_contentSecurityPolicy.

* NetworkProcess/NetworkLoadChecker.cpp:
(WebKit::NetworkLoadChecker::contentSecurityPolicy):
(WebKit::NetworkLoadChecker::contentSecurityPolicy const): Deleted.
* NetworkProcess/NetworkLoadChecker.h:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@231476 268f45cc-cd09-0410-ab3c-d52691b4dbfc

18 files changed:
Source/WebCore/ChangeLog
Source/WebCore/Sources.txt
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/dom/Document.cpp
Source/WebCore/loader/DocumentLoader.cpp
Source/WebCore/loader/DocumentLoader.h
Source/WebCore/loader/FrameLoaderClient.h
Source/WebCore/loader/WorkerThreadableLoader.cpp
Source/WebCore/page/csp/ContentSecurityPolicy.cpp
Source/WebCore/page/csp/ContentSecurityPolicy.h
Source/WebCore/page/csp/ContentSecurityPolicyClient.cpp [new file with mode: 0644]
Source/WebCore/page/csp/ContentSecurityPolicyClient.h [new file with mode: 0644]
Source/WebCore/page/csp/ContentSecurityPolicySource.cpp
Source/WebCore/page/csp/ContentSecurityPolicySource.h
Source/WebCore/workers/WorkerGlobalScope.cpp
Source/WebKit/ChangeLog
Source/WebKit/NetworkProcess/NetworkLoadChecker.cpp
Source/WebKit/NetworkProcess/NetworkLoadChecker.h

index 0605d3d..88e5902 100644 (file)
@@ -1,3 +1,64 @@
+2018-05-07  Daniel Bates  <dabates@apple.com>
+
+        Abstract logic to log console messages and send CSP violation reports into a client
+        https://bugs.webkit.org/show_bug.cgi?id=185393
+        <rdar://problem/40036053>
+
+        Reviewed by Brent Fulgham.
+
+        First pass at adding infrastructure to supporting CSP reporting from NetworkProcess and workers.
+        Replaces the existing ContentSecurityPolicy constructor that takes a Frame with one that
+        takes a ContentSecurityPolicyClient to delegate to for logging and sending reports. We will look
+        to remove ContentSecurityPolicy constructor that takes a ScriptExecutionContext in a follow up.
+
+        Standardize on instantiating a ContentSecurityPolicy with the full URL to resource that it protects
+        instead of taking only the SecurityOrigin of this URL. By taking the full URL the ContentSecurityPolicy
+        object is now capable of resolving a relative report URL without needing a Document/ScriptExecutionContext.
+
+        We are underutilizing the CSPInfo struct and ContentSecurityPolicyClient::willSendCSPViolationReport()
+        delegate callback in this patch. We will make use of this functionality in a subsequent patch to
+        support collecting script state (e.g. source line number) when reporting CSP violations in worker
+        threads. We also no longer go through the unnecessary motions to try to collect script state for a
+        frame-ancestors violation (since DocumentLoader extends ContentSecurityPolicyClient and does not
+        implement ContentSecurityPolicyClient::willSendCSPViolationReport()). The frame-ancestors directive
+        is checked before a document is parsed and executes script; => there will never be any script state
+        to collect; => it is not necessary to try to collect it as we currently do.
+
+        * Sources.txt: Add file ContentSecurityPolicyClient.cpp. See the remarks for ContentSecurityPolicyClient.cpp
+        below on why we have this file.
+        * WebCore.xcodeproj/project.pbxproj: Add files ContentSecurityPolicyClient.{h, cpp}.
+        * dom/Document.cpp:
+        (WebCore::Document::initSecurityContext): Pass the URL of the protected document.
+        * loader/DocumentLoader.cpp:
+        (WebCore::DocumentLoader::responseReceived): Ditto.
+        (WebCore::DocumentLoader::addConsoleMessage): Added.
+        (WebCore::DocumentLoader::sendCSPViolationReport): Added.
+        (WebCore::DocumentLoader::dispatchSecurityPolicyViolationEvent): Added.
+        * loader/DocumentLoader.h:
+        * loader/FrameLoaderClient.h: Fix typo in comment.
+        * loader/WorkerThreadableLoader.cpp:
+        (WebCore::WorkerThreadableLoader::MainThreadBridge::MainThreadBridge): Pass the URL of the worker script.
+        * page/csp/ContentSecurityPolicy.cpp:
+        (WebCore::ContentSecurityPolicy::ContentSecurityPolicy): Added overload that takes a URL&& and an optional
+        ContentSecurityPolicyClient*.
+        (WebCore::ContentSecurityPolicy::deprecatedURLForReporting const): Extracted and simplified stripURLForUseInReport()
+        into this member function.
+        (WebCore::ContentSecurityPolicy::reportViolation const): Modified to make use of the client, if we have
+        one and removed code for handling a ContentSecurityPolicy that was instantiated with a Frame.
+        (WebCore::ContentSecurityPolicy::logToConsole const): Ditto.
+        (WebCore::stripURLForUseInReport): Deleted; incorporated into ContentSecurityPolicy::deprecatedURLForReporting().
+        * page/csp/ContentSecurityPolicy.h:
+        * page/csp/ContentSecurityPolicyClient.cpp: Added. This file exists so that we can define the virtual
+        destructor out-of-line and export this abstract class so as to avoid the need for the vtable to be
+        defined in the translation unit of each derived class.
+        * page/csp/ContentSecurityPolicyClient.h: Added.
+        * page/csp/ContentSecurityPolicySource.cpp:
+        (WebCore::ContentSecurityPolicySource::operator SecurityOriginData const): Added.
+        * page/csp/ContentSecurityPolicySource.h:
+        * workers/WorkerGlobalScope.cpp:
+        (WebCore::WorkerGlobalScope::WorkerGlobalScope): Instantiate the ContentSecurityPolicy object with the
+        URL of the worker script.
+
 2018-05-07  Simon Fraser  <simon.fraser@apple.com>
 
         CSS filters which reference SVG filters fail to respect the "color-interpolation-filters" of the filter
index e803a7c..94e010a 100644 (file)
@@ -1430,6 +1430,7 @@ page/animation/ImplicitAnimation.cpp
 page/animation/KeyframeAnimation.cpp
 
 page/csp/ContentSecurityPolicy.cpp
+page/csp/ContentSecurityPolicyClient.cpp
 page/csp/ContentSecurityPolicyDirective.cpp
 page/csp/ContentSecurityPolicyDirectiveList.cpp
 page/csp/ContentSecurityPolicyDirectiveNames.cpp
index ec0c7b7..f9bdb8f 100644 (file)
                CE08C3D2152B599A0021B8C2 /* AlternativeTextController.h in Headers */ = {isa = PBXBuildFile; fileRef = CE08C3D0152B599A0021B8C2 /* AlternativeTextController.h */; settings = {ATTRIBUTES = (); }; };
                CE1866451F72E5B400A0CAB6 /* MarkedText.h in Headers */ = {isa = PBXBuildFile; fileRef = CE1866431F72E5B400A0CAB6 /* MarkedText.h */; settings = {ATTRIBUTES = (Private, ); }; };
                CE2849871CA360DF00B4A57F /* ContentSecurityPolicyDirectiveNames.h in Headers */ = {isa = PBXBuildFile; fileRef = CE2849861CA360DF00B4A57F /* ContentSecurityPolicyDirectiveNames.h */; };
+               CE5FA255209E48C50051D700 /* ContentSecurityPolicyClient.h in Headers */ = {isa = PBXBuildFile; fileRef = CE5FA253209E48C50051D700 /* ContentSecurityPolicyClient.h */; settings = {ATTRIBUTES = (Private, ); }; };
                CE6DADFA1C591E6A003F6A88 /* ContentSecurityPolicyResponseHeaders.h in Headers */ = {isa = PBXBuildFile; fileRef = CE6DADF81C591E6A003F6A88 /* ContentSecurityPolicyResponseHeaders.h */; settings = {ATTRIBUTES = (Private, ); }; };
                CE799F981C6A46BC0097B518 /* ContentSecurityPolicySourceList.h in Headers */ = {isa = PBXBuildFile; fileRef = CE799F961C6A46BC0097B518 /* ContentSecurityPolicySourceList.h */; };
                CE799F9C1C6A4BCD0097B518 /* ContentSecurityPolicyDirectiveList.h in Headers */ = {isa = PBXBuildFile; fileRef = CE799F9A1C6A4BCD0097B518 /* ContentSecurityPolicyDirectiveList.h */; };
                CE2849861CA360DF00B4A57F /* ContentSecurityPolicyDirectiveNames.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ContentSecurityPolicyDirectiveNames.h; path = csp/ContentSecurityPolicyDirectiveNames.h; sourceTree = "<group>"; };
                CE2849881CA3614600B4A57F /* ContentSecurityPolicyDirectiveNames.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ContentSecurityPolicyDirectiveNames.cpp; path = csp/ContentSecurityPolicyDirectiveNames.cpp; sourceTree = "<group>"; };
                CE5CB1B314EDAB6F00BB2795 /* EventSender.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EventSender.h; sourceTree = "<group>"; };
+               CE5FA253209E48C50051D700 /* ContentSecurityPolicyClient.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ContentSecurityPolicyClient.h; path = csp/ContentSecurityPolicyClient.h; sourceTree = "<group>"; };
                CE6D89294C7AACE0AD89B3DD /* MathMLMencloseElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MathMLMencloseElement.h; sourceTree = "<group>"; };
                CE6DADF71C591E6A003F6A88 /* ContentSecurityPolicyResponseHeaders.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ContentSecurityPolicyResponseHeaders.cpp; path = csp/ContentSecurityPolicyResponseHeaders.cpp; sourceTree = "<group>"; };
                CE6DADF81C591E6A003F6A88 /* ContentSecurityPolicyResponseHeaders.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ContentSecurityPolicyResponseHeaders.h; path = csp/ContentSecurityPolicyResponseHeaders.h; sourceTree = "<group>"; };
                CEF418CC1179678C009D112C /* ViewportArguments.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ViewportArguments.cpp; sourceTree = "<group>"; };
                CEF418CD1179678C009D112C /* ViewportArguments.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ViewportArguments.h; sourceTree = "<group>"; };
                CEF59B251CA0E11D005C3E13 /* ContentSecurityPolicyDirective.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ContentSecurityPolicyDirective.cpp; path = csp/ContentSecurityPolicyDirective.cpp; sourceTree = "<group>"; };
+               CEFD5DB2209EBED400788B67 /* ContentSecurityPolicyClient.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = ContentSecurityPolicyClient.cpp; path = csp/ContentSecurityPolicyClient.cpp; sourceTree = "<group>"; };
                D000EBA011BDAFD400C47726 /* FrameLoaderStateMachine.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FrameLoaderStateMachine.cpp; sourceTree = "<group>"; };
                D000EBA111BDAFD400C47726 /* FrameLoaderStateMachine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FrameLoaderStateMachine.h; sourceTree = "<group>"; };
                D000ED2511C1B9CD00C47726 /* SubframeLoader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SubframeLoader.cpp; sourceTree = "<group>"; };
                        children = (
                                97C471D912F925BC0086354B /* ContentSecurityPolicy.cpp */,
                                97C471DA12F925BD0086354B /* ContentSecurityPolicy.h */,
+                               CEFD5DB2209EBED400788B67 /* ContentSecurityPolicyClient.cpp */,
+                               CE5FA253209E48C50051D700 /* ContentSecurityPolicyClient.h */,
                                CEF59B251CA0E11D005C3E13 /* ContentSecurityPolicyDirective.cpp */,
                                CE799FA21C6A503A0097B518 /* ContentSecurityPolicyDirective.h */,
                                CE799F991C6A4BCD0097B518 /* ContentSecurityPolicyDirectiveList.cpp */,
                                A89943280B42338800D7C802 /* BitmapImage.h in Headers */,
                                976D6C79122B8A3D001FD1F7 /* Blob.h in Headers */,
                                976D6C7C122B8A3D001FD1F7 /* BlobBuilder.h in Headers */,
+                               CE5FA255209E48C50051D700 /* ContentSecurityPolicyClient.h in Headers */,
                                A15D75161E68F7C800A35FBC /* BlobCallback.h in Headers */,
                                2EDEF1F4121B0EFC00726DB2 /* BlobData.h in Headers */,
                                E1D31CDD19196020001005A3 /* BlobDataFileReference.h in Headers */,
index e41c8a3..d1bb4f3 100644 (file)
@@ -5500,7 +5500,7 @@ void Document::initSecurityContext()
         // This can occur via document.implementation.createDocument().
         setCookieURL(URL(ParsedURLString, emptyString()));
         setSecurityOriginPolicy(SecurityOriginPolicy::create(SecurityOrigin::createUnique()));
-        setContentSecurityPolicy(std::make_unique<ContentSecurityPolicy>(*this));
+        setContentSecurityPolicy(std::make_unique<ContentSecurityPolicy>(URL { ParsedURLString, emptyString() }, *this));
         return;
     }
 
@@ -5519,7 +5519,7 @@ void Document::initSecurityContext()
         isSecurityOriginUnique = documentLoader && documentLoader->response().tainting() == ResourceResponse::Tainting::Opaque;
 
     setSecurityOriginPolicy(SecurityOriginPolicy::create(isSecurityOriginUnique ? SecurityOrigin::createUnique() : SecurityOrigin::create(m_url)));
-    setContentSecurityPolicy(std::make_unique<ContentSecurityPolicy>(*this));
+    setContentSecurityPolicy(std::make_unique<ContentSecurityPolicy>(URL { m_url }, *this));
 
     String overrideContentSecurityPolicy = m_frame->loader().client().overrideContentSecurityPolicy();
     if (!overrideContentSecurityPolicy.isNull())
index c184bbd..954ba77 100644 (file)
@@ -64,6 +64,7 @@
 #include "MemoryCache.h"
 #include "NetworkLoadMetrics.h"
 #include "Page.h"
+#include "PingLoader.h"
 #include "PolicyChecker.h"
 #include "ProgressTracker.h"
 #include "ResourceHandle.h"
@@ -72,6 +73,7 @@
 #include "SchemeRegistry.h"
 #include "ScriptableDocumentParser.h"
 #include "SecurityPolicy.h"
+#include "SecurityPolicyViolationEvent.h"
 #include "ServiceWorker.h"
 #include "ServiceWorkerProvider.h"
 #include "Settings.h"
@@ -767,7 +769,7 @@ void DocumentLoader::responseReceived(const ResourceResponse& response, Completi
     
     auto url = response.url();
 
-    ContentSecurityPolicy contentSecurityPolicy(SecurityOrigin::create(url), m_frame);
+    ContentSecurityPolicy contentSecurityPolicy(URL { url }, this);
     contentSecurityPolicy.didReceiveHeaders(ContentSecurityPolicyResponseHeaders { response }, m_request.httpReferrer());
     if (!contentSecurityPolicy.allowFrameAncestors(*m_frame, url)) {
         stopLoadingAfterXFrameOptionsOrContentSecurityPolicyDenied(identifier, response);
@@ -2009,4 +2011,19 @@ PreviewConverter* DocumentLoader::previewConverter() const
 
 #endif
 
+void DocumentLoader::addConsoleMessage(MessageSource messageSource, MessageLevel messageLevel, const String& message, unsigned long requestIdentifier)
+{
+    static_cast<ScriptExecutionContext*>(m_frame->document())->addConsoleMessage(messageSource, messageLevel, message, requestIdentifier);
+}
+
+void DocumentLoader::sendCSPViolationReport(URL&& reportURL, Ref<FormData>&& report)
+{
+    PingLoader::sendViolationReport(*m_frame, WTFMove(reportURL), WTFMove(report), ViolationReportType::ContentSecurityPolicy);
+}
+
+void DocumentLoader::dispatchSecurityPolicyViolationEvent(Ref<SecurityPolicyViolationEvent>&& violationEvent)
+{
+    m_frame->document()->enqueueDocumentEvent(WTFMove(violationEvent));
+}
+
 } // namespace WebCore
index 18094ec..00f6dca 100644 (file)
@@ -31,6 +31,7 @@
 
 #include "CachedRawResourceClient.h"
 #include "CachedResourceHandle.h"
+#include "ContentSecurityPolicyClient.h"
 #include "DocumentWriter.h"
 #include "FrameDestructionObserver.h"
 #include "LinkIcon.h"
@@ -107,7 +108,11 @@ enum class PopUpPolicy {
     Block,
 };
 
-class DocumentLoader : public RefCounted<DocumentLoader>, public FrameDestructionObserver, private CachedRawResourceClient {
+class DocumentLoader
+    : public RefCounted<DocumentLoader>
+    , public FrameDestructionObserver
+    , public ContentSecurityPolicyClient
+    , private CachedRawResourceClient {
     WTF_MAKE_FAST_ALLOCATED;
     friend class ContentFilter;
 public:
@@ -404,6 +409,11 @@ private:
     void notifyFinishedLoadingApplicationManifest(uint64_t callbackIdentifier, std::optional<ApplicationManifest>);
 #endif
 
+    // ContentSecurityPolicyClient
+    WEBCORE_EXPORT void addConsoleMessage(MessageSource, MessageLevel, const String&, unsigned long requestIdentifier) final;
+    WEBCORE_EXPORT void sendCSPViolationReport(URL&&, Ref<FormData>&&) final;
+    WEBCORE_EXPORT void dispatchSecurityPolicyViolationEvent(Ref<SecurityPolicyViolationEvent>&&) final;
+
     Ref<CachedResourceLoader> m_cachedResourceLoader;
 
     CachedResourceHandle<CachedRawResource> m_mainResource;
index 330b6ef..c6f67de 100644 (file)
@@ -112,7 +112,7 @@ class WEBCORE_EXPORT FrameLoaderClient {
 public:
     // An inline function cannot be the first non-abstract virtual function declared
     // in the class as it results in the vtable being generated as a weak symbol.
-    // This hurts performance (in Mac OS X at least, when loadig frameworks), so we
+    // This hurts performance (in Mac OS X at least, when loading frameworks), so we
     // don't want to do it in WebKit.
     virtual bool hasHTMLView() const;
 
index d6f5dc9..e1d60eb 100644 (file)
@@ -116,7 +116,7 @@ WorkerThreadableLoader::MainThreadBridge::MainThreadBridge(ThreadableLoaderClien
     ASSERT(contentSecurityPolicy);
 
     auto securityOriginCopy = securityOrigin->isolatedCopy();
-    auto contentSecurityPolicyCopy = std::make_unique<ContentSecurityPolicy>(securityOriginCopy);
+    auto contentSecurityPolicyCopy = std::make_unique<ContentSecurityPolicy>(globalScope.url().isolatedCopy());
     contentSecurityPolicyCopy->copyStateFrom(contentSecurityPolicy);
     contentSecurityPolicyCopy->copyUpgradeInsecureRequestStateFrom(*contentSecurityPolicy);
 
index d152a20..8d910be 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2011 Google, Inc. All rights reserved.
- * Copyright (C) 2013-2017 Apple Inc. All rights reserved.
+ * Copyright (C) 2013-2018 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -27,6 +27,7 @@
 #include "config.h"
 #include "ContentSecurityPolicy.h"
 
+#include "ContentSecurityPolicyClient.h"
 #include "ContentSecurityPolicyDirective.h"
 #include "ContentSecurityPolicyDirectiveList.h"
 #include "ContentSecurityPolicyDirectiveNames.h"
@@ -88,19 +89,19 @@ static String consoleMessageForViolation(const char* effectiveViolatedDirective,
     return result.toString();
 }
 
-ContentSecurityPolicy::ContentSecurityPolicy(ScriptExecutionContext& scriptExecutionContext)
-    : m_scriptExecutionContext(&scriptExecutionContext)
-    , m_sandboxFlags(SandboxNone)
+ContentSecurityPolicy::ContentSecurityPolicy(URL&& protectedURL, ContentSecurityPolicyClient* client)
+    : m_client { client }
+    , m_protectedURL { WTFMove(protectedURL) }
 {
-    ASSERT(scriptExecutionContext.securityOrigin());
-    updateSourceSelf(*scriptExecutionContext.securityOrigin());
+    updateSourceSelf(SecurityOrigin::create(m_protectedURL).get());
 }
 
-ContentSecurityPolicy::ContentSecurityPolicy(const SecurityOrigin& securityOrigin, const Frame* frame)
-    : m_frame(frame)
-    , m_sandboxFlags(SandboxNone)
+ContentSecurityPolicy::ContentSecurityPolicy(URL&& protectedURL, ScriptExecutionContext& scriptExecutionContext)
+    : m_scriptExecutionContext(&scriptExecutionContext)
+    , m_protectedURL { WTFMove(protectedURL) }
 {
-    updateSourceSelf(securityOrigin);
+    ASSERT(scriptExecutionContext.securityOrigin());
+    updateSourceSelf(*scriptExecutionContext.securityOrigin());
 }
 
 ContentSecurityPolicy::~ContentSecurityPolicy() = default;
@@ -614,13 +615,13 @@ bool ContentSecurityPolicy::allowBaseURI(const URL& url, bool overrideContentSec
     return allPoliciesAllow(WTFMove(handleViolatedDirective), &ContentSecurityPolicyDirectiveList::violatedDirectiveForBaseURI, url);
 }
 
-static String stripURLForUseInReport(Document& document, const URL& url)
+String ContentSecurityPolicy::deprecatedURLForReporting(const URL& url) const
 {
     if (!url.isValid())
-        return String();
+        return { };
     if (!url.isHierarchical() || url.protocolIs("file"))
         return url.protocol().toString();
-    return document.securityOrigin().canRequest(url) ? url.strippedForUseAsReferrer() : SecurityOrigin::create(url).get().toString();
+    return static_cast<SecurityOriginData>(*m_selfSource).securityOrigin()->canRequest(url) ? url.strippedForUseAsReferrer() : SecurityOrigin::create(url)->toString();
 }
 
 void ContentSecurityPolicy::reportViolation(const String& violatedDirective, const ContentSecurityPolicyDirective& effectiveViolatedDirective, const URL& blockedURL, const String& consoleMessage, JSC::ExecState* state) const
@@ -648,48 +649,45 @@ void ContentSecurityPolicy::reportViolation(const String& effectiveViolatedDirec
         return;
 
     // FIXME: Support sending reports from worker.
-    if (!is<Document>(m_scriptExecutionContext) && !m_frame)
-        return;
-
-    ASSERT(!m_frame || effectiveViolatedDirective == ContentSecurityPolicyDirectiveNames::frameAncestors);
-
-    auto& document = is<Document>(m_scriptExecutionContext) ? downcast<Document>(*m_scriptExecutionContext) : *m_frame->document();
-    auto* frame = document.frame();
-    ASSERT(!m_frame || m_frame == frame);
-    if (!frame)
-        return;
-
-    String documentURI;
-    String blockedURI;
-    if (is<Document>(m_scriptExecutionContext)) {
-        documentURI = document.url().strippedForUseAsReferrer();
-        blockedURI = stripURLForUseInReport(document, blockedURL);
-    } else {
-        // The URL of |document| may not have been initialized (say, when reporting a frame-ancestors violation).
-        // So, we use the URL of the blocked document for the protected document URL.
-        documentURI = blockedURL;
-        blockedURI = blockedURL;
+    CSPInfo info;
+    info.documentURI = blockedURL;
+    if (m_client)
+        m_client->willSendCSPViolationReport(info);
+    else {
+        if (!is<Document>(m_scriptExecutionContext))
+            return;
+
+        auto& document = downcast<Document>(*m_scriptExecutionContext);
+        auto* frame = document.frame();
+        if (!frame)
+            return;
+
+        info.documentURI = document.url().strippedForUseAsReferrer();
+
+        auto stack = createScriptCallStack(JSMainThreadExecState::currentState(), 2);
+        auto* callFrame = stack->firstNonNativeCallFrame();
+        if (callFrame && callFrame->lineNumber()) {
+            info.sourceFile = deprecatedURLForReporting(URL { URL { }, callFrame->sourceURL() });
+            info.lineNumber = callFrame->lineNumber();
+            info.columnNumber = callFrame->columnNumber();
+        }
     }
-    String violatedDirectiveText = violatedDirective;
-    String originalPolicy = violatedDirectiveList.header();
+    ASSERT(m_client || is<Document>(m_scriptExecutionContext));
+
+    String blockedURI = deprecatedURLForReporting(blockedURL);
     // FIXME: Is it policy to not use the status code for HTTPS, or is that a bug?
-    unsigned short statusCode = m_selfSourceProtocol == "http" ? m_httpStatusCode : 0;
-
-    String sourceFile;
-    int lineNumber = 0;
-    int columnNumber = 0;
-    auto stack = createScriptCallStack(JSMainThreadExecState::currentState(), 2);
-    auto* callFrame = stack->firstNonNativeCallFrame();
-    if (callFrame && callFrame->lineNumber()) {
-        sourceFile = stripURLForUseInReport(document, URL(URL(), callFrame->sourceURL()));
-        lineNumber = callFrame->lineNumber();
-        columnNumber = callFrame->columnNumber();
-    }
+    unsigned short httpStatusCode = m_selfSourceProtocol == "http" ? m_httpStatusCode : 0;
 
     // 1. Dispatch violation event.
     bool canBubble = false;
     bool cancelable = false;
-    document.enqueueDocumentEvent(SecurityPolicyViolationEvent::create(eventNames().securitypolicyviolationEvent, canBubble, cancelable, documentURI, m_referrer, blockedURI, violatedDirectiveText, effectiveViolatedDirective, originalPolicy, sourceFile, statusCode, lineNumber, columnNumber));
+    auto violationEvent = SecurityPolicyViolationEvent::create(eventNames().securitypolicyviolationEvent, canBubble,
+        cancelable, info.documentURI, m_referrer, blockedURI, violatedDirective, effectiveViolatedDirective,
+        violatedDirectiveList.header(), info.sourceFile, httpStatusCode, info.lineNumber, info.columnNumber);
+    if (m_client)
+        m_client->dispatchSecurityPolicyViolationEvent(WTFMove(violationEvent));
+    else
+        downcast<Document>(*m_scriptExecutionContext).enqueueDocumentEvent(WTFMove(violationEvent));
 
     // 2. Send violation report (if applicable).
     auto& reportURIs = violatedDirectiveList.reportURIs();
@@ -707,25 +705,32 @@ void ContentSecurityPolicy::reportViolation(const String& effectiveViolatedDirec
     // harmless information.
 
     auto cspReport = JSON::Object::create();
-    cspReport->setString(ASCIILiteral("document-uri"), documentURI);
+    cspReport->setString(ASCIILiteral("document-uri"), info.documentURI);
     cspReport->setString(ASCIILiteral("referrer"), m_referrer);
-    cspReport->setString(ASCIILiteral("violated-directive"), violatedDirectiveText);
+    cspReport->setString(ASCIILiteral("violated-directive"), violatedDirective);
     cspReport->setString(ASCIILiteral("effective-directive"), effectiveViolatedDirective);
-    cspReport->setString(ASCIILiteral("original-policy"), originalPolicy);
+    cspReport->setString(ASCIILiteral("original-policy"), violatedDirectiveList.header());
     cspReport->setString(ASCIILiteral("blocked-uri"), blockedURI);
-    cspReport->setInteger(ASCIILiteral("status-code"), statusCode);
-    if (!sourceFile.isNull()) {
-        cspReport->setString(ASCIILiteral("source-file"), sourceFile);
-        cspReport->setInteger(ASCIILiteral("line-number"), lineNumber);
-        cspReport->setInteger(ASCIILiteral("column-number"), columnNumber);
+    cspReport->setInteger(ASCIILiteral("status-code"), httpStatusCode);
+    if (!info.sourceFile.isNull()) {
+        cspReport->setString(ASCIILiteral("source-file"), info.sourceFile);
+        cspReport->setInteger(ASCIILiteral("line-number"), info.lineNumber);
+        cspReport->setInteger(ASCIILiteral("column-number"), info.columnNumber);
     }
 
     auto reportObject = JSON::Object::create();
     reportObject->setObject(ASCIILiteral("csp-report"), WTFMove(cspReport));
 
     auto report = FormData::create(reportObject->toJSONString().utf8());
-    for (const auto& url : reportURIs)
-        PingLoader::sendViolationReport(*frame, is<Document>(m_scriptExecutionContext) ? document.completeURL(url) : document.completeURL(url, blockedURL), report.copyRef(), ViolationReportType::ContentSecurityPolicy);
+
+    if (m_client) {
+        for (const auto& url : reportURIs)
+            m_client->sendCSPViolationReport(URL { m_protectedURL, url }, report.copyRef());
+    } else {
+        auto& document = downcast<Document>(*m_scriptExecutionContext);
+        for (const auto& url : reportURIs)
+            PingLoader::sendViolationReport(*document.frame(), URL { m_protectedURL, url }, report.copyRef(), ViolationReportType::ContentSecurityPolicy);
+    }
 }
 
 void ContentSecurityPolicy::reportUnsupportedDirective(const String& name) const
@@ -817,10 +822,10 @@ void ContentSecurityPolicy::logToConsole(const String& message, const String& co
         return;
 
     // FIXME: <http://webkit.org/b/114317> ContentSecurityPolicy::logToConsole should include a column number
-    if (m_scriptExecutionContext)
+    if (m_client)
+        m_client->addConsoleMessage(MessageSource::Security, MessageLevel::Error, message, 0);
+    else if (m_scriptExecutionContext)
         m_scriptExecutionContext->addConsoleMessage(MessageSource::Security, MessageLevel::Error, message, contextURL, contextLine.oneBasedInt(), 0, state);
-    else if (m_frame && m_frame->document())
-        static_cast<ScriptExecutionContext*>(m_frame->document())->addConsoleMessage(MessageSource::Security, MessageLevel::Error, message, contextURL, contextLine.oneBasedInt(), 0, state);
 }
 
 void ContentSecurityPolicy::reportBlockedScriptExecutionToInspector(const String& directiveText) const
index 7d17980..543ec09 100644 (file)
 
 #include "ContentSecurityPolicyHash.h"
 #include "ContentSecurityPolicyResponseHeaders.h"
+#include "SecurityContext.h"
 #include "SecurityOrigin.h"
 #include "SecurityOriginHash.h"
 #include <functional>
 #include <wtf/HashSet.h>
-#include <wtf/OptionSet.h>
 #include <wtf/Vector.h>
 #include <wtf/text/TextPosition.h>
 
@@ -57,15 +57,15 @@ class ScriptExecutionContext;
 class SecurityOrigin;
 class TextEncoding;
 class URL;
+struct ContentSecurityPolicyClient;
 
 typedef Vector<std::unique_ptr<ContentSecurityPolicyDirectiveList>> CSPDirectiveListVector;
-typedef int SandboxFlags;
 
 class ContentSecurityPolicy {
     WTF_MAKE_FAST_ALLOCATED;
 public:
-    explicit ContentSecurityPolicy(ScriptExecutionContext&);
-    WEBCORE_EXPORT explicit ContentSecurityPolicy(const SecurityOrigin&, const Frame* = nullptr);
+    explicit ContentSecurityPolicy(URL&&, ScriptExecutionContext&);
+    WEBCORE_EXPORT explicit ContentSecurityPolicy(URL&&, ContentSecurityPolicyClient* = nullptr);
     WEBCORE_EXPORT ~ContentSecurityPolicy();
 
     void copyStateFrom(const ContentSecurityPolicy*);
@@ -173,6 +173,9 @@ private:
     void updateSourceSelf(const SecurityOrigin&);
     void applyPolicyToScriptExecutionContext();
 
+    // Implements the deprecated CSP2 "strip uri for reporting" algorithm from <https://www.w3.org/TR/CSP2/#violation-reports>.
+    String deprecatedURLForReporting(const URL&) const;
+
     const TextEncoding& documentEncoding() const;
 
     enum class Disposition {
@@ -203,16 +206,17 @@ private:
     void reportViolation(const String& effectiveViolatedDirective, const String& violatedDirective, const ContentSecurityPolicyDirectiveList& violatedDirectiveList, const URL& blockedURL, const String& consoleMessage, const String& sourceURL, const TextPosition& sourcePosition, JSC::ExecState*) const;
     void reportBlockedScriptExecutionToInspector(const String& directiveText) const;
 
-    // We can never have both a script execution context and a frame.
+    // We can never have both a script execution context and a ContentSecurityPolicyClient.
     ScriptExecutionContext* m_scriptExecutionContext { nullptr };
-    const Frame* m_frame { nullptr };
+    ContentSecurityPolicyClient* m_client { nullptr };
+    URL m_protectedURL;
     std::unique_ptr<ContentSecurityPolicySource> m_selfSource;
     String m_selfSourceProtocol;
     CSPDirectiveListVector m_policies;
     String m_lastPolicyEvalDisabledErrorMessage;
     String m_lastPolicyWebAssemblyDisabledErrorMessage;
     String m_referrer;
-    SandboxFlags m_sandboxFlags;
+    SandboxFlags m_sandboxFlags { SandboxNone };
     bool m_overrideInlineStyleAllowed { false };
     bool m_isReportingEnabled { true };
     bool m_upgradeInsecureRequests { false };
diff --git a/Source/WebCore/page/csp/ContentSecurityPolicyClient.cpp b/Source/WebCore/page/csp/ContentSecurityPolicyClient.cpp
new file mode 100644 (file)
index 0000000..259ad65
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2018 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "ContentSecurityPolicyClient.h"
+
+namespace WebCore {
+
+void ContentSecurityPolicyClient::willSendCSPViolationReport(CSPInfo&)
+{
+}
+
+} // namespace WebCore
+
diff --git a/Source/WebCore/page/csp/ContentSecurityPolicyClient.h b/Source/WebCore/page/csp/ContentSecurityPolicyClient.h
new file mode 100644 (file)
index 0000000..79fbbf2
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2018 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <JavaScriptCore/ConsoleTypes.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+class FormData;
+class SecurityPolicyViolationEvent;
+class URL;
+
+struct CSPInfo {
+    String documentURI;
+    String sourceFile;
+    int lineNumber { 0 };
+    int columnNumber { 0 };
+};
+
+struct WEBCORE_EXPORT ContentSecurityPolicyClient {
+    // An inline function cannot be the first non-abstract virtual function declared
+    // in the class as it results in the vtable being generated as a weak symbol.
+    // This hurts performance (in Mac OS X at least, when loading frameworks), so we
+    // don't want to do it in WebKit.
+    virtual void willSendCSPViolationReport(CSPInfo&);
+
+    virtual ~ContentSecurityPolicyClient() = default;
+
+    virtual void addConsoleMessage(MessageSource, MessageLevel, const String&, unsigned long requestIdentifier = 0) = 0;
+    virtual void sendCSPViolationReport(URL&&, Ref<FormData>&&) = 0;
+    virtual void dispatchSecurityPolicyViolationEvent(Ref<SecurityPolicyViolationEvent>&&) = 0;
+};
+
+} // namespace WebCore
index 7a4333d..bcac664 100644 (file)
@@ -28,6 +28,7 @@
 #include "ContentSecurityPolicySource.h"
 
 #include "ContentSecurityPolicy.h"
+#include "SecurityOriginData.h"
 #include "URL.h"
 
 namespace WebCore {
@@ -108,4 +109,9 @@ bool ContentSecurityPolicySource::isSchemeOnly() const
     return m_host.isEmpty();
 }
 
+ContentSecurityPolicySource::operator SecurityOriginData() const
+{
+    return { m_scheme, m_host, m_port };
+}
+
 } // namespace WebCore
index 28a1a68..56cf0dc 100644 (file)
@@ -32,6 +32,7 @@ namespace WebCore {
 
 class ContentSecurityPolicy;
 class URL;
+struct SecurityOriginData;
 
 class ContentSecurityPolicySource {
     WTF_MAKE_FAST_ALLOCATED;
@@ -40,6 +41,8 @@ public:
 
     bool matches(const URL&, bool didReceiveRedirectResponse = false) const;
 
+    operator SecurityOriginData() const;
+
 private:
     bool schemeMatches(const URL&) const;
     bool hostMatches(const URL&) const;
index eb2a7b6..f32ef2e 100644 (file)
@@ -82,7 +82,7 @@ WorkerGlobalScope::WorkerGlobalScope(const URL& url, Ref<SecurityOrigin>&& origi
         origin->grantStorageAccessFromFileURLsQuirk();
 
     setSecurityOriginPolicy(SecurityOriginPolicy::create(WTFMove(origin)));
-    setContentSecurityPolicy(std::make_unique<ContentSecurityPolicy>(*this));
+    setContentSecurityPolicy(std::make_unique<ContentSecurityPolicy>(URL { m_url }, *this));
 }
 
 WorkerGlobalScope::~WorkerGlobalScope()
index 846d9ba..faae3a8 100644 (file)
@@ -1,3 +1,24 @@
+2018-05-07  Daniel Bates  <dabates@apple.com>
+
+        Abstract logic to log console messages and send CSP violation reports into a client
+        https://bugs.webkit.org/show_bug.cgi?id=185393
+        <rdar://problem/40036053>
+
+        Reviewed by Brent Fulgham.
+
+        For now, build a URL from the source origin associated with the NetworkResourceLoader
+        and pass this to the ContentSecurityPolicy constructor.
+
+        Additionally, make NetworkLoadChecker::contentSecurityPolicy() non-const since it returns
+        a non-const pointer to a ContentSecurityPolicy object; => callers can mutate this object
+        right from under NetworkLoadChecker. Making this non-const makes this clear to a reader.
+        Also remove the mutable keyword from the definition of NetworkLoadChecker::m_contentSecurityPolicy.
+
+        * NetworkProcess/NetworkLoadChecker.cpp:
+        (WebKit::NetworkLoadChecker::contentSecurityPolicy):
+        (WebKit::NetworkLoadChecker::contentSecurityPolicy const): Deleted.
+        * NetworkProcess/NetworkLoadChecker.h:
+
 2018-05-07  Alex Christensen  <achristensen@webkit.org>
 
         WebResourceLoadStatisticsStore::requestStorageAccess should call its completion handler on the main thread
index 0190cd2..960731d 100644 (file)
@@ -311,10 +311,11 @@ bool NetworkLoadChecker::doesNotNeedCORSCheck(const URL& url) const
     return m_isSameOriginRequest;
 }
 
-ContentSecurityPolicy* NetworkLoadChecker::contentSecurityPolicy() const
+ContentSecurityPolicy* NetworkLoadChecker::contentSecurityPolicy()
 {
     if (!m_contentSecurityPolicy && m_cspResponseHeaders) {
-        m_contentSecurityPolicy = std::make_unique<ContentSecurityPolicy>(*m_origin);
+        // FIXME: Pass the URL of the protected resource instead of its origin.
+        m_contentSecurityPolicy = std::make_unique<ContentSecurityPolicy>(URL { URL { }, m_origin->toString() });
         m_contentSecurityPolicy->didReceiveHeaders(*m_cspResponseHeaders, String { m_referrer }, ContentSecurityPolicy::ReportParsingErrors::No);
     }
     return m_contentSecurityPolicy.get();
index 910cf98..9e4754a 100644 (file)
@@ -71,7 +71,7 @@ public:
 private:
     NetworkLoadChecker(WebCore::FetchOptions&&, PAL::SessionID, WebCore::HTTPHeaderMap&&, WebCore::URL&&, RefPtr<WebCore::SecurityOrigin>&&, WebCore::PreflightPolicy, String&& referrer);
 
-    WebCore::ContentSecurityPolicy* contentSecurityPolicy() const;
+    WebCore::ContentSecurityPolicy* contentSecurityPolicy();
     bool isChecking() const { return !!m_corsPreflightChecker; }
     bool isRedirected() const { return m_redirectCount; }
 
@@ -106,7 +106,7 @@ private:
     std::unique_ptr<NetworkCORSPreflightChecker> m_corsPreflightChecker;
     bool m_isSameOriginRequest { true };
     bool m_isSimpleRequest { true };
-    mutable std::unique_ptr<WebCore::ContentSecurityPolicy> m_contentSecurityPolicy;
+    std::unique_ptr<WebCore::ContentSecurityPolicy> m_contentSecurityPolicy;
     size_t m_redirectCount { 0 };
     WebCore::URL m_previousURL;
     WebCore::PreflightPolicy m_preflightPolicy;