ContentFilter should access DocumentLoader through an interface
authorachristensen@apple.com <achristensen@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 23 Jan 2020 18:50:55 +0000 (18:50 +0000)
committerachristensen@apple.com <achristensen@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 23 Jan 2020 18:50:55 +0000 (18:50 +0000)
https://bugs.webkit.org/show_bug.cgi?id=206564

Reviewed by Andy Estes.

This will make it easier to move, like to the NetworkProcess where there are no DocumentLoaders.
Also use WTF::Function instead of std::function and UniqueRef instead of std::unique_ptr.
No change in behavior.

* WebCore.xcodeproj/project.pbxproj:
* loader/ContentFilter.cpp:
(WebCore::ContentFilter::types):
(WebCore::ContentFilter::create):
(WebCore::ContentFilter::ContentFilter):
(WebCore::ContentFilter::continueAfterWillSendRequest):
(WebCore::ContentFilter::continueAfterResponseReceived):
(WebCore::ContentFilter::continueAfterDataReceived):
(WebCore::ContentFilter::continueAfterNotifyFinished):
(WebCore::ContentFilter::forEachContentFilterUntilBlocked):
(WebCore::ContentFilter::didDecide):
(WebCore::ContentFilter::deliverResourceData):
(WebCore::ContentFilter::handleProvisionalLoadFailure):
(): Deleted.
* loader/ContentFilter.h:
* loader/ContentFilterClient.h: Added.
(WebCore::ContentFilterClient::~ContentFilterClient):
* loader/DocumentLoader.cpp:
(WebCore::DocumentLoader::handleProvisionalLoadFailure):
(WebCore::DocumentLoader::didBlock):
* loader/DocumentLoader.h:
* platform/cocoa/NetworkExtensionContentFilter.h:
* platform/cocoa/NetworkExtensionContentFilter.mm:
(WebCore::NetworkExtensionContentFilter::create):
* platform/cocoa/ParentalControlsContentFilter.h:
* platform/cocoa/ParentalControlsContentFilter.mm:
(WebCore::ParentalControlsContentFilter::create):

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

14 files changed:
Source/WebCore/ChangeLog
Source/WebCore/Headers.cmake
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/loader/ContentFilter.cpp
Source/WebCore/loader/ContentFilter.h
Source/WebCore/loader/ContentFilterClient.h [new file with mode: 0644]
Source/WebCore/loader/DocumentLoader.cpp
Source/WebCore/loader/DocumentLoader.h
Source/WebCore/platform/cocoa/NetworkExtensionContentFilter.h
Source/WebCore/platform/cocoa/NetworkExtensionContentFilter.mm
Source/WebCore/platform/cocoa/ParentalControlsContentFilter.h
Source/WebCore/platform/cocoa/ParentalControlsContentFilter.mm
Source/WebCore/testing/MockContentFilter.cpp
Source/WebCore/testing/MockContentFilter.h

index 8afb25c..f746e1e 100644 (file)
@@ -1,3 +1,42 @@
+2020-01-23  Alex Christensen  <achristensen@webkit.org>
+
+        ContentFilter should access DocumentLoader through an interface
+        https://bugs.webkit.org/show_bug.cgi?id=206564
+
+        Reviewed by Andy Estes.
+
+        This will make it easier to move, like to the NetworkProcess where there are no DocumentLoaders.
+        Also use WTF::Function instead of std::function and UniqueRef instead of std::unique_ptr.
+        No change in behavior.
+
+        * WebCore.xcodeproj/project.pbxproj:
+        * loader/ContentFilter.cpp:
+        (WebCore::ContentFilter::types):
+        (WebCore::ContentFilter::create):
+        (WebCore::ContentFilter::ContentFilter):
+        (WebCore::ContentFilter::continueAfterWillSendRequest):
+        (WebCore::ContentFilter::continueAfterResponseReceived):
+        (WebCore::ContentFilter::continueAfterDataReceived):
+        (WebCore::ContentFilter::continueAfterNotifyFinished):
+        (WebCore::ContentFilter::forEachContentFilterUntilBlocked):
+        (WebCore::ContentFilter::didDecide):
+        (WebCore::ContentFilter::deliverResourceData):
+        (WebCore::ContentFilter::handleProvisionalLoadFailure):
+        (): Deleted.
+        * loader/ContentFilter.h:
+        * loader/ContentFilterClient.h: Added.
+        (WebCore::ContentFilterClient::~ContentFilterClient):
+        * loader/DocumentLoader.cpp:
+        (WebCore::DocumentLoader::handleProvisionalLoadFailure):
+        (WebCore::DocumentLoader::didBlock):
+        * loader/DocumentLoader.h:
+        * platform/cocoa/NetworkExtensionContentFilter.h:
+        * platform/cocoa/NetworkExtensionContentFilter.mm:
+        (WebCore::NetworkExtensionContentFilter::create):
+        * platform/cocoa/ParentalControlsContentFilter.h:
+        * platform/cocoa/ParentalControlsContentFilter.mm:
+        (WebCore::ParentalControlsContentFilter::create):
+
 2020-01-23  Zalan Bujtas  <zalan@apple.com>
 
         [LFC][IFC] Do not special case formatting root layout
