Title: [290189] trunk/Source
Revision
290189
Author
pvol...@apple.com
Date
2022-02-18 17:02:27 -0800 (Fri, 18 Feb 2022)

Log Message

Move content filtering to Networking process
https://bugs.webkit.org/show_bug.cgi?id=233760
<rdar://problem/86150702>

Reviewed by Brent Fulgham.

Source/WebCore:

Remove content filtering from DocumentLoader when the feature is enabled, since this takes place in the WebContent process.
Modify the ContentFilter class by removing use of the types CachedResoure and CachedRawResource, since objects of these
types are not available in the Networking process. Parameters with these types are replaced with URL parameters.
The new behavior is behind a feature flag, which is not enabled in this patch.

* WebCore.xcodeproj/project.pbxproj:
* loader/ContentFilter.cpp:
(WebCore::ContentFilter::startFilteringMainResource):
(WebCore::ContentFilter::stopFilteringMainResource):
(WebCore::ContentFilter::continueAfterResponseReceived):
(WebCore::ContentFilter::continueAfterDataReceived):
(WebCore::ContentFilter::continueAfterNotifyFinished):
(WebCore::ContentFilter::didDecide):
(WebCore::ContentFilter::deliverResourceData):
(WebCore::ContentFilter::url):
(WebCore::ContentFilter::deliverStoredResourceData):
* loader/ContentFilter.h:
(WebCore::ContentFilter::blockedError const):
(WebCore::ContentFilter::isAllowed const):
(WebCore::ContentFilter::responseReceived const):
* loader/ContentFilterClient.h:
* loader/DocumentLoader.cpp:
(WebCore::DocumentLoader::notifyFinished):
(WebCore::DocumentLoader::willSendRequest):
(WebCore::DocumentLoader::responseReceived):
(WebCore::DocumentLoader::dataReceived):
(WebCore::DocumentLoader::detachFromFrame):
(WebCore::DocumentLoader::startLoadingMainResource):
(WebCore::DocumentLoader::clearMainResource):
(WebCore::DocumentLoader::becomeMainResourceClient):
(WebCore::DocumentLoader::contentFilterDidBlock):
(WebCore::DocumentLoader::handleContentFilterDidBlock):
(WebCore::DocumentLoader::handleContentFilterProvisionalLoadFailure):
(WebCore::DocumentLoader::contentFilterWillHandleProvisionalLoadFailure):
(WebCore::DocumentLoader::contentFilterHandleProvisionalLoadFailure):
* loader/DocumentLoader.h:
* loader/FrameLoader.cpp:
(WebCore::FrameLoader::dispatchDidFailProvisionalLoad):
* loader/PolicyChecker.cpp:
(WebCore::FrameLoader::PolicyChecker::checkNavigationPolicy):
* loader/SubstituteData.h:
(WebCore::SubstituteData::encode const):
(WebCore::SubstituteData::decode):
* platform/cocoa/ContentFilterUnblockHandlerCocoa.mm:
(WebCore::ContentFilterUnblockHandler::canHandleRequest const):

Source/WebKit:

Move content filtering from the DocumentLoader class in the WebProcess to the NetworkResourceLoader class in the
Networking process. The NetworkResourceLoader is now a client of the content filter, and will send messages
to the DocumentLoader in the WebProcess to cancel the load when the content filter decided to block the load.
If the content filter is providing replacement data, this will also be sent over IPC to the WebProcess.
Data is not being sent to the WebProcess until the content filter has decided to allow the load, if content
filtering is enabled.

* NetworkProcess/NetworkResourceLoader.cpp:
(WebKit::NetworkResourceLoader::start):
(WebKit::NetworkResourceLoader::startContentFiltering):
(WebKit::NetworkResourceLoader::didReceiveResponse):
(WebKit::NetworkResourceLoader::didFinishLoading):
(WebKit::NetworkResourceLoader::willSendRedirectedRequest):
(WebKit::NetworkResourceLoader::bufferingTimerFired):
(WebKit::NetworkResourceLoader::sendBuffer):
(WebKit::NetworkResourceLoader::didRetrieveCacheEntry):
(WebKit::NetworkResourceLoader::sendResultForCacheEntry):
(WebKit::NetworkResourceLoader::dataReceivedThroughContentFilter):
(WebKit::NetworkResourceLoader::contentFilterDidBlock):
(WebKit::NetworkResourceLoader::cancelMainResourceLoadForContentFilter):
(WebKit::NetworkResourceLoader::handleProvisionalLoadFailureFromContentFilter):
* NetworkProcess/NetworkResourceLoader.h:
* UIProcess/Network/NetworkProcessProxy.cpp:
(WebKit::NetworkProcessProxy::reloadAfterUnblockedContentFilter):
* UIProcess/Network/NetworkProcessProxy.h:
* UIProcess/Network/NetworkProcessProxy.messages.in:
* WebProcess/Network/WebResourceLoader.cpp:
(WebKit::WebResourceLoader::contentFilterDidBlockLoad):
(WebKit::WebResourceLoader::cancelMainResourceLoadForContentFilter):
(WebKit::WebResourceLoader::handleProvisionalLoadFailureFromContentFilter):
(WebKit::WebResourceLoader::reload):
* WebProcess/Network/WebResourceLoader.h:
* WebProcess/Network/WebResourceLoader.messages.in:

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (290188 => 290189)


--- trunk/Source/WebCore/ChangeLog	2022-02-19 00:57:42 UTC (rev 290188)
+++ trunk/Source/WebCore/ChangeLog	2022-02-19 01:02:27 UTC (rev 290189)
@@ -1,3 +1,57 @@
+2022-02-18  Per Arne Vollan  <pvol...@apple.com>
+
+        Move content filtering to Networking process
+        https://bugs.webkit.org/show_bug.cgi?id=233760
+        <rdar://problem/86150702>
+
+        Reviewed by Brent Fulgham.
+
+        Remove content filtering from DocumentLoader when the feature is enabled, since this takes place in the WebContent process.
+        Modify the ContentFilter class by removing use of the types CachedResoure and CachedRawResource, since objects of these
+        types are not available in the Networking process. Parameters with these types are replaced with URL parameters.
+        The new behavior is behind a feature flag, which is not enabled in this patch.
+
+        * WebCore.xcodeproj/project.pbxproj:
+        * loader/ContentFilter.cpp:
+        (WebCore::ContentFilter::startFilteringMainResource):
+        (WebCore::ContentFilter::stopFilteringMainResource):
+        (WebCore::ContentFilter::continueAfterResponseReceived):
+        (WebCore::ContentFilter::continueAfterDataReceived):
+        (WebCore::ContentFilter::continueAfterNotifyFinished):
+        (WebCore::ContentFilter::didDecide):
+        (WebCore::ContentFilter::deliverResourceData):
+        (WebCore::ContentFilter::url):
+        (WebCore::ContentFilter::deliverStoredResourceData):
+        * loader/ContentFilter.h:
+        (WebCore::ContentFilter::blockedError const):
+        (WebCore::ContentFilter::isAllowed const):
+        (WebCore::ContentFilter::responseReceived const):
+        * loader/ContentFilterClient.h:
+        * loader/DocumentLoader.cpp:
+        (WebCore::DocumentLoader::notifyFinished):
+        (WebCore::DocumentLoader::willSendRequest):
+        (WebCore::DocumentLoader::responseReceived):
+        (WebCore::DocumentLoader::dataReceived):
+        (WebCore::DocumentLoader::detachFromFrame):
+        (WebCore::DocumentLoader::startLoadingMainResource):
+        (WebCore::DocumentLoader::clearMainResource):
+        (WebCore::DocumentLoader::becomeMainResourceClient):
+        (WebCore::DocumentLoader::contentFilterDidBlock):
+        (WebCore::DocumentLoader::handleContentFilterDidBlock):
+        (WebCore::DocumentLoader::handleContentFilterProvisionalLoadFailure):
+        (WebCore::DocumentLoader::contentFilterWillHandleProvisionalLoadFailure):
+        (WebCore::DocumentLoader::contentFilterHandleProvisionalLoadFailure):
+        * loader/DocumentLoader.h:
+        * loader/FrameLoader.cpp:
+        (WebCore::FrameLoader::dispatchDidFailProvisionalLoad):
+        * loader/PolicyChecker.cpp:
+        (WebCore::FrameLoader::PolicyChecker::checkNavigationPolicy):
+        * loader/SubstituteData.h:
+        (WebCore::SubstituteData::encode const):
+        (WebCore::SubstituteData::decode):
+        * platform/cocoa/ContentFilterUnblockHandlerCocoa.mm:
+        (WebCore::ContentFilterUnblockHandler::canHandleRequest const):
+
 2022-02-18  Mark Lam  <mark....@apple.com>
 
         Provide a WebCore subspaceImplFor template to make code more readable.

Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (290188 => 290189)