index f24afa9..2cbd63f 100644 (file)
@@ -689,6 +689,7 @@ set(WebCore_PRIVATE_FRAMEWORK_HEADERS
 
     loader/AdClickAttribution.h
     loader/CanvasActivityRecord.h
+    loader/ContentFilterClient.h
     loader/CookieJar.h
     loader/CrossOriginAccessControl.h
     loader/CrossOriginPreflightResultCache.h
index c386f73..5ceed00 100644 (file)
                5CD9F5661AA0F73C00DA45FF /* DFABytecode.h in Headers */ = {isa = PBXBuildFile; fileRef = 5C39305D1AA0F6A90029C816 /* DFABytecode.h */; settings = {ATTRIBUTES = (Private, ); }; };
                5CD9F5671AA0F74200DA45FF /* DFABytecodeCompiler.h in Headers */ = {isa = PBXBuildFile; fileRef = 5C39305F1AA0F6A90029C816 /* DFABytecodeCompiler.h */; settings = {ATTRIBUTES = (Private, ); }; };
                5CD9F5681AA0F74600DA45FF /* DFABytecodeInterpreter.h in Headers */ = {isa = PBXBuildFile; fileRef = 5C3930611AA0F6A90029C816 /* DFABytecodeInterpreter.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               5CDCDDC623D80A1C00BA34A1 /* ContentFilterClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 5CDCDDBF23D7B7BE00BA34A1 /* ContentFilterClient.h */; settings = {ATTRIBUTES = (Private, ); }; };
                5CDD83641E4325A000621E92 /* LibWebRTCDataChannelHandler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5CDD833F1E43253D00621E92 /* LibWebRTCDataChannelHandler.cpp */; };
                5CDFA6C81AA4F2DA00EA8746 /* ContentExtensionActions.h in Headers */ = {isa = PBXBuildFile; fileRef = 5CDFA6C71AA4F2DA00EA8746 /* ContentExtensionActions.h */; settings = {ATTRIBUTES = (Private, ); }; };
                5CEEE4361F5F8F210014A5F5 /* RectEdges.h in Headers */ = {isa = PBXBuildFile; fileRef = 5C97A3361F5F7A6500105207 /* RectEdges.h */; settings = {ATTRIBUTES = (Private, ); }; };
                5CBC8DAB1AAA302200E1C803 /* MediaAccessibilitySoftLink.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MediaAccessibilitySoftLink.h; sourceTree = "<group>"; };
                5CCC270622D53B6800964FA0 /* AutofillElements.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AutofillElements.h; sourceTree = "<group>"; };
                5CCC270722D53B6900964FA0 /* AutofillElements.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AutofillElements.cpp; sourceTree = "<group>"; };
+               5CDCDDBF23D7B7BE00BA34A1 /* ContentFilterClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ContentFilterClient.h; sourceTree = "<group>"; };
                5CDD83391E4324BB00621E83 /* RealtimeIncomingVideoSourceCocoa.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = RealtimeIncomingVideoSourceCocoa.mm; sourceTree = "<group>"; };
                5CDD83391E4324BB00621E92 /* RealtimeIncomingVideoSource.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RealtimeIncomingVideoSource.cpp; sourceTree = "<group>"; };
                5CDD833A1E4324BB00621E83 /* RealtimeIncomingVideoSourceCocoa.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RealtimeIncomingVideoSourceCocoa.h; sourceTree = "<group>"; };
                                EFCC6C8D20FE914000A2321B /* CanvasActivityRecord.h */,
                                A149786C1ABAF33800CEF7E4 /* ContentFilter.cpp */,
                                A149786D1ABAF33800CEF7E4 /* ContentFilter.h */,