--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2022-02-19 00:57:42 UTC (rev 290188)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2022-02-19 01:02:27 UTC (rev 290189)
@@ -3368,7 +3368,7 @@
 		A14832CC187F67C400DA63A6 /* WebCoreThreadRun.h in Headers */ = {isa = PBXBuildFile; fileRef = A148329E187F508700DA63A6 /* WebCoreThreadRun.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		A14832CF187F684700DA63A6 /* WebCoreThreadSystemInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = A14832A1187F508700DA63A6 /* WebCoreThreadSystemInterface.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		A1491DA31F859D870095F5D4 /* PaymentSession.h in Headers */ = {isa = PBXBuildFile; fileRef = A1491DA21F859D870095F5D4 /* PaymentSession.h */; };
-		A149786F1ABAF33800CEF7E4 /* ContentFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = A149786D1ABAF33800CEF7E4 /* ContentFilter.h */; };
+		A149786F1ABAF33800CEF7E4 /* ContentFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = A149786D1ABAF33800CEF7E4 /* ContentFilter.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		A14978711ABAF3A500CEF7E4 /* PlatformContentFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = A14978701ABAF3A500CEF7E4 /* PlatformContentFilter.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		A14BB0A01F9813B800605A35 /* MockPayment.h in Headers */ = {isa = PBXBuildFile; fileRef = A14BB09E1F9813B800605A35 /* MockPayment.h */; };
 		A15D75161E68F7C800A35FBC /* BlobCallback.h in Headers */ = {isa = PBXBuildFile; fileRef = A15D75131E68F7B100A35FBC /* BlobCallback.h */; };

Modified: trunk/Source/WebCore/loader/ContentFilter.cpp (290188 => 290189)


--- trunk/Source/WebCore/loader/ContentFilter.cpp	2022-02-19 00:57:42 UTC (rev 290188)
+++ trunk/Source/WebCore/loader/ContentFilter.cpp	2022-02-19 01:02:27 UTC (rev 290189)
@@ -113,22 +113,39 @@
     return !request.isNull();
 }
 
+#if ENABLE(CONTENT_FILTERING_IN_NETWORKING_PROCESS)
+void ContentFilter::startFilteringMainResource(const URL& url)
+{
+    if (m_state != State::Stopped)
+        return;
+
+    LOG(ContentFiltering, "ContentFilter will start filtering main resource at <%{sensitive}s>.\n", url.string().ascii().data());
+    m_state = State::Filtering;
+    ASSERT(m_mainResourceURL.isEmpty());
+    m_mainResourceURL = url;
+}
+#else
 void ContentFilter::startFilteringMainResource(CachedRawResource& resource)
 {
     if (m_state != State::Stopped)
         return;
 
-    LOG(ContentFiltering, "ContentFilter will start filtering main resource at <%s>.\n", resource.url().string().ascii().data());
+    LOG(ContentFiltering, "ContentFilter will start filtering main resource at <%{sensitive}s>.\n", resource.url().string().ascii().data());
     m_state = State::Filtering;
     ASSERT(!m_mainResource);
     m_mainResource = &resource;
 }
+#endif
 
 void ContentFilter::stopFilteringMainResource()
 {
     if (m_state != State::Blocked)
         m_state = State::Stopped;
+#if ENABLE(CONTENT_FILTERING_IN_NETWORKING_PROCESS)
+    m_mainResourceURL = URL();
+#else
     m_mainResource = nullptr;
+#endif
 }
 
 bool ContentFilter::continueAfterResponseReceived(const ResourceResponse& response)
@@ -142,21 +159,38 @@
         });
     }
 
+    m_responseReceived = true;
+
     return m_state != State::Blocked;
 }
 
+#if ENABLE(CONTENT_FILTERING_IN_NETWORKING_PROCESS)
+bool ContentFilter::continueAfterDataReceived(const SharedBuffer& data, size_t encodedDataLength)
+#else
 bool ContentFilter::continueAfterDataReceived(const SharedBuffer& data)
+#endif
 {
     Ref<ContentFilterClient> protectedClient { m_client };
 
     if (m_state == State::Filtering) {
-        LOG(ContentFiltering, "ContentFilter received %zu bytes of data from <%s>.\n", data.size(), m_mainResource->url().string().ascii().data());
+        LOG(ContentFiltering, "ContentFilter received %zu bytes of data from <%{sensitive}s>.\n", data.size(), url().string().ascii().data());
+
         forEachContentFilterUntilBlocked([data = "" { data }](auto& contentFilter) {
             contentFilter.addData(data);
         });
-
-        if (m_state == State::Allowed)
-            deliverResourceData(*m_mainResource);
+#if ENABLE(CONTENT_FILTERING_IN_NETWORKING_PROCESS)
+        if (m_state == State::Allowed) {
+            deliverStoredResourceData();
+            deliverResourceData(data, encodedDataLength);
+        } else
+            m_buffers.append(ResourceDataItem { RefPtr { &data }, encodedDataLength });
+#else
+        if (m_state == State::Allowed) {
+            ASSERT(m_mainResource->dataBufferingPolicy() == DataBufferingPolicy::BufferData);
+            if (auto* buffer = m_mainResource->resourceBuffer())
+                deliverResourceData(buffer->makeContiguous());
+        }
+#endif
         return false;
     }
 
@@ -163,16 +197,23 @@
     return m_state != State::Blocked;
 }
 
+#if ENABLE(CONTENT_FILTERING_IN_NETWORKING_PROCESS)
+bool ContentFilter::continueAfterNotifyFinished(const URL& resourceURL)
+#else
 bool ContentFilter::continueAfterNotifyFinished(CachedResource& resource)
+#endif
 {
+    Ref<ContentFilterClient> protectedClient { m_client };
+#if ENABLE(CONTENT_FILTERING_IN_NETWORKING_PROCESS)
+    ASSERT_UNUSED(resourceURL, resourceURL == m_mainResourceURL);
+#else
     ASSERT_UNUSED(resource, &resource == m_mainResource);
-    Ref<ContentFilterClient> protectedClient { m_client };
-
     if (m_mainResource->errorOccurred())
         return true;
+#endif
 
     if (m_state == State::Filtering) {
-        LOG(ContentFiltering, "ContentFilter will finish filtering main resource at <%s>.\n", m_mainResource->url().string().ascii().data());
+        LOG(ContentFiltering, "ContentFilter will finish filtering main resource at <%{sensitive}s>.\n", url().string().ascii().data());
         forEachContentFilterUntilBlocked([](PlatformContentFilter& contentFilter) {
             contentFilter.finishedAddingData();
         });
@@ -179,7 +220,14 @@
 
         if (m_state != State::Blocked) {
             m_state = State::Allowed;
-            deliverResourceData(*m_mainResource);
+#if ENABLE(CONTENT_FILTERING_IN_NETWORKING_PROCESS)
+            deliverStoredResourceData();
+#else
+            if (auto* buffer = m_mainResource->resourceBuffer()) {
+                ASSERT(m_mainResource->dataBufferingPolicy() == DataBufferingPolicy::BufferData);
+                deliverResourceData(buffer->makeContiguous());
+            }
+#endif
         }
 
         if (m_state == State::Stopped)
@@ -219,7 +267,9 @@
     ASSERT(m_state != State::Allowed);
     ASSERT(m_state != State::Blocked);
     ASSERT(state == State::Allowed || state == State::Blocked);
-    LOG(ContentFiltering, "ContentFilter decided load should be %s for main resource at <%s>.\n", state == State::Allowed ? "allowed" : "blocked", m_mainResource ? m_mainResource->url().string().ascii().data() : "");
+#if !LOG_DISABLED
+    LOG(ContentFiltering, "ContentFilter decided load should be %s for main resource at <%{sensitive}s>.\n", state == State::Allowed ? "allowed" : "blocked", url().string().ascii().data());
+#endif // !LOG_DISABLED
     m_state = state;
     if (m_state != State::Blocked)
         return;
@@ -228,14 +278,28 @@
     m_client.cancelMainResourceLoadForContentFilter(m_blockedError);
 }
 
-void ContentFilter::deliverResourceData(CachedResource& resource)
+void ContentFilter::deliverResourceData(const SharedBuffer& buffer, size_t encodedDataLength)
 {
     ASSERT(m_state == State::Allowed);
-    ASSERT(resource.dataBufferingPolicy() == DataBufferingPolicy::BufferData);
-    if (auto* resourceBuffer = resource.resourceBuffer())
-        m_client.dataReceivedThroughContentFilter(resourceBuffer->makeContiguous());
+#if ENABLE(CONTENT_FILTERING_IN_NETWORKING_PROCESS)
+    m_client.dataReceivedThroughContentFilter(buffer, encodedDataLength);
+#else
+    UNUSED_PARAM(encodedDataLength);
+    m_client.dataReceivedThroughContentFilter(buffer);
+#endif
 }
 
+URL ContentFilter::url()
+{
+#if ENABLE(CONTENT_FILTERING_IN_NETWORKING_PROCESS)
+    return m_mainResourceURL;
+#else
+    if (m_mainResource)
+        return m_mainResource->url();
+    return URL();
+#endif
+}
+
 static const URL& blockedPageURL()
 {
     static NeverDestroyed blockedPageURL = [] () -> URL {
@@ -245,6 +309,7 @@
     return blockedPageURL;
 }
 
+#if !ENABLE(CONTENT_FILTERING_IN_NETWORKING_PROCESS)
 bool ContentFilter::continueAfterSubstituteDataRequest(const DocumentLoader& activeLoader, const SubstituteData& substituteData)
 {
     if (auto contentFilter = activeLoader.contentFilter()) {
@@ -259,6 +324,7 @@
 
     return true;
 }
+#endif
 
 bool ContentFilter::willHandleProvisionalLoadFailure(const ResourceError& error) const
 {
@@ -283,6 +349,15 @@
     m_client.handleProvisionalLoadFailureFromContentFilter(blockedPageURL(), substituteData);
 }
 
+#if ENABLE(CONTENT_FILTERING_IN_NETWORKING_PROCESS)
+void ContentFilter::deliverStoredResourceData()
+{
+    for (auto& buffer : m_buffers)
+        deliverResourceData(*buffer.buffer, buffer.encodedDataLength);
+    m_buffers.clear();
+}
+#endif
+
 } // namespace WebCore
 
 #endif // ENABLE(CONTENT_FILTERING)

Modified: trunk/Source/WebCore/loader/ContentFilter.h (290188 => 290189)


--- trunk/Source/WebCore/loader/ContentFilter.h	2022-02-19 00:57:42 UTC (rev 290188)
+++ trunk/Source/WebCore/loader/ContentFilter.h	2022-02-19 01:02:27 UTC (rev 290189)
@@ -50,23 +50,36 @@
 public:
     template <typename T> static void addType() { types().append(type<T>()); }
 
-    static std::unique_ptr<ContentFilter> create(ContentFilterClient&);
-    ~ContentFilter();
+    WEBCORE_EXPORT static std::unique_ptr<ContentFilter> create(ContentFilterClient&);
+    WEBCORE_EXPORT ~ContentFilter();
 
     static const char* urlScheme() { return "x-apple-content-filter"; }
 
+#if ENABLE(CONTENT_FILTERING_IN_NETWORKING_PROCESS)
+    WEBCORE_EXPORT void startFilteringMainResource(const URL&);
+#else
     void startFilteringMainResource(CachedRawResource&);
-    void stopFilteringMainResource();
+#endif
+    WEBCORE_EXPORT void stopFilteringMainResource();
 
-    bool continueAfterWillSendRequest(ResourceRequest&, const ResourceResponse&);
-    bool continueAfterResponseReceived(const ResourceResponse&);
+    WEBCORE_EXPORT bool continueAfterWillSendRequest(ResourceRequest&, const ResourceResponse&);
+    WEBCORE_EXPORT bool continueAfterResponseReceived(const ResourceResponse&);
+#if ENABLE(CONTENT_FILTERING_IN_NETWORKING_PROCESS)
+    WEBCORE_EXPORT bool continueAfterDataReceived(const SharedBuffer&, size_t encodedDataLength);
+    WEBCORE_EXPORT bool continueAfterNotifyFinished(const URL& resourceURL);
+#else
     bool continueAfterDataReceived(const SharedBuffer&);
     bool continueAfterNotifyFinished(CachedResource&);
+#endif
 
     static bool continueAfterSubstituteDataRequest(const DocumentLoader& activeLoader, const SubstituteData&);
     bool willHandleProvisionalLoadFailure(const ResourceError&) const;
-    void handleProvisionalLoadFailure(const ResourceError&);
+    WEBCORE_EXPORT void handleProvisionalLoadFailure(const ResourceError&);
 
+    const ResourceError& blockedError() const { return m_blockedError; }
+    bool isAllowed() const { return m_state == State::Allowed; }
+    bool responseReceived() const { return m_responseReceived; }
+    
 private:
     using State = PlatformContentFilter::State;
 
@@ -82,15 +95,31 @@
 
     template <typename Function> void forEachContentFilterUntilBlocked(Function&&);
     void didDecide(State);
-    void deliverResourceData(CachedResource&);
-
+    void deliverResourceData(const SharedBuffer&, size_t encodedDataLength = 0);
+#if ENABLE(CONTENT_FILTERING_IN_NETWORKING_PROCESS)
+    void deliverStoredResourceData();
+#endif
+    
+    URL url();
+    
     Container m_contentFilters;
     ContentFilterClient& m_client;
+#if ENABLE(CONTENT_FILTERING_IN_NETWORKING_PROCESS)
+    URL m_mainResourceURL;
+    struct ResourceDataItem {
+        RefPtr<const SharedBuffer> buffer;
+        size_t encodedDataLength;
+    };
+    
+    Vector<ResourceDataItem> m_buffers;
+#else
     CachedResourceHandle<CachedRawResource> m_mainResource;
+#endif
     const PlatformContentFilter* m_blockingContentFilter { nullptr };
     State m_state { State::Stopped };
     ResourceError m_blockedError;
     bool m_isLoadingBlockedPage { false };
+    bool m_responseReceived { false };
 };
 
 template <typename T>

Modified: trunk/Source/WebCore/loader/ContentFilterClient.h (290188 => 290189)


--- trunk/Source/WebCore/loader/ContentFilterClient.h	2022-02-19 00:57:42 UTC (rev 290188)
+++ trunk/Source/WebCore/loader/ContentFilterClient.h	2022-02-19 01:02:27 UTC (rev 290189)
@@ -42,7 +42,11 @@
     virtual void ref() const = 0;
     virtual void deref() const = 0;
 
+#if ENABLE(CONTENT_FILTERING_IN_NETWORKING_PROCESS)
+    virtual void dataReceivedThroughContentFilter(const SharedBuffer&, size_t) = 0;
+#else
     virtual void dataReceivedThroughContentFilter(const SharedBuffer&) = 0;
+#endif
     virtual ResourceError contentFilterDidBlock(ContentFilterUnblockHandler, String&& unblockRequestDeniedScript) = 0;
     virtual void cancelMainResourceLoadForContentFilter(const ResourceError&) = 0;
     virtual void handleProvisionalLoadFailureFromContentFilter(const URL& blockedPageURL, SubstituteData&) = 0;

Modified: trunk/Source/WebCore/loader/DocumentLoader.cpp (290188 => 290189)


--- trunk/Source/WebCore/loader/DocumentLoader.cpp	2022-02-19 00:57:42 UTC (rev 290188)
+++ trunk/Source/WebCore/loader/DocumentLoader.cpp	2022-02-19 01:02:27 UTC (rev 290189)
@@ -419,7 +419,7 @@
 void DocumentLoader::notifyFinished(CachedResource& resource, const NetworkLoadMetrics& metrics)
 {
     ASSERT(isMainThread());
-#if ENABLE(CONTENT_FILTERING)
+#if ENABLE(CONTENT_FILTERING) && !ENABLE(CONTENT_FILTERING_IN_NETWORKING_PROCESS)
     if (m_contentFilter && !m_contentFilter->continueAfterNotifyFinished(resource))
         return;
 #endif
@@ -710,7 +710,7 @@
         newRequest.setURL(WTFMove(url));
     }
 
-#if ENABLE(CONTENT_FILTERING)
+#if ENABLE(CONTENT_FILTERING) && !ENABLE(CONTENT_FILTERING_IN_NETWORKING_PROCESS)
     if (m_contentFilter && !m_contentFilter->continueAfterWillSendRequest(newRequest, redirectResponse))
         return completionHandler(WTFMove(newRequest));
 #endif
@@ -902,7 +902,7 @@
     ASSERT(response.certificateInfo());
     CompletionHandlerCallingScope completionHandlerCaller(WTFMove(completionHandler));
 
-#if ENABLE(CONTENT_FILTERING)
+#if ENABLE(CONTENT_FILTERING) && !ENABLE(CONTENT_FILTERING_IN_NETWORKING_PROCESS)
     if (m_contentFilter && !m_contentFilter->continueAfterResponseReceived(response))
         return;
 #endif
@@ -1322,7 +1322,7 @@
 
 void DocumentLoader::dataReceived(const SharedBuffer& buffer)
 {
-#if ENABLE(CONTENT_FILTERING)
+#if ENABLE(CONTENT_FILTERING) && !ENABLE(CONTENT_FILTERING_IN_NETWORKING_PROCESS)
     if (m_contentFilter && !m_contentFilter->continueAfterDataReceived(buffer))
         return;
 #endif
@@ -1463,7 +1463,7 @@
     stopLoading();
     if (m_mainResource && m_mainResource->hasClient(*this))
         m_mainResource->removeClient(*this);
-#if ENABLE(CONTENT_FILTERING)
+#if ENABLE(CONTENT_FILTERING) && !ENABLE(CONTENT_FILTERING_IN_NETWORKING_PROCESS)
     if (m_contentFilter)
         m_contentFilter->stopFilteringMainResource();
 #endif
@@ -2025,7 +2025,7 @@
         return;
     }
 
-#if ENABLE(CONTENT_FILTERING)
+#if ENABLE(CONTENT_FILTERING) && !ENABLE(CONTENT_FILTERING_IN_NETWORKING_PROCESS)
     m_contentFilter = !m_substituteData.isValid() ? ContentFilter::create(*this) : nullptr;
 #endif
 
@@ -2230,7 +2230,7 @@
     ASSERT(isMainThread());
     if (m_mainResource && m_mainResource->hasClient(*this))
         m_mainResource->removeClient(*this);
-#if ENABLE(CONTENT_FILTERING)
+#if ENABLE(CONTENT_FILTERING) && !ENABLE(CONTENT_FILTERING_IN_NETWORKING_PROCESS)
     if (m_contentFilter)
         m_contentFilter->stopFilteringMainResource();
 #endif
@@ -2357,7 +2357,7 @@
 
 void DocumentLoader::becomeMainResourceClient()
 {
-#if ENABLE(CONTENT_FILTERING)
+#if ENABLE(CONTENT_FILTERING) && !ENABLE(CONTENT_FILTERING_IN_NETWORKING_PROCESS)
     if (m_contentFilter)
         m_contentFilter->startFilteringMainResource(*m_mainResource);
 #endif
@@ -2414,7 +2414,7 @@
     m_frame->document()->enqueueSecurityPolicyViolationEvent(WTFMove(eventInit));
 }
 
-#if ENABLE(CONTENT_FILTERING)
+#if ENABLE(CONTENT_FILTERING) && !ENABLE(CONTENT_FILTERING_IN_NETWORKING_PROCESS)
 void DocumentLoader::dataReceivedThroughContentFilter(const SharedBuffer& buffer)
 {
     dataReceived(buffer);
@@ -2425,12 +2425,19 @@
     cancelMainResourceLoad(error);
 }
 
+ResourceError DocumentLoader::contentFilterDidBlock(ContentFilterUnblockHandler unblockHandler, String&& unblockRequestDeniedScript)
+{
+    return handleContentFilterDidBlock(unblockHandler, WTFMove(unblockRequestDeniedScript));
+}
+
 void DocumentLoader::handleProvisionalLoadFailureFromContentFilter(const URL& blockedPageURL, SubstituteData& substituteData)
 {
     frameLoader()->load(FrameLoadRequest(*frame(), blockedPageURL, substituteData));
 }
+#endif // ENABLE(CONTENT_FILTERING) && !ENABLE(CONTENT_FILTERING_IN_NETWORKING_PROCESS)
 
-ResourceError DocumentLoader::contentFilterDidBlock(ContentFilterUnblockHandler unblockHandler, String&& unblockRequestDeniedScript)
+#if ENABLE(CONTENT_FILTERING)
+ResourceError DocumentLoader::handleContentFilterDidBlock(ContentFilterUnblockHandler unblockHandler, String&& unblockRequestDeniedScript)
 {
     unblockHandler.setUnreachableURL(documentURL());
     if (!unblockRequestDeniedScript.isEmpty() && frame()) {
@@ -2440,8 +2447,40 @@
         });
     }
     frameLoader()->client().contentFilterDidBlockLoad(WTFMove(unblockHandler));