+                               5CDCDDBF23D7B7BE00BA34A1 /* ContentFilterClient.h */,
                                E1424C91164B52C800F32D40 /* CookieJar.cpp */,
                                E1424C92164B52C800F32D40 /* CookieJar.h */,
                                E1C416160F6563180092D2FB /* CrossOriginAccessControl.cpp */,
                                262391361A648CEE007251A3 /* ContentExtensionsDebugging.h in Headers */,
                                51FB67DC1AE6B82F00D06C5A /* ContentExtensionStyleSheet.h in Headers */,
                                A149786F1ABAF33800CEF7E4 /* ContentFilter.h in Headers */,
+                               5CDCDDC623D80A1C00BA34A1 /* ContentFilterClient.h in Headers */,
                                A14090FD1AA51E480091191A /* ContentFilterUnblockHandler.h in Headers */,
                                5C9C2DB52241A67B00996B0B /* ContentRuleListResults.h in Headers */,
                                97C471DC12F925BD0086354B /* ContentSecurityPolicy.h in Headers */,
index 6eafca3..383a592 100644 (file)
@@ -29,6 +29,7 @@
 #if ENABLE(CONTENT_FILTERING)
 
 #include "CachedRawResource.h"
+#include "ContentFilterClient.h"
 #include "ContentFilterUnblockHandler.h"
 #include "DocumentLoader.h"
 #include "Frame.h"