-    return frameLoader()->blockedByContentFilterError(request());
+    auto error = frameLoader()->blockedByContentFilterError(request());
+
+#if ENABLE(CONTENT_FILTERING_IN_NETWORKING_PROCESS)
+    m_blockedByContentFilter = true;
+    m_blockedError = error;
+#endif
+
+    return error;
 }
+
+void DocumentLoader::handleContentFilterProvisionalLoadFailure(const URL& blockedPageURL, const SubstituteData& substituteData)
+{
+    frameLoader()->load(FrameLoadRequest(*frame(), blockedPageURL, substituteData));
+}
+
+bool DocumentLoader::contentFilterWillHandleProvisionalLoadFailure(const ResourceError& error)
+{
+#if ENABLE(CONTENT_FILTERING_IN_NETWORKING_PROCESS)
+    return m_blockedByContentFilter && m_blockedError.errorCode() == error.errorCode() && m_blockedError.domain() == error.domain();
+#else
+    return m_contentFilter && m_contentFilter->willHandleProvisionalLoadFailure(error);
+#endif
+}
+
+void DocumentLoader::contentFilterHandleProvisionalLoadFailure(const ResourceError& error)
+{
+#if ENABLE(CONTENT_FILTERING_IN_NETWORKING_PROCESS)
+    UNUSED_PARAM(error);
+#else
+    if (m_contentFilter)
+        m_contentFilter->handleProvisionalLoadFailure(error);
+#endif
+}
+
 #endif // ENABLE(CONTENT_FILTERING)
 
 void DocumentLoader::setActiveContentRuleListActionPatterns(const HashMap<String, Vector<String>>& patterns)

Modified: trunk/Source/WebCore/loader/DocumentLoader.h (290188 => 290189)


--- trunk/Source/WebCore/loader/DocumentLoader.h	2022-02-19 00:57:42 UTC (rev 290188)
+++ trunk/Source/WebCore/loader/DocumentLoader.h	2022-02-19 01:02:27 UTC (rev 290189)
@@ -159,7 +159,7 @@
     : public RefCounted<DocumentLoader>
     , public FrameDestructionObserver
     , public ContentSecurityPolicyClient
-#if ENABLE(CONTENT_FILTERING)
+#if ENABLE(CONTENT_FILTERING) && !ENABLE(CONTENT_FILTERING_IN_NETWORKING_PROCESS)
     , public ContentFilterClient
 #endif
     , private CachedRawResourceClient {
@@ -402,10 +402,14 @@
     ShouldOpenExternalURLsPolicy shouldOpenExternalURLsPolicyToPropagate() const;
 
 #if ENABLE(CONTENT_FILTERING)
+#if !ENABLE(CONTENT_FILTERING_IN_NETWORKING_PROCESS)
     ContentFilter* contentFilter() const { return m_contentFilter.get(); }
     void ref() const final { RefCounted<DocumentLoader>::ref(); }
     void deref() const final { RefCounted<DocumentLoader>::deref(); }
 #endif
+    WEBCORE_EXPORT ResourceError handleContentFilterDidBlock(ContentFilterUnblockHandler, String&& unblockRequestDeniedScript);
+    WEBCORE_EXPORT void handleContentFilterProvisionalLoadFailure(const URL& blockedPageURL, const SubstituteData&);
+#endif
 
     void startIconLoading();
     WEBCORE_EXPORT void didGetLoadDecisionForIcon(bool decision, uint64_t loadIdentifier, CompletionHandler<void(FragmentedSharedBuffer*)>&&);
@@ -451,6 +455,11 @@
     bool isContinuingLoadAfterProvisionalLoadStarted() const { return m_isContinuingLoadAfterProvisionalLoadStarted; }
     void setIsContinuingLoadAfterProvisionalLoadStarted(bool isContinuingLoadAfterProvisionalLoadStarted) { m_isContinuingLoadAfterProvisionalLoadStarted = isContinuingLoadAfterProvisionalLoadStarted; }
 
+#if ENABLE(CONTENT_FILTERING)
+    bool contentFilterWillHandleProvisionalLoadFailure(const ResourceError&);
+    void contentFilterHandleProvisionalLoadFailure(const ResourceError&);
+#endif
+
 protected:
     WEBCORE_EXPORT DocumentLoader(const ResourceRequest&, const SubstituteData&);
 
@@ -503,7 +512,7 @@
 
     void responseReceived(const ResourceResponse&, CompletionHandler<void()>&&);
 
-#if ENABLE(CONTENT_FILTERING)
+#if ENABLE(CONTENT_FILTERING) && !ENABLE(CONTENT_FILTERING_IN_NETWORKING_PROCESS)
     // ContentFilterClient
     WEBCORE_EXPORT void dataReceivedThroughContentFilter(const SharedBuffer&) final;
     WEBCORE_EXPORT ResourceError contentFilterDidBlock(ContentFilterUnblockHandler, String&& unblockRequestDeniedScript) final;
@@ -655,8 +664,13 @@
     std::unique_ptr<ContentSecurityPolicy> m_contentSecurityPolicy;
 
 #if ENABLE(CONTENT_FILTERING)
+#if !ENABLE(CONTENT_FILTERING_IN_NETWORKING_PROCESS)
     std::unique_ptr<ContentFilter> m_contentFilter;
+#else
+    bool m_blockedByContentFilter { false };
+    ResourceError m_blockedError;
 #endif
+#endif
 
 #if USE(QUICK_LOOK)
     RefPtr<PreviewConverter> m_previewConverter;

Modified: trunk/Source/WebCore/loader/FrameLoader.cpp (290188 => 290189)


--- trunk/Source/WebCore/loader/FrameLoader.cpp	2022-02-19 00:57:42 UTC (rev 290188)
+++ trunk/Source/WebCore/loader/FrameLoader.cpp	2022-02-19 01:02:27 UTC (rev 290189)
@@ -2453,7 +2453,6 @@
     m_provisionalLoadErrorBeingHandledURL = provisionalDocumentLoader.url();
 
 #if ENABLE(CONTENT_FILTERING)
-    auto contentFilter = provisionalDocumentLoader.contentFilter();
     auto contentFilterWillContinueLoading = false;
 #endif
 
@@ -2461,7 +2460,7 @@
     if (history().provisionalItem())
         willContinueLoading = WillContinueLoading::Yes;
 #if ENABLE(CONTENT_FILTERING)
-    if (contentFilter && contentFilter->willHandleProvisionalLoadFailure(error)) {
+    if (provisionalDocumentLoader.contentFilterWillHandleProvisionalLoadFailure(error)) {
         willContinueLoading = WillContinueLoading::Yes;
         contentFilterWillContinueLoading = true;
     }
@@ -2471,7 +2470,7 @@
 
 #if ENABLE(CONTENT_FILTERING)
     if (contentFilterWillContinueLoading)
-        contentFilter->handleProvisionalLoadFailure(error);
+        provisionalDocumentLoader.contentFilterHandleProvisionalLoadFailure(error);
 #endif
 
     m_provisionalLoadErrorBeingHandledURL = { };

Modified: trunk/Source/WebCore/loader/PolicyChecker.cpp (290188 => 290189)


--- trunk/Source/WebCore/loader/PolicyChecker.cpp	2022-02-19 00:57:42 UTC (rev 290188)
+++ trunk/Source/WebCore/loader/PolicyChecker.cpp	2022-02-19 01:02:27 UTC (rev 290189)
@@ -141,7 +141,7 @@
     auto& substituteData = loader->substituteData();
     if (substituteData.isValid() && !substituteData.failingURL().isEmpty()) {
         bool shouldContinue = true;
-#if ENABLE(CONTENT_FILTERING)
+#if ENABLE(CONTENT_FILTERING) && !ENABLE(CONTENT_FILTERING_IN_NETWORKING_PROCESS)
         if (auto loader = m_frame.loader().activeDocumentLoader())
             shouldContinue = ContentFilter::continueAfterSubstituteDataRequest(*loader, substituteData);
 #endif

Modified: trunk/Source/WebCore/loader/SubstituteData.h (290188 => 290189)


--- trunk/Source/WebCore/loader/SubstituteData.h	2022-02-19 00:57:42 UTC (rev 290188)
+++ trunk/Source/WebCore/loader/SubstituteData.h	2022-02-19 01:02:27 UTC (rev 290189)
@@ -59,7 +59,10 @@
         const String& textEncoding() const { return m_response.textEncodingName(); }
         const URL& failingURL() const { return m_failingURL; }
         const ResourceResponse& response() const { return m_response; }
-        
+
+        template<class Encoder> void encode(Encoder&) const;
+        template<class Decoder> static std::optional<SubstituteData> decode(Decoder&);
+
     private:
         RefPtr<FragmentedSharedBuffer> m_content;
         URL m_failingURL;
@@ -67,4 +70,36 @@
         SessionHistoryVisibility m_shouldRevealToSessionHistory { SessionHistoryVisibility::Hidden };
     };
 
+template<class Encoder>
+void SubstituteData::encode(Encoder& encoder) const
+{
+    encoder << m_content << m_failingURL << m_response << m_shouldRevealToSessionHistory;
+}
+
+template<class Decoder>
+std::optional<SubstituteData> SubstituteData::decode(Decoder& decoder)
+{
+    std::optional<RefPtr<FragmentedSharedBuffer>> content;
+    decoder >> content;
+    if (!content)
+        return std::nullopt;
+
+    std::optional<URL> failingURL;
+    decoder >> failingURL;
+    if (!failingURL)
+        return std::nullopt;
+
+    std::optional<ResourceResponse> response;
+    decoder >> response;
+    if (!response)
+        return std::nullopt;
+
+    std::optional<SessionHistoryVisibility> shouldRevealToSessionHistory;
+    decoder >> shouldRevealToSessionHistory;
+    if (!shouldRevealToSessionHistory)
+        return std::nullopt;
+
+    return { { WTFMove(*content), *failingURL, *response, *shouldRevealToSessionHistory } };
+}
+
 } // namespace WebCore

Modified: trunk/Source/WebKit/ChangeLog (290188 => 290189)


--- trunk/Source/WebKit/ChangeLog	2022-02-19 00:57:42 UTC (rev 290188)
+++ trunk/Source/WebKit/ChangeLog	2022-02-19 01:02:27 UTC (rev 290189)
@@ -1,5 +1,47 @@
 2022-02-18  Per Arne Vollan  <pvol...@apple.com>
 
+        Move content filtering to Networking process
+        https://bugs.webkit.org/show_bug.cgi?id=233760
+        <rdar://problem/86150702>
+
+        Reviewed by Brent Fulgham.
+
+        Move content filtering from the DocumentLoader class in the WebProcess to the NetworkResourceLoader class in the
+        Networking process. The NetworkResourceLoader is now a client of the content filter, and will send messages
+        to the DocumentLoader in the WebProcess to cancel the load when the content filter decided to block the load.
+        If the content filter is providing replacement data, this will also be sent over IPC to the WebProcess.
+        Data is not being sent to the WebProcess until the content filter has decided to allow the load, if content
+        filtering is enabled.
+
+        * NetworkProcess/NetworkResourceLoader.cpp:
+        (WebKit::NetworkResourceLoader::start):
+        (WebKit::NetworkResourceLoader::startContentFiltering):
+        (WebKit::NetworkResourceLoader::didReceiveResponse):
+        (WebKit::NetworkResourceLoader::didFinishLoading):
+        (WebKit::NetworkResourceLoader::willSendRedirectedRequest):
+        (WebKit::NetworkResourceLoader::bufferingTimerFired):
+        (WebKit::NetworkResourceLoader::sendBuffer):
+        (WebKit::NetworkResourceLoader::didRetrieveCacheEntry):
+        (WebKit::NetworkResourceLoader::sendResultForCacheEntry):
+        (WebKit::NetworkResourceLoader::dataReceivedThroughContentFilter):
+        (WebKit::NetworkResourceLoader::contentFilterDidBlock):
+        (WebKit::NetworkResourceLoader::cancelMainResourceLoadForContentFilter):
+        (WebKit::NetworkResourceLoader::handleProvisionalLoadFailureFromContentFilter):
+        * NetworkProcess/NetworkResourceLoader.h:
+        * UIProcess/Network/NetworkProcessProxy.cpp:
+        (WebKit::NetworkProcessProxy::reloadAfterUnblockedContentFilter):
+        * UIProcess/Network/NetworkProcessProxy.h:
+        * UIProcess/Network/NetworkProcessProxy.messages.in:
+        * WebProcess/Network/WebResourceLoader.cpp:
+        (WebKit::WebResourceLoader::contentFilterDidBlockLoad):
+        (WebKit::WebResourceLoader::cancelMainResourceLoadForContentFilter):
+        (WebKit::WebResourceLoader::handleProvisionalLoadFailureFromContentFilter):
+        (WebKit::WebResourceLoader::reload):
+        * WebProcess/Network/WebResourceLoader.h:
+        * WebProcess/Network/WebResourceLoader.messages.in:
+
+2022-02-18  Per Arne Vollan  <pvol...@apple.com>
+
         [iOS] Add required Mach service to the sandbox of the GPU process
         https://bugs.webkit.org/show_bug.cgi?id=236860
 

Modified: trunk/Source/WebKit/NetworkProcess/NetworkResourceLoader.cpp (290188 => 290189)


--- trunk/Source/WebKit/NetworkProcess/NetworkResourceLoader.cpp	2022-02-19 00:57:42 UTC (rev 290188)
+++ trunk/Source/WebKit/NetworkProcess/NetworkResourceLoader.cpp	2022-02-19 01:02:27 UTC (rev 290189)
@@ -67,6 +67,11 @@
 #include <WebCore/PreviewConverter.h>
 #endif
 
+#if ENABLE(CONTENT_FILTERING_IN_NETWORKING_PROCESS)
+#include <WebCore/ContentFilter.h>
+#include <WebCore/ContentFilterUnblockHandler.h>
+#endif
+
 #define LOADER_RELEASE_LOG(fmt, ...) RELEASE_LOG(Network, "%p - [pageProxyID=%" PRIu64 ", webPageID=%" PRIu64 ", frameID=%" PRIu64 ", resourceID=%" PRIu64 ", isMainResource=%d, destination=%u, isSynchronous=%d] NetworkResourceLoader::" fmt, this, m_parameters.webPageProxyID.toUInt64(), m_parameters.webPageID.toUInt64(), m_parameters.webFrameID.toUInt64(), m_parameters.identifier.toUInt64(), isMainResource(), static_cast<unsigned>(m_parameters.options.destination), isSynchronous(), ##__VA_ARGS__)
 #define LOADER_RELEASE_LOG_ERROR(fmt, ...) RELEASE_LOG_ERROR(Network, "%p - [pageProxyID=%" PRIu64 ", webPageID=%" PRIu64 ", frameID=%" PRIu64 ", resourceID=%" PRIu64 ", isMainResource=%d, destination=%u, isSynchronous=%d] NetworkResourceLoader::" fmt, this, m_parameters.webPageProxyID.toUInt64(), m_parameters.webPageID.toUInt64(), m_parameters.webFrameID.toUInt64(), m_parameters.identifier.toUInt64(), isMainResource(), static_cast<unsigned>(m_parameters.options.destination), isSynchronous(), ##__VA_ARGS__)
 
@@ -187,8 +192,13 @@
     ASSERT(!m_wasStarted);
     m_wasStarted = true;
 
+    auto newRequest = ResourceRequest { originalRequest() };
+#if ENABLE(CONTENT_FILTERING_IN_NETWORKING_PROCESS)
+    startContentFiltering(newRequest);
+#endif
+
     if (m_networkLoadChecker) {
-        m_networkLoadChecker->check(ResourceRequest { originalRequest() }, this, [this, weakThis = WeakPtr { *this }] (auto&& result) {
+        m_networkLoadChecker->check(ResourceRequest { newRequest }, this, [this, weakThis = WeakPtr { *this }] (auto&& result) {
             if (!weakThis)
                 return;
 
@@ -217,14 +227,26 @@
         return;
     }
     // FIXME: Remove that code path once m_networkLoadChecker is used for all network loads.
-    if (canUseCache(originalRequest())) {
+    if (canUseCache(newRequest)) {
         retrieveCacheEntry(originalRequest());
         return;
     }
 
-    startNetworkLoad(ResourceRequest { originalRequest() }, FirstLoad::Yes);
+    startNetworkLoad(ResourceRequest { newRequest }, FirstLoad::Yes);
 }
 
+#if ENABLE(CONTENT_FILTERING_IN_NETWORKING_PROCESS)
+void NetworkResourceLoader::startContentFiltering(ResourceRequest& request)
+{
+    if (!isMainResource())
+        return;
+    m_contentFilter = ContentFilter::create(*this);
+    if (!m_contentFilter->continueAfterWillSendRequest(request, ResourceResponse()))
+        return;
+    m_contentFilter->startFilteringMainResource(request.url());
+}
+#endif
+
 void NetworkResourceLoader::retrieveCacheEntry(const ResourceRequest& request)
 {
     LOADER_RELEASE_LOG("retrieveCacheEntry: isMainFrameLoad=%d", isMainFrameLoad());
@@ -692,6 +714,11 @@
 {
     LOADER_RELEASE_LOG("didReceiveResponse: (httpStatusCode=%d, MIMEType=%" PUBLIC_LOG_STRING ", expectedContentLength=%" PRId64 ", hasCachedEntryForValidation=%d, hasNetworkLoadChecker=%d)", receivedResponse.httpStatusCode(), receivedResponse.mimeType().utf8().data(), receivedResponse.expectedContentLength(), !!m_cacheEntryForValidation, !!m_networkLoadChecker);
 
+#if ENABLE(CONTENT_FILTERING_IN_NETWORKING_PROCESS)
+    if (m_contentFilter && !m_contentFilter->continueAfterResponseReceived(receivedResponse))
+        return completionHandler(PolicyAction::Ignore);
+#endif
+
     if (isMainResource())
         didReceiveMainResourceResponse(receivedResponse);
 
@@ -904,6 +931,13 @@
             // FIXME: Pass a real value or remove the encoded data size feature.
             sendBuffer(*m_bufferedData.get(), -1);
         }
+#if ENABLE(CONTENT_FILTERING_IN_NETWORKING_PROCESS)
+        if (m_contentFilter) {
+            m_contentFilter->continueAfterNotifyFinished(m_parameters.request.url());
+            m_contentFilter->stopFilteringMainResource();
+        }
+#endif
+
         send(Messages::WebResourceLoader::DidFinishResourceLoad(networkLoadMetrics));
     }
 
@@ -993,6 +1027,11 @@
     if (!m_firstResponseURL.isValid())
         m_firstResponseURL = redirectResponse.url();
 
+#if ENABLE(CONTENT_FILTERING_IN_NETWORKING_PROCESS)
+    if (m_contentFilter && !m_contentFilter->continueAfterWillSendRequest(request, redirectResponse))
+        return;
+#endif
+
     std::optional<WebCore::PrivateClickMeasurement::AttributionTriggerData> privateClickMeasurementAttributionTriggerData;
     if (!sessionID().isEphemeral()) {
         if (auto result = WebCore::PrivateClickMeasurement::parseAttributionRequest(redirectRequest.url())) {
@@ -1251,8 +1290,14 @@
     if (m_bufferedData.isEmpty())
         return;
 
+#if ENABLE(CONTENT_FILTERING_IN_NETWORKING_PROCESS)
+    auto sharedBuffer = m_bufferedData.takeAsContiguous();
+    bool shouldFilter = m_contentFilter && !m_contentFilter->continueAfterDataReceived(sharedBuffer, m_bufferedDataEncodedDataLength);
+    if (!shouldFilter)
+        send(Messages::WebResourceLoader::DidReceiveData(IPC::SharedBufferCopy(sharedBuffer.get()), m_bufferedDataEncodedDataLength));
+#else
     send(Messages::WebResourceLoader::DidReceiveData(IPC::SharedBufferCopy(*m_bufferedData.get()), m_bufferedDataEncodedDataLength));
-
+#endif
     m_bufferedData.empty();
     m_bufferedDataEncodedDataLength = 0;
 }
@@ -1261,6 +1306,11 @@
 {
     ASSERT(!isSynchronous());
 
+#if ENABLE(CONTENT_FILTERING_IN_NETWORKING_PROCESS)
+    if (m_contentFilter && !m_contentFilter->continueAfterDataReceived(buffer.makeContiguous(), encodedDataLength))
+        return;
+#endif
+
     send(Messages::WebResourceLoader::DidReceiveData(IPC::SharedBufferCopy(buffer), encodedDataLength));
 }
 
@@ -1307,6 +1357,11 @@
     LOADER_RELEASE_LOG("didRetrieveCacheEntry:");
     auto response = entry->response();
 
+#if ENABLE(CONTENT_FILTERING_IN_NETWORKING_PROCESS)
+    if (m_contentFilter && !m_contentFilter->responseReceived() && !m_contentFilter->continueAfterResponseReceived(response))
+        return;
+#endif
+
     if (isMainResource())
         didReceiveMainResourceResponse(response);
 
@@ -1358,6 +1413,13 @@
     LOADER_RELEASE_LOG("sendResultForCacheEntry:");
 #if ENABLE(SHAREABLE_RESOURCE)
     if (!entry->shareableResourceHandle().isNull()) {
+#if ENABLE(CONTENT_FILTERING_IN_NETWORKING_PROCESS)
+        if (m_contentFilter && !m_contentFilter->continueAfterDataReceived(entry->buffer()->makeContiguous(), entry->buffer()->size())) {
+            m_contentFilter->continueAfterNotifyFinished(m_parameters.request.url());
+            m_contentFilter->stopFilteringMainResource();
+            return;
+        }
+#endif
         send(Messages::WebResourceLoader::DidReceiveResource(entry->shareableResourceHandle()));
         return;
     }
@@ -1381,6 +1443,12 @@
     networkLoadMetrics.responseBodyDecodedSize = 0;
 
     sendBuffer(*entry->buffer(), entry->buffer()->size());
+#if ENABLE(CONTENT_FILTERING_IN_NETWORKING_PROCESS)
+    if (m_contentFilter) {
+        m_contentFilter->continueAfterNotifyFinished(m_parameters.request.url());
+        m_contentFilter->stopFilteringMainResource();
+    }
+#endif
     send(Messages::WebResourceLoader::DidFinishResourceLoad(networkLoadMetrics));
 }
 
@@ -1697,6 +1765,43 @@
     return m_parameters.request.isAppInitiated();
 }
 
+#if ENABLE(CONTENT_FILTERING_IN_NETWORKING_PROCESS)
+void NetworkResourceLoader::dataReceivedThroughContentFilter(const SharedBuffer& buffer, size_t encodedDataLength)
+{
+    send(Messages::WebResourceLoader::DidReceiveData(IPC::SharedBufferCopy(buffer), encodedDataLength));
+}
+
+WebCore::ResourceError NetworkResourceLoader::contentFilterDidBlock(WebCore::ContentFilterUnblockHandler unblockHandler, String&& unblockRequestDeniedScript)
+{
+    send(Messages::WebResourceLoader::ContentFilterDidBlockLoad(unblockHandler, unblockRequestDeniedScript));
+    if (!unblockHandler.needsUIProcess()) {
+        unblockHandler.requestUnblockAsync([this, protectedThis = Ref { *this }](bool unblocked) {
+            if (!unblocked)
+                return;
+            m_connection->networkProcess().parentProcessConnection()->send(Messages::NetworkProcessProxy::ReloadAfterUnblockedContentFilter(m_parameters.webPageProxyID), 0);
+        });
+    }
+    return WebKit::blockedByContentFilterError(m_parameters.request);
+}
+
+void NetworkResourceLoader::cancelMainResourceLoadForContentFilter(const WebCore::ResourceError& error)
+{
+    RELEASE_ASSERT(m_contentFilter);
+    m_contentFilter->handleProvisionalLoadFailure(error);
+}
+
+void NetworkResourceLoader::handleProvisionalLoadFailureFromContentFilter(const URL& blockedPageURL, WebCore::SubstituteData& substituteData)
+{
+    if (substituteData.isValid())
+        send(Messages::WebResourceLoader::HandleProvisionalLoadFailureFromContentFilter(blockedPageURL, substituteData));
+    else {
+        RELEASE_ASSERT(m_contentFilter);
+        auto& error = m_contentFilter->blockedError();
+        send(Messages::WebResourceLoader::CancelMainResourceLoadForContentFilter(error));
+    }
+}
+#endif // ENABLE(CONTENT_FILTERING_IN_NETWORKING_PROCESS)
+
 } // namespace WebKit
 
 #undef LOADER_RELEASE_LOG

Modified: trunk/Source/WebKit/NetworkProcess/NetworkResourceLoader.h (290188 => 290189)


--- trunk/Source/WebKit/NetworkProcess/NetworkResourceLoader.h	2022-02-19 00:57:42 UTC (rev 290188)
+++ trunk/Source/WebKit/NetworkProcess/NetworkResourceLoader.h	2022-02-19 01:02:27 UTC (rev 290189)
@@ -34,6 +34,7 @@
 #include "NetworkResourceLoadIdentifier.h"
 #include "NetworkResourceLoadParameters.h"
 #include "PrivateRelayed.h"
+#include <WebCore/ContentFilterClient.h>
 #include <WebCore/ContentSecurityPolicyClient.h>
 #include <WebCore/CrossOriginAccessControl.h>
 #include <WebCore/PrivateClickMeasurement.h>
@@ -45,6 +46,7 @@
 
 namespace WebCore {
 class BlobDataFileReference;
+class ContentFilter;
 class FormData;
 class NetworkStorageSession;
 class ResourceRequest;
@@ -72,6 +74,9 @@
     , public IPC::MessageSender
     , public WebCore::ContentSecurityPolicyClient
     , public WebCore::CrossOriginAccessControlCheckDisabler
+#if ENABLE(CONTENT_FILTERING_IN_NETWORKING_PROCESS)
+    , public WebCore::ContentFilterClient
+#endif
     , public CanMakeWeakPtr<NetworkResourceLoader> {
 public:
     static Ref<NetworkResourceLoader> create(NetworkResourceLoadParameters&& parameters, NetworkConnectionToWebProcess& connection, Messages::NetworkConnectionToWebProcess::PerformSynchronousLoadDelayedReply&& reply = nullptr)
@@ -92,7 +97,7 @@
     // Message handlers.
     void didReceiveNetworkResourceLoaderMessage(IPC::Connection&, IPC::Decoder&);
 
-    void continueWillSendRequest(WebCore::ResourceRequest&& newRequest, bool isAllowedToAskUserForCredentials);
+    void continueWillSendRequest(WebCore::ResourceRequest&&, bool isAllowedToAskUserForCredentials);
 
     void setResponse(WebCore::ResourceResponse&& response) { m_response = WTFMove(response); }
     const WebCore::ResourceResponse& response() const { return m_response; }
@@ -155,6 +160,11 @@
 
     bool isAppInitiated();
 
+#if ENABLE(CONTENT_FILTERING_IN_NETWORKING_PROCESS)
+    void ref() const final { RefCounted<NetworkResourceLoader>::ref(); }
+    void deref() const final { RefCounted<NetworkResourceLoader>::deref(); }
+#endif
+
 private:
     NetworkResourceLoader(NetworkResourceLoadParameters&&, NetworkConnectionToWebProcess&, Messages::NetworkConnectionToWebProcess::PerformSynchronousLoadDelayedReply&&);
 
@@ -162,6 +172,14 @@
     IPC::Connection* messageSenderConnection() const override;
     uint64_t messageSenderDestinationID() const override { return m_parameters.identifier.toUInt64(); }
 
+#if ENABLE(CONTENT_FILTERING_IN_NETWORKING_PROCESS)
+    // ContentFilterClient
+    void dataReceivedThroughContentFilter(const WebCore::SharedBuffer&, size_t) final;
+    WebCore::ResourceError contentFilterDidBlock(WebCore::ContentFilterUnblockHandler, String&& unblockRequestDeniedScript) final;
+    void cancelMainResourceLoadForContentFilter(const WebCore::ResourceError&) final;
+    void handleProvisionalLoadFailureFromContentFilter(const URL& blockedPageURL, WebCore::SubstituteData&) final;
+#endif
+
     bool canUseCache(const WebCore::ResourceRequest&) const;
     bool canUseCachedRedirect(const WebCore::ResourceRequest&) const;
 
@@ -220,6 +238,10 @@
 
     ResourceLoadInfo resourceLoadInfo();
 
+#if ENABLE(CONTENT_FILTERING_IN_NETWORKING_PROCESS)
+    void startContentFiltering(WebCore::ResourceRequest&);
+#endif
+
     const NetworkResourceLoadParameters m_parameters;
 
     Ref<NetworkConnectionToWebProcess> m_connection;
@@ -264,6 +286,11 @@
     WebCore::ResourceResponse m_redirectResponse;
     URL m_firstResponseURL; // First URL in response's URL list (https://fetch.spec.whatwg.org/#concept-response-url-list).
     std::optional<WebCore::CrossOriginOpenerPolicyEnforcementResult> m_currentCoopEnforcementResult;
+
+#if ENABLE(CONTENT_FILTERING_IN_NETWORKING_PROCESS)
+    std::unique_ptr<WebCore::ContentFilter> m_contentFilter;
+#endif
+
     PrivateRelayed m_privateRelayed { PrivateRelayed::No };
 };
 

Modified: trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.cpp (290188 => 290189)


--- trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.cpp	2022-02-19 00:57:42 UTC (rev 290188)
+++ trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.cpp	2022-02-19 01:02:27 UTC (rev 290189)
@@ -28,6 +28,7 @@
 
 #include "APIContentRuleList.h"
 #include "APICustomProtocolManagerClient.h"
+#include "APINavigation.h"
 #include "AuthenticationChallengeProxy.h"
 #include "AuthenticationManager.h"
 #include "DownloadProxyMap.h"
@@ -604,6 +605,14 @@
     page->resourceLoadDidCompleteWithError(WTFMove(loadInfo), WTFMove(response), WTFMove(error));
 }
 
+#if ENABLE(CONTENT_FILTERING_IN_NETWORKING_PROCESS)
+void NetworkProcessProxy::reloadAfterUnblockedContentFilter(WebPageProxyIdentifier pageID)
+{
+    if (auto* page = WebProcessProxy::webPage(pageID))
+        page->reload({ });
+}
+#endif
+
 #if ENABLE(INTELLIGENT_TRACKING_PREVENTION)
 void NetworkProcessProxy::dumpResourceLoadStatistics(PAL::SessionID sessionID, CompletionHandler<void(String)>&& completionHandler)
 {

Modified: trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.h (290188 => 290189)


--- trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.h	2022-02-19 00:57:42 UTC (rev 290188)
+++ trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.h	2022-02-19 01:02:27 UTC (rev 290189)
@@ -254,6 +254,10 @@
     void resourceLoadDidReceiveResponse(WebPageProxyIdentifier, ResourceLoadInfo&&, WebCore::ResourceResponse&&);
     void resourceLoadDidCompleteWithError(WebPageProxyIdentifier, ResourceLoadInfo&&, WebCore::ResourceResponse&&, WebCore::ResourceError&&);
 
+#if ENABLE(CONTENT_FILTERING_IN_NETWORKING_PROCESS)
+    void reloadAfterUnblockedContentFilter(WebPageProxyIdentifier);
+#endif
+
 #if ENABLE(APP_BOUND_DOMAINS)
     void hasAppBoundSession(PAL::SessionID, CompletionHandler<void(bool)>&&);
     void clearAppBoundSession(PAL::SessionID, CompletionHandler<void()>&&);

Modified: trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.messages.in (290188 => 290189)


--- trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.messages.in	2022-02-19 00:57:42 UTC (rev 290188)
+++ trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.messages.in	2022-02-19 01:02:27 UTC (rev 290189)
@@ -76,6 +76,10 @@
     ResourceLoadDidReceiveChallenge(WebKit::WebPageProxyIdentifier pageIdentifier, struct WebKit::ResourceLoadInfo resourceLoadInfo, WebCore::AuthenticationChallenge challenge)
     ResourceLoadDidReceiveResponse(WebKit::WebPageProxyIdentifier pageIdentifier, struct WebKit::ResourceLoadInfo resourceLoadInfo, WebCore::ResourceResponse response)
     ResourceLoadDidCompleteWithError(WebKit::WebPageProxyIdentifier pageIdentifier, struct WebKit::ResourceLoadInfo resourceLoadInfo, WebCore::ResourceResponse response, WebCore::ResourceError error)
+    
+#if ENABLE(CONTENT_FILTERING_IN_NETWORKING_PROCESS)
+    ReloadAfterUnblockedContentFilter(WebKit::WebPageProxyIdentifier pageIdentifier)
+#endif
 
     TriggerBrowsingContextGroupSwitchForNavigation(WebKit::WebPageProxyIdentifier pageIdentifier, uint64_t navigationID, enum:uint8_t WebCore::BrowsingContextGroupSwitchDecision browsingContextGroupSwitchDecision, WebCore::RegistrableDomain responseDomain, WebKit::NetworkResourceLoadIdentifier existingNetworkResourceLoadIdentifierToResume) -> (bool success) Async
 

Modified: trunk/Source/WebKit/WebProcess/Network/WebResourceLoader.cpp (290188 => 290189)


--- trunk/Source/WebKit/WebProcess/Network/WebResourceLoader.cpp	2022-02-19 00:57:42 UTC (rev 290188)
+++ trunk/Source/WebKit/WebProcess/Network/WebResourceLoader.cpp	2022-02-19 01:02:27 UTC (rev 290189)
@@ -54,6 +54,7 @@
 #include <WebCore/ResourceError.h>
 #include <WebCore/ResourceLoader.h>
 #include <WebCore/SubresourceLoader.h>
+#include <WebCore/SubstituteData.h>
 #include <wtf/CompletionHandler.h>
 
 #define WEBRESOURCELOADER_RELEASE_LOG(fmt, ...) RELEASE_LOG(Network, "%p - [webPageID=%" PRIu64 ", frameID=%" PRIu64 ", resourceID=%" PRIu64 "] WebResourceLoader::" fmt, this, m_trackingParameters.pageID.toUInt64(), m_trackingParameters.frameID.toUInt64(), m_trackingParameters.resourceID.toUInt64(), ##__VA_ARGS__)
@@ -349,6 +350,29 @@
 }
 #endif
 
+#if ENABLE(CONTENT_FILTERING_IN_NETWORKING_PROCESS)
+void WebResourceLoader::contentFilterDidBlockLoad(const WebCore::ContentFilterUnblockHandler& unblockHandler, String&& unblockRequestDeniedScript)
+{
+    if (!m_coreLoader || !m_coreLoader->documentLoader())
+        return;
+    m_coreLoader->documentLoader()->handleContentFilterDidBlock(unblockHandler, WTFMove(unblockRequestDeniedScript));
+}
+
+void WebResourceLoader::cancelMainResourceLoadForContentFilter(const WebCore::ResourceError& error)
+{
+    if (!m_coreLoader || !m_coreLoader->documentLoader())
+        return;
+    m_coreLoader->documentLoader()->cancelMainResourceLoad(error);
+}
+
+void WebResourceLoader::handleProvisionalLoadFailureFromContentFilter(const URL& blockedPageURL, const WebCore::SubstituteData& substituteData)
+{
+    if (!m_coreLoader || !m_coreLoader->documentLoader() || !substituteData.isValid())
+        return;
+    m_coreLoader->documentLoader()->handleContentFilterProvisionalLoadFailure(blockedPageURL, substituteData);
+}
+#endif // ENABLE(CONTENT_FILTERING_IN_NETWORKING_PROCESS)
+
 } // namespace WebKit
 
 #undef WEBRESOURCELOADER_RELEASE_LOG

Modified: trunk/Source/WebKit/WebProcess/Network/WebResourceLoader.h (290188 => 290189)


--- trunk/Source/WebKit/WebProcess/Network/WebResourceLoader.h	2022-02-19 00:57:42 UTC (rev 290188)
+++ trunk/Source/WebKit/WebProcess/Network/WebResourceLoader.h	2022-02-19 01:02:27 UTC (rev 290189)
@@ -43,11 +43,13 @@
 }
 
 namespace WebCore {
+class ContentFilterUnblockHandler;
 class NetworkLoadMetrics;
 class ResourceError;
 class ResourceLoader;
 class ResourceRequest;
 class ResourceResponse;
+class SubstituteData;
 enum class MainFrameMainResource : bool;
 }
 
@@ -99,6 +101,12 @@
     void didReceiveResource(const ShareableResource::Handle&);
 #endif
 
+#if ENABLE(CONTENT_FILTERING_IN_NETWORKING_PROCESS)
+    void contentFilterDidBlockLoad(const WebCore::ContentFilterUnblockHandler&, String&& unblockRequestDeniedScript);
+    void cancelMainResourceLoadForContentFilter(const WebCore::ResourceError&);
+    void handleProvisionalLoadFailureFromContentFilter(const URL& blockedPageURL, const WebCore::SubstituteData&);
+#endif
+    
     RefPtr<WebCore::ResourceLoader> m_coreLoader;
     TrackingParameters m_trackingParameters;
     WebResourceInterceptController m_interceptController;

Modified: trunk/Source/WebKit/WebProcess/Network/WebResourceLoader.messages.in (290188 => 290189)


--- trunk/Source/WebKit/WebProcess/Network/WebResourceLoader.messages.in	2022-02-19 00:57:42 UTC (rev 290188)
+++ trunk/Source/WebKit/WebProcess/Network/WebResourceLoader.messages.in	2022-02-19 01:02:27 UTC (rev 290189)
@@ -37,4 +37,11 @@
     // DidReceiveResource is for when we have the entire resource data available at once, such as when the resource is cached in memory
     DidReceiveResource(WebKit::ShareableResource::Handle resource)
 #endif
+
+#if ENABLE(CONTENT_FILTERING_IN_NETWORKING_PROCESS)
+    ContentFilterDidBlockLoad(WebCore::ContentFilterUnblockHandler unblockHandler, String unblockRequestDeniedScript)
+    CancelMainResourceLoadForContentFilter(WebCore::ResourceError error)
+    HandleProvisionalLoadFailureFromContentFilter(URL blockedPageURL, WebCore::SubstituteData substituteData)
+#endif
+
 }
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to