@@ -54,36 +55,35 @@ namespace WebCore {
 Vector<ContentFilter::Type>& ContentFilter::types()
 {
     static NeverDestroyed<Vector<ContentFilter::Type>> types {
-        Vector<ContentFilter::Type> {
+        Vector<ContentFilter::Type>::from(
 #if HAVE(PARENTAL_CONTROLS)
             type<ParentalControlsContentFilter>(),
 #endif
 #if HAVE(NETWORK_EXTENSION)
             type<NetworkExtensionContentFilter>()
 #endif
-        }
+        )
     };
     return types;
 }
 
-std::unique_ptr<ContentFilter> ContentFilter::create(DocumentLoader& documentLoader)
+std::unique_ptr<ContentFilter> ContentFilter::create(ContentFilterClient& client)
 {
     Container filters;
     for (auto& type : types()) {
         auto filter = type.create();
-        ASSERT(filter);
         filters.append(WTFMove(filter));
     }
 
     if (filters.isEmpty())
         return nullptr;
 
-    return makeUnique<ContentFilter>(WTFMove(filters), documentLoader);
+    return makeUnique<ContentFilter>(WTFMove(filters), client);
 }
 
-ContentFilter::ContentFilter(Container&& contentFilters, DocumentLoader& documentLoader)
-    : m_contentFilters { WTFMove(contentFilters) }
-    , m_documentLoader { documentLoader }
+ContentFilter::ContentFilter(Container&& contentFilters, ContentFilterClient& client)
+    : m_contentFilters(WTFMove(contentFilters))
+    , m_client(client)
 {
     LOG(ContentFiltering, "Creating ContentFilter with %zu platform content filter(s).\n", m_contentFilters.size());
     ASSERT(!m_contentFilters.isEmpty());
@@ -96,7 +96,7 @@ ContentFilter::~ContentFilter()
 
 bool ContentFilter::continueAfterWillSendRequest(ResourceRequest& request, const ResourceResponse& redirectResponse)
 {
-    Ref<DocumentLoader> protectedDocumentLoader { m_documentLoader };
+    Ref<ContentFilterClient> protectedClient { m_client };
 
     LOG(ContentFiltering, "ContentFilter received request for <%s> with redirect response from <%s>.\n", request.url().string().ascii().data(), redirectResponse.url().string().ascii().data());
 #if !LOG_DISABLED
@@ -135,7 +135,7 @@ void ContentFilter::stopFilteringMainResource()
 
 bool ContentFilter::continueAfterResponseReceived(const ResourceResponse& response)
 {
-    Ref<DocumentLoader> protectedDocumentLoader { m_documentLoader };
+    Ref<ContentFilterClient> protectedClient { m_client };
 
     if (m_state == State::Filtering) {
         LOG(ContentFiltering, "ContentFilter received response from <%s>.\n", response.url().string().ascii().data());
@@ -149,7 +149,7 @@ bool ContentFilter::continueAfterResponseReceived(const ResourceResponse& respon
 
 bool ContentFilter::continueAfterDataReceived(const char* data, int length)
 {
-    Ref<DocumentLoader> protectedDocumentLoader { m_documentLoader };
+    Ref<ContentFilterClient> protectedClient { m_client };
 
     if (m_state == State::Filtering) {
         LOG(ContentFiltering, "ContentFilter received %d bytes of data from <%s>.\n", length, m_mainResource->url().string().ascii().data());
@@ -168,7 +168,7 @@ bool ContentFilter::continueAfterDataReceived(const char* data, int length)
 bool ContentFilter::continueAfterNotifyFinished(CachedResource& resource)
 {
     ASSERT_UNUSED(resource, &resource == m_mainResource);
-    Ref<DocumentLoader> protectedDocumentLoader { m_documentLoader };
+    Ref<ContentFilterClient> protectedClient { m_client };
 
     if (m_mainResource->errorOccurred())
         return true;
@@ -201,11 +201,11 @@ inline void ContentFilter::forEachContentFilterUntilBlocked(Function&& function)
             continue;
         }
 
-        function(*contentFilter);
+        function(contentFilter.get());
 
         if (contentFilter->didBlockData()) {
             ASSERT(!m_blockingContentFilter);
-            m_blockingContentFilter = contentFilter.get();
+            m_blockingContentFilter = &contentFilter;
             didDecide(State::Blocked);
             return;
         } else if (contentFilter->needsMoreData())
@@ -226,20 +226,8 @@ void ContentFilter::didDecide(State state)
     if (m_state != State::Blocked)
         return;
 
-    ContentFilterUnblockHandler unblockHandler { m_blockingContentFilter->unblockHandler() };
-    unblockHandler.setUnreachableURL(m_documentLoader.documentURL());
-    auto frame { m_documentLoader.frame() };
-    String unblockRequestDeniedScript { m_blockingContentFilter->unblockRequestDeniedScript() };
-    if (!unblockRequestDeniedScript.isEmpty() && frame) {
-        unblockHandler.wrapWithDecisionHandler([scriptController = makeWeakPtr(frame->script()), script = unblockRequestDeniedScript.isolatedCopy()](bool unblocked) {
-            if (!unblocked && scriptController)
-                scriptController->executeScriptIgnoringException(script);
-        });
-    }
-    m_documentLoader.frameLoader()->client().contentFilterDidBlockLoad(WTFMove(unblockHandler));
-
-    m_blockedError = m_documentLoader.frameLoader()->blockedByContentFilterError(m_documentLoader.request());
-    m_documentLoader.cancelMainResourceLoad(m_blockedError);
+    m_blockedError = m_client.contentFilterDidBlock(m_blockingContentFilter->unblockHandler(), m_blockingContentFilter->unblockRequestDeniedScript());
+    m_client.cancelMainResourceLoadForContentFilter(m_blockedError);
 }
 
 void ContentFilter::deliverResourceData(CachedResource& resource)
@@ -247,7 +235,7 @@ void ContentFilter::deliverResourceData(CachedResource& resource)
     ASSERT(m_state == State::Allowed);
     ASSERT(resource.dataBufferingPolicy() == DataBufferingPolicy::BufferData);
     if (auto* resourceBuffer = resource.resourceBuffer())
-        m_documentLoader.dataReceived(resource, resourceBuffer->data(), resourceBuffer->size());
+        m_client.dataReceivedThroughContentFilter(resourceBuffer->data(), resourceBuffer->size());
 }
 
 static const URL& blockedPageURL()
@@ -294,7 +282,7 @@ void ContentFilter::handleProvisionalLoadFailure(const ResourceError& error)
     ResourceResponse response { URL(), "text/html"_s, static_cast<long long>(replacementData->size()), "UTF-8"_s };
     SubstituteData substituteData { WTFMove(replacementData), error.failingURL(), response, SubstituteData::SessionHistoryVisibility::Hidden };
     SetForScope<bool> loadingBlockedPage { m_isLoadingBlockedPage, true };
-    m_documentLoader.frameLoader()->load(FrameLoadRequest(*m_documentLoader.frame(), blockedPageURL(), ShouldOpenExternalURLsPolicy::ShouldNotAllow, substituteData));
+    m_client.handleProvisionalLoadFailureFromContentFilter(blockedPageURL(), substituteData);
 }
 
 } // namespace WebCore
index 81e87b3..b02a2a9 100644 (file)
 #include "ResourceError.h"
 #include <functional>
 #include <wtf/Forward.h>
+#include <wtf/UniqueRef.h>
 
 namespace WebCore {
 
 class CachedRawResource;
+class ContentFilterClient;
 class DocumentLoader;
 class ResourceRequest;
 class ResourceResponse;
@@ -48,7 +50,7 @@ class ContentFilter {
 public:
     template <typename T> static void addType() { types().append(type<T>()); }
 
-    static std::unique_ptr<ContentFilter> create(DocumentLoader&);
+    static std::unique_ptr<ContentFilter> create(ContentFilterClient&);
     ~ContentFilter();
 
     static const char* urlScheme() { return "x-apple-content-filter"; }
@@ -69,23 +71,23 @@ private:
     using State = PlatformContentFilter::State;
 
     struct Type {
-        const std::function<std::unique_ptr<PlatformContentFilter>()> create;
+        Function<UniqueRef<PlatformContentFilter>()> create;
     };
     template <typename T> static Type type();
     WEBCORE_EXPORT static Vector<Type>& types();
 
-    using Container = Vector<std::unique_ptr<PlatformContentFilter>>;
-    friend std::unique_ptr<ContentFilter> std::make_unique<ContentFilter>(Container&&, DocumentLoader&);
-    ContentFilter(Container&&, DocumentLoader&);
+    using Container = Vector<UniqueRef<PlatformContentFilter>>;
+    friend std::unique_ptr<ContentFilter> std::make_unique<ContentFilter>(Container&&, ContentFilterClient&);
+    ContentFilter(Container&&, ContentFilterClient&);
 
     template <typename Function> void forEachContentFilterUntilBlocked(Function&&);
     void didDecide(State);
     void deliverResourceData(CachedResource&);
 
-    const Container m_contentFilters;
-    DocumentLoader& m_documentLoader;
+    Container m_contentFilters;
+    ContentFilterClient& m_client;
     CachedResourceHandle<CachedRawResource> m_mainResource;
-    PlatformContentFilter* m_blockingContentFilter { nullptr };
+    const PlatformContentFilter* m_blockingContentFilter { nullptr };
     State m_state { State::Stopped };
     ResourceError m_blockedError;
     bool m_isLoadingBlockedPage { false };
diff --git a/Source/WebCore/loader/ContentFilterClient.h b/Source/WebCore/loader/ContentFilterClient.h
new file mode 100644 (file)
index 0000000..0472396
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2020 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. ``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
+ * 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
+
+#if ENABLE(CONTENT_FILTERING)
+
+#include <wtf/Forward.h>
+
+namespace WebCore {
+
+class ContentFilterUnblockHandler;
+class ResourceError;
+class SubstituteData;
+
+class ContentFilterClient {
+public:
+    virtual ~ContentFilterClient() = default;
+    virtual void ref() const = 0;
+    virtual void deref() const = 0;
+
+    virtual void dataReceivedThroughContentFilter(const char*, int) = 0;
+    virtual ResourceError contentFilterDidBlock(ContentFilterUnblockHandler, String&& unblockRequestDeniedScript) = 0;
+    virtual void cancelMainResourceLoadForContentFilter(const ResourceError&) = 0;
+    virtual void handleProvisionalLoadFailureFromContentFilter(const URL& blockedPageURL, SubstituteData&) = 0;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(CONTENT_FILTERING)
index 2ab2ef5..efd2735 100644 (file)
 
 #if ENABLE(CONTENT_FILTERING)
 #include "ContentFilter.h"
+#include "FrameLoadRequest.h"
+#include "ScriptController.h"
 #endif
 
 #if USE(QUICK_LOOK)
@@ -2186,4 +2188,34 @@ void DocumentLoader::enqueueSecurityPolicyViolationEvent(SecurityPolicyViolation
     m_frame->document()->enqueueSecurityPolicyViolationEvent(WTFMove(eventInit));
 }
 
+#if ENABLE(CONTENT_FILTERING)
+void DocumentLoader::dataReceivedThroughContentFilter(const char* data, int size)
+{
+    dataReceived(data, size);
+}
+
+void DocumentLoader::cancelMainResourceLoadForContentFilter(const ResourceError& error)
+{
+    cancelMainResourceLoad(error);
+}
+
+void DocumentLoader::handleProvisionalLoadFailureFromContentFilter(const URL& blockedPageURL, SubstituteData& substituteData)
+{
+    frameLoader()->load(FrameLoadRequest(*frame(), blockedPageURL, ShouldOpenExternalURLsPolicy::ShouldNotAllow, substituteData));
+}
+
+ResourceError DocumentLoader::contentFilterDidBlock(ContentFilterUnblockHandler unblockHandler, WTF::String&& unblockRequestDeniedScript)
+{
+    unblockHandler.setUnreachableURL(documentURL());
+    if (!unblockRequestDeniedScript.isEmpty() && frame()) {
+        unblockHandler.wrapWithDecisionHandler([scriptController = makeWeakPtr(frame()->script()), script = unblockRequestDeniedScript.isolatedCopy()](bool unblocked) {
+            if (!unblocked && scriptController)
+                scriptController->executeScriptIgnoringException(script);
+        });
+    }
+    frameLoader()->client().contentFilterDidBlockLoad(WTFMove(unblockHandler));
+    return frameLoader()->blockedByContentFilterError(request());
+}
+#endif // ENABLE(CONTENT_FILTERING)
+
 } // namespace WebCore
index 24c88ab..5bc523a 100644 (file)
@@ -31,6 +31,7 @@
 
 #include "CachedRawResourceClient.h"
 #include "CachedResourceHandle.h"
+#include "ContentFilterClient.h"
 #include "ContentSecurityPolicyClient.h"
 #include "DeviceOrientationOrMotionPermissionState.h"
 #include "DocumentIdentifier.h"
@@ -142,6 +143,9 @@ class DocumentLoader
     : public RefCounted<DocumentLoader>
     , public FrameDestructionObserver
     , public ContentSecurityPolicyClient
+#if ENABLE(CONTENT_FILTERING)
+    , public ContentFilterClient
+#endif
     , private CachedRawResourceClient {
     WTF_MAKE_FAST_ALLOCATED_WITH_HEAP_IDENTIFIER(DocumentLoader);
     friend class ContentFilter;
@@ -366,7 +370,9 @@ public:
     ShouldOpenExternalURLsPolicy shouldOpenExternalURLsPolicyToPropagate() const;
 
 #if ENABLE(CONTENT_FILTERING)
-    ContentFilter* contentFilter() const;
+    ContentFilter* contentFilter() const { return m_contentFilter.get(); }
+    void ref() const final { RefCounted<DocumentLoader>::ref(); }
+    void deref() const final { RefCounted<DocumentLoader>::deref(); }
 #endif
 
     bool isAlwaysOnLoggingAllowed() const;
@@ -444,6 +450,15 @@ private:
 #endif
 
     void responseReceived(const ResourceResponse&, CompletionHandler<void()>&&);
+
+#if ENABLE(CONTENT_FILTERING)
+    // ContentFilterClient
+    WEBCORE_EXPORT void dataReceivedThroughContentFilter(const char*, int) final;
+    WEBCORE_EXPORT ResourceError contentFilterDidBlock(ContentFilterUnblockHandler, String&& unblockRequestDeniedScript) final;
+    WEBCORE_EXPORT void cancelMainResourceLoadForContentFilter(const ResourceError&) final;
+    WEBCORE_EXPORT void handleProvisionalLoadFailureFromContentFilter(const URL& blockedPageURL, SubstituteData&) final;
+#endif
+
     void dataReceived(const char* data, int length);
 
     bool maybeLoadEmpty();
@@ -702,15 +717,6 @@ inline ApplicationCacheHost* DocumentLoader::applicationCacheHostUnlessBeingDest
     return m_applicationCacheHost.get();
 }
 
-#if ENABLE(CONTENT_FILTERING)
-
-inline ContentFilter* DocumentLoader::contentFilter() const
-{
-    return m_contentFilter.get();
-}
-
-#endif
-
 inline void DocumentLoader::didTellClientAboutLoad(const String& url)
 {
 #if !PLATFORM(COCOA)
index 369a90e..051a6c2 100644 (file)
@@ -30,6 +30,7 @@
 #include <wtf/Compiler.h>
 #include <wtf/OSObjectPtr.h>
 #include <wtf/RetainPtr.h>
+#include <wtf/UniqueRef.h>
 
 enum NEFilterSourceStatus : NSInteger;
 
@@ -39,10 +40,10 @@ OBJC_CLASS NSData;
 namespace WebCore {
 
 class NetworkExtensionContentFilter final : public PlatformContentFilter {
-    friend std::unique_ptr<NetworkExtensionContentFilter> std::make_unique<NetworkExtensionContentFilter>();
+    friend UniqueRef<NetworkExtensionContentFilter> WTF::makeUniqueRefWithoutFastMallocCheck<NetworkExtensionContentFilter>();
 
 public:
-    static std::unique_ptr<NetworkExtensionContentFilter> create();
+    static UniqueRef<NetworkExtensionContentFilter> create();
 
     void willSendRequest(ResourceRequest&, const ResourceResponse&) override;
     void responseReceived(const ResourceResponse&) override;
index 59e7724..661bd00 100644 (file)
@@ -71,9 +71,9 @@ bool NetworkExtensionContentFilter::enabled()
     return enabled;
 }
 
-std::unique_ptr<NetworkExtensionContentFilter> NetworkExtensionContentFilter::create()
+UniqueRef<NetworkExtensionContentFilter> NetworkExtensionContentFilter::create()
 {
-    return makeUnique<NetworkExtensionContentFilter>();
+    return makeUniqueRef<NetworkExtensionContentFilter>();
 }
 
 void NetworkExtensionContentFilter::initialize(const URL* url)
index 1b3685d..56a788c 100644 (file)
@@ -28,6 +28,7 @@
 #include "PlatformContentFilter.h"
 #include <wtf/Compiler.h>
 #include <wtf/RetainPtr.h>
+#include <wtf/UniqueRef.h>
 
 OBJC_CLASS NSData;
 OBJC_CLASS WebFilterEvaluator;
@@ -35,10 +36,10 @@ OBJC_CLASS WebFilterEvaluator;
 namespace WebCore {
 
 class ParentalControlsContentFilter final : public PlatformContentFilter {
-    friend std::unique_ptr<ParentalControlsContentFilter> std::make_unique<ParentalControlsContentFilter>();
+    friend UniqueRef<ParentalControlsContentFilter> WTF::makeUniqueRefWithoutFastMallocCheck<ParentalControlsContentFilter>();
 
 public:
-    static std::unique_ptr<ParentalControlsContentFilter> create();
+    static UniqueRef<ParentalControlsContentFilter> create();
 
     void willSendRequest(ResourceRequest&, const ResourceResponse&) override { }
     void responseReceived(const ResourceResponse&) override;
index 4c5baf8..ae8fb39 100644 (file)
@@ -67,9 +67,9 @@ bool ParentalControlsContentFilter::enabled()
     return enabled;
 }
 
-std::unique_ptr<ParentalControlsContentFilter> ParentalControlsContentFilter::create()
+UniqueRef<ParentalControlsContentFilter> ParentalControlsContentFilter::create()
 {
-    return makeUnique<ParentalControlsContentFilter>();
+    return makeUniqueRef<ParentalControlsContentFilter>();
 }
 
 static inline bool canHandleResponse(const ResourceResponse& response)
index 778a918..2c93cec 100644 (file)
@@ -62,9 +62,9 @@ bool MockContentFilter::enabled()
     return enabled;
 }
 
-std::unique_ptr<MockContentFilter> MockContentFilter::create()
+UniqueRef<MockContentFilter> MockContentFilter::create()
 {
-    return makeUnique<MockContentFilter>();
+    return makeUniqueRef<MockContentFilter>();
 }
 
 void MockContentFilter::willSendRequest(ResourceRequest& request, const ResourceResponse& redirectResponse)
index c99d2ae..8545f19 100644 (file)
 
 #include "MockContentFilterSettings.h"
 #include "PlatformContentFilter.h"
+#include <wtf/UniqueRef.h>
 
 namespace WebCore {
 
 class MockContentFilter final : public PlatformContentFilter {
-    friend std::unique_ptr<MockContentFilter> std::make_unique<MockContentFilter>();
+    friend UniqueRef<MockContentFilter> WTF::makeUniqueRefWithoutFastMallocCheck<MockContentFilter>();
 
 public:
     static void ensureInstalled();
-    static std::unique_ptr<MockContentFilter> create();
+    static UniqueRef<MockContentFilter> create();
 
     void willSendRequest(ResourceRequest&, const ResourceResponse&) override;
     void responseReceived(const ResourceResponse&) override;