Add SPI to inform applications of WKContentRuleList actions
authorachristensen@apple.com <achristensen@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 21 Mar 2019 20:23:46 +0000 (20:23 +0000)
committerachristensen@apple.com <achristensen@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 21 Mar 2019 20:23:46 +0000 (20:23 +0000)
https://bugs.webkit.org/show_bug.cgi?id=195965
<rdar://problem/42664365>

Reviewed by Geoff Garen.

Source/WebCore:

We already had SPI to inform the application of notifications.
In order to inform it about other actions, I needed to put them in a different structure.
Basically, instead of a Vector<Action> I use a Vector<Vector<Action>> that contains the same actions.
That way we can give one callback per WKContentRuleList.

* Modules/websockets/WebSocketChannel.cpp:
(WebCore::WebSocketChannel::connect):
* WebCore.xcodeproj/project.pbxproj:
* contentextensions/ContentExtensionActions.h:
* contentextensions/ContentExtensionParser.cpp:
(WebCore::ContentExtensions::loadEncodedRules):
* contentextensions/ContentExtensionRule.cpp:
(WebCore::ContentExtensions::Action::isolatedCopy const):
* contentextensions/ContentExtensionRule.h:
(WebCore::ContentExtensions::Action::operator== const):
(WebCore::ContentExtensions::Action::setExtensionIdentifier): Deleted.
(WebCore::ContentExtensions::Action::extensionIdentifier const): Deleted.
* contentextensions/ContentExtensionsBackend.cpp:
(WebCore::ContentExtensions::ContentExtensionsBackend::actionsForResourceLoad const):
(WebCore::ContentExtensions::ContentExtensionsBackend::processContentRuleListsForLoad):
(WebCore::ContentExtensions::ContentExtensionsBackend::processContentRuleListsForPingLoad):
(WebCore::ContentExtensions::applyResultsToRequest):
(WebCore::ContentExtensions::ContentExtensionsBackend::processContentExtensionRulesForLoad): Deleted.
(WebCore::ContentExtensions::ContentExtensionsBackend::processContentExtensionRulesForPingLoad): Deleted.
(WebCore::ContentExtensions::applyBlockedStatusToRequest): Deleted.
* contentextensions/ContentExtensionsBackend.h:
* contentextensions/ContentRuleListResults.h: Added.
(WebCore::ContentRuleListResults::Result::shouldNotifyApplication const):
(WebCore::ContentRuleListResults::shouldNotifyApplication const):
(WebCore::ContentRuleListResults::encode const):
(WebCore::ContentRuleListResults::decode):
(WebCore::ContentRuleListResults::Result::encode const):
(WebCore::ContentRuleListResults::Result::decode):
(WebCore::ContentRuleListResults::Summary::encode const):
(WebCore::ContentRuleListResults::Summary::decode):
* css/StyleSheetContents.cpp:
(WebCore::StyleSheetContents::subresourcesAllowReuse const):
* html/HTMLMediaElement.cpp:
(WebCore::HTMLMediaElement::loadResource):
* loader/FrameLoader.cpp:
(WebCore::FrameLoader::loadResourceSynchronously):
* loader/PingLoader.cpp:
(WebCore::processContentRuleListsForLoad):
(WebCore::PingLoader::loadImage):
(WebCore::PingLoader::sendPing):
(WebCore::PingLoader::sendViolationReport):
(WebCore::processContentExtensionRulesForLoad): Deleted.
* loader/ResourceLoader.cpp:
(WebCore::ResourceLoader::willSendRequestInternal):
* loader/cache/CachedResourceLoader.cpp:
(WebCore::CachedResourceLoader::requestResource):
* loader/cache/CachedResourceRequest.cpp:
(WebCore::CachedResourceRequest::applyResults):
(WebCore::CachedResourceRequest::applyBlockedStatus): Deleted.
* loader/cache/CachedResourceRequest.h:
* page/ChromeClient.h:
(WebCore::ChromeClient::contentRuleListNotification):
* page/DOMWindow.cpp:
(WebCore::DOMWindow::open):
* page/UserContentProvider.cpp:
(WebCore::UserContentProvider::processContentRuleListsForLoad):
(WebCore::UserContentProvider::actionsForResourceLoad):
(WebCore::UserContentProvider::processContentExtensionRulesForLoad): Deleted.
* page/UserContentProvider.h:

Source/WebKit:

* NetworkProcess/NetworkLoadChecker.cpp:
(WebKit::NetworkLoadChecker::checkRequest):
(WebKit::NetworkLoadChecker::processContentRuleListsForLoad):
(WebKit::NetworkLoadChecker::processContentExtensionRulesForLoad): Deleted.
* NetworkProcess/NetworkLoadChecker.h:
* UIProcess/API/APINavigationClient.h:
(API::NavigationClient::contentRuleListNotification):
* UIProcess/API/C/WKPage.cpp:
(WKPageSetPageNavigationClient):
* UIProcess/API/Cocoa/WKNavigationDelegatePrivate.h:
* UIProcess/Cocoa/NavigationState.h:
* UIProcess/Cocoa/NavigationState.mm:
(WebKit::NavigationState::setNavigationDelegate):
(WebKit::NavigationState::NavigationClient::contentRuleListNotification):
* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::contentRuleListNotification):
* UIProcess/WebPageProxy.h:
* UIProcess/WebPageProxy.messages.in:
* WebProcess/WebCoreSupport/WebChromeClient.cpp:
(WebKit::WebChromeClient::contentRuleListNotification):
* WebProcess/WebCoreSupport/WebChromeClient.h:

Tools:

* TestWebKitAPI/Tests/WebCore/ContentExtensions.cpp:
(TestWebKitAPI::allActionsForResourceLoad):
(TestWebKitAPI::testRequest):
(TestWebKitAPI::TEST_F):
* TestWebKitAPI/Tests/WebKitCocoa/ContentRuleListNotification.mm:
(Notification::description):
(Notification::operator== const):
(toVector):
(-[ContentRuleListNotificationDelegate _webView:URL:contentRuleListIdentifiers:notifications:]):
(-[ContentRuleListNotificationDelegate _webView:contentRuleListWithIdentifier:performedActionOnURL:blockedLoad:blockedCookies:madeHTTPS:notifications:]):
(makeContentRuleList):
(TEST):
(makeWarnContentRuleList): Deleted.

LayoutTests:

* http/tests/contentextensions/popups-expected.txt:
Because popups now use UserContentProvider.processContentRuleListsForLoad like everything else,
it now prints messages to the debug console.  That is a desired improvement, so expectations are updated accordingly.

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

58 files changed:
LayoutTests/ChangeLog
LayoutTests/http/tests/contentextensions/popups-expected.txt
Source/WebCore/ChangeLog
Source/WebCore/Modules/websockets/WebSocketChannel.cpp
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/contentextensions/ContentExtensionActions.h
Source/WebCore/contentextensions/ContentExtensionCompiler.cpp
Source/WebCore/contentextensions/ContentExtensionParser.cpp
Source/WebCore/contentextensions/ContentExtensionRule.cpp
Source/WebCore/contentextensions/ContentExtensionRule.h
Source/WebCore/contentextensions/ContentExtensionsBackend.cpp
Source/WebCore/contentextensions/ContentExtensionsBackend.h
Source/WebCore/contentextensions/ContentRuleListResults.h [new file with mode: 0644]
Source/WebCore/css/StyleSheetContents.cpp
Source/WebCore/html/HTMLMediaElement.cpp
Source/WebCore/loader/FrameLoader.cpp
Source/WebCore/loader/PingLoader.cpp
Source/WebCore/loader/ResourceLoader.cpp
Source/WebCore/loader/cache/CachedResourceLoader.cpp
Source/WebCore/loader/cache/CachedResourceRequest.cpp
Source/WebCore/loader/cache/CachedResourceRequest.h
Source/WebCore/page/ChromeClient.h
Source/WebCore/page/DOMWindow.cpp
Source/WebCore/page/UserContentProvider.cpp
Source/WebCore/page/UserContentProvider.h
Source/WebKit/ChangeLog
Source/WebKit/NetworkProcess/NetworkLoadChecker.cpp
Source/WebKit/NetworkProcess/NetworkLoadChecker.h
Source/WebKit/Shared/API/APIObject.h
Source/WebKit/Shared/Cocoa/APIObject.mm
Source/WebKit/Sources.txt
Source/WebKit/SourcesCocoa.txt
Source/WebKit/UIProcess/API/APIContentRuleListAction.cpp [new file with mode: 0644]
Source/WebKit/UIProcess/API/APIContentRuleListAction.h [new file with mode: 0644]
Source/WebKit/UIProcess/API/APINavigationClient.h
Source/WebKit/UIProcess/API/C/WKPage.cpp
Source/WebKit/UIProcess/API/Cocoa/WKNavigationDelegatePrivate.h
Source/WebKit/UIProcess/API/Cocoa/_WKContentRuleListAction.h [new file with mode: 0644]
Source/WebKit/UIProcess/API/Cocoa/_WKContentRuleListAction.mm [new file with mode: 0644]
Source/WebKit/UIProcess/API/Cocoa/_WKContentRuleListActionInternal.h [new file with mode: 0644]
Source/WebKit/UIProcess/Cocoa/NavigationState.h
Source/WebKit/UIProcess/Cocoa/NavigationState.mm
Source/WebKit/UIProcess/WebPageProxy.cpp
Source/WebKit/UIProcess/WebPageProxy.h
Source/WebKit/UIProcess/WebPageProxy.messages.in
Source/WebKit/WebKit.xcodeproj/project.pbxproj
Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.cpp
Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.h
Tools/ChangeLog
Tools/Scripts/webkitpy/common/system/abstractexecutive.py
Tools/Scripts/webkitpy/common/system/executive.py
Tools/Scripts/webkitpy/common/system/executive_mock.py
Tools/Scripts/webkitpy/common/system/executive_unittest.py
Tools/Scripts/webkitpy/port/darwin.py
Tools/Scripts/webkitpy/port/leakdetector.py
Tools/TestWebKitAPI/Tests/WebCore/ContentExtensions.cpp
Tools/TestWebKitAPI/Tests/WebKitCocoa/ContentRuleListNotification.mm
Tools/WebKitTestRunner/mac/WebKitTestRunnerEvent.mm

index 4cbb710..f188fdd 100644 (file)
@@ -1,3 +1,15 @@
+2019-03-21  Alex Christensen  <achristensen@webkit.org>
+
+        Add SPI to inform applications of WKContentRuleList actions
+        https://bugs.webkit.org/show_bug.cgi?id=195965
+        <rdar://problem/42664365>
+
+        Reviewed by Geoff Garen.
+
+        * http/tests/contentextensions/popups-expected.txt:
+        Because popups now use UserContentProvider.processContentRuleListsForLoad like everything else,
+        it now prints messages to the debug console.  That is a desired improvement, so expectations are updated accordingly.
+
 2019-03-21  Simon Fraser  <simon.fraser@apple.com>
 
         Add an internal feature flag to disable the -webkit-overflow-scrolling CSS property
index 1997344..69343fe 100644 (file)
@@ -1,3 +1,4 @@
+CONSOLE MESSAGE: line 10: Content blocker prevented frame displaying http://127.0.0.1:8000/contentextensions/popups.html from loading a resource from about:blank
 ALERT: about:blank successfully blocked
 ALERT: data url should not be blocked
 ALERT: data url should not be blocked
index 4ac7d95..11ea389 100644 (file)
@@ -1,3 +1,76 @@
+2019-03-21  Alex Christensen  <achristensen@webkit.org>
+
+        Add SPI to inform applications of WKContentRuleList actions
+        https://bugs.webkit.org/show_bug.cgi?id=195965
+        <rdar://problem/42664365>
+
+        Reviewed by Geoff Garen.
+
+        We already had SPI to inform the application of notifications.
+        In order to inform it about other actions, I needed to put them in a different structure.
+        Basically, instead of a Vector<Action> I use a Vector<Vector<Action>> that contains the same actions.
+        That way we can give one callback per WKContentRuleList.
+
+        * Modules/websockets/WebSocketChannel.cpp:
+        (WebCore::WebSocketChannel::connect):
+        * WebCore.xcodeproj/project.pbxproj:
+        * contentextensions/ContentExtensionActions.h:
+        * contentextensions/ContentExtensionParser.cpp:
+        (WebCore::ContentExtensions::loadEncodedRules):
+        * contentextensions/ContentExtensionRule.cpp:
+        (WebCore::ContentExtensions::Action::isolatedCopy const):
+        * contentextensions/ContentExtensionRule.h:
+        (WebCore::ContentExtensions::Action::operator== const):
+        (WebCore::ContentExtensions::Action::setExtensionIdentifier): Deleted.
+        (WebCore::ContentExtensions::Action::extensionIdentifier const): Deleted.
+        * contentextensions/ContentExtensionsBackend.cpp:
+        (WebCore::ContentExtensions::ContentExtensionsBackend::actionsForResourceLoad const):
+        (WebCore::ContentExtensions::ContentExtensionsBackend::processContentRuleListsForLoad):
+        (WebCore::ContentExtensions::ContentExtensionsBackend::processContentRuleListsForPingLoad):
+        (WebCore::ContentExtensions::applyResultsToRequest):
+        (WebCore::ContentExtensions::ContentExtensionsBackend::processContentExtensionRulesForLoad): Deleted.
+        (WebCore::ContentExtensions::ContentExtensionsBackend::processContentExtensionRulesForPingLoad): Deleted.
+        (WebCore::ContentExtensions::applyBlockedStatusToRequest): Deleted.
+        * contentextensions/ContentExtensionsBackend.h:
+        * contentextensions/ContentRuleListResults.h: Added.
+        (WebCore::ContentRuleListResults::Result::shouldNotifyApplication const):
+        (WebCore::ContentRuleListResults::shouldNotifyApplication const):
+        (WebCore::ContentRuleListResults::encode const):
+        (WebCore::ContentRuleListResults::decode):
+        (WebCore::ContentRuleListResults::Result::encode const):
+        (WebCore::ContentRuleListResults::Result::decode):
+        (WebCore::ContentRuleListResults::Summary::encode const):
+        (WebCore::ContentRuleListResults::Summary::decode):
+        * css/StyleSheetContents.cpp:
+        (WebCore::StyleSheetContents::subresourcesAllowReuse const):
+        * html/HTMLMediaElement.cpp:
+        (WebCore::HTMLMediaElement::loadResource):
+        * loader/FrameLoader.cpp:
+        (WebCore::FrameLoader::loadResourceSynchronously):
+        * loader/PingLoader.cpp:
+        (WebCore::processContentRuleListsForLoad):
+        (WebCore::PingLoader::loadImage):
+        (WebCore::PingLoader::sendPing):
+        (WebCore::PingLoader::sendViolationReport):
+        (WebCore::processContentExtensionRulesForLoad): Deleted.
+        * loader/ResourceLoader.cpp:
+        (WebCore::ResourceLoader::willSendRequestInternal):
+        * loader/cache/CachedResourceLoader.cpp:
+        (WebCore::CachedResourceLoader::requestResource):
+        * loader/cache/CachedResourceRequest.cpp:
+        (WebCore::CachedResourceRequest::applyResults):
+        (WebCore::CachedResourceRequest::applyBlockedStatus): Deleted.
+        * loader/cache/CachedResourceRequest.h:
+        * page/ChromeClient.h:
+        (WebCore::ChromeClient::contentRuleListNotification):
+        * page/DOMWindow.cpp:
+        (WebCore::DOMWindow::open):
+        * page/UserContentProvider.cpp:
+        (WebCore::UserContentProvider::processContentRuleListsForLoad):
+        (WebCore::UserContentProvider::actionsForResourceLoad):
+        (WebCore::UserContentProvider::processContentExtensionRulesForLoad): Deleted.
+        * page/UserContentProvider.h:
+
 2019-03-21  Simon Fraser  <simon.fraser@apple.com>
 
         Add an internal feature flag to disable the -webkit-overflow-scrolling CSS property
index 16f038d..c432dd4 100644 (file)
@@ -33,6 +33,7 @@
 #include "WebSocketChannel.h"
 
 #include "Blob.h"
+#include "ContentRuleListResults.h"
 #include "CookieJar.h"
 #include "Document.h"
 #include "FileError.h"
@@ -89,8 +90,8 @@ void WebSocketChannel::connect(const URL& requestedURL, const String& protocol)
 #if ENABLE(CONTENT_EXTENSIONS)
     if (auto* page = m_document->page()) {
         if (auto* documentLoader = m_document->loader()) {
-            auto blockedStatus = page->userContentProvider().processContentExtensionRulesForLoad(url, ResourceType::Raw, *documentLoader);
-            if (blockedStatus.blockedLoad) {
+            auto results = page->userContentProvider().processContentRuleListsForLoad(url, ResourceType::Raw, *documentLoader);
+            if (results.summary.blockedLoad) {
                 Ref<WebSocketChannel> protectedThis(*this);
                 callOnMainThread([protectedThis = WTFMove(protectedThis)] {
                     if (protectedThis->m_client)
@@ -98,13 +99,13 @@ void WebSocketChannel::connect(const URL& requestedURL, const String& protocol)
                 });
                 return;
             }
-            if (blockedStatus.madeHTTPS) {
+            if (results.summary.madeHTTPS) {
                 ASSERT(url.protocolIs("ws"));
                 url.setProtocol("wss");
                 if (m_client)
                     m_client->didUpgradeURL();
             }
-            if (blockedStatus.blockedCookies)
+            if (results.summary.blockedCookies)
                 allowCookies = false;
         }
     }
index e0f13c5..336b8a7 100644 (file)
                5C4304B1191AC908000E2BC0 /* EXTShaderTextureLOD.h in Headers */ = {isa = PBXBuildFile; fileRef = 5C4304AE191AC908000E2BC0 /* EXTShaderTextureLOD.h */; };
                5C4304B6191AEF46000E2BC0 /* JSEXTShaderTextureLOD.h in Headers */ = {isa = PBXBuildFile; fileRef = 5C4304B4191AEF46000E2BC0 /* JSEXTShaderTextureLOD.h */; };
                5C7C88D81D0F1F4A009D2F6D /* SocketProvider.h in Headers */ = {isa = PBXBuildFile; fileRef = 5C7C88D71D0F1F2B009D2F6D /* SocketProvider.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               5C9C2DB52241A67B00996B0B /* ContentRuleListResults.h in Headers */ = {isa = PBXBuildFile; fileRef = 5C9C2DB32241A67300996B0B /* ContentRuleListResults.h */; settings = {ATTRIBUTES = (Private, ); }; };
                5C9EF2F321F06190003BDC56 /* StorageSessionProvider.h in Headers */ = {isa = PBXBuildFile; fileRef = 5C9EF2F221F06171003BDC56 /* StorageSessionProvider.h */; settings = {ATTRIBUTES = (Private, ); }; };
                5CA1DEC61F71F1C700E71BD3 /* HTTPHeaderField.h in Headers */ = {isa = PBXBuildFile; fileRef = 5CA1DEC41F71E68700E71BD3 /* HTTPHeaderField.h */; settings = {ATTRIBUTES = (Private, ); }; };
                5CB37FFF1C62D2A100F20188 /* ScrollAnimatorMock.h in Headers */ = {isa = PBXBuildFile; fileRef = 5CB37FFD1C62D27800F20188 /* ScrollAnimatorMock.h */; };
                5C7C88D71D0F1F2B009D2F6D /* SocketProvider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SocketProvider.h; sourceTree = "<group>"; };
                5C97A3361F5F7A6500105207 /* RectEdges.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RectEdges.h; sourceTree = "<group>"; };
                5C9B860B1C21E3C600110F36 /* NetworkLoadMetrics.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = NetworkLoadMetrics.mm; sourceTree = "<group>"; };
+               5C9C2DB32241A67300996B0B /* ContentRuleListResults.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ContentRuleListResults.h; sourceTree = "<group>"; };
                5C9EF16F1DFF719900A452E3 /* XPathGrammar.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = XPathGrammar.cpp; sourceTree = "<group>"; };
                5C9EF1701DFF719900A452E3 /* XPathGrammar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XPathGrammar.h; sourceTree = "<group>"; };
                5C9EF2F221F06171003BDC56 /* StorageSessionProvider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StorageSessionProvider.h; sourceTree = "<group>"; };
                                262391351A648CEE007251A3 /* ContentExtensionsDebugging.h */,
                                51FB67D91AE6B5E400D06C5A /* ContentExtensionStyleSheet.cpp */,
                                51FB67DA1AE6B5E400D06C5A /* ContentExtensionStyleSheet.h */,
+                               5C9C2DB32241A67300996B0B /* ContentRuleListResults.h */,
                                267725F61A5B3AD9003C24DD /* DFA.cpp */,
                                267725F71A5B3AD9003C24DD /* DFA.h */,
                                5C39305D1AA0F6A90029C816 /* DFABytecode.h */,
                                51FB67DC1AE6B82F00D06C5A /* ContentExtensionStyleSheet.h in Headers */,
                                A149786F1ABAF33800CEF7E4 /* ContentFilter.h in Headers */,
                                A14090FD1AA51E480091191A /* ContentFilterUnblockHandler.h in Headers */,
+                               5C9C2DB52241A67B00996B0B /* ContentRuleListResults.h in Headers */,
                                97C471DC12F925BD0086354B /* ContentSecurityPolicy.h in Headers */,
                                CE5FA255209E48C50051D700 /* ContentSecurityPolicyClient.h in Headers */,
                                CE799FA41C6A503A0097B518 /* ContentSecurityPolicyDirective.h in Headers */,
index cb02ead..5efac15 100644 (file)
 
 namespace WebCore {
 
+struct ContentRuleListResults;
 class Page;
 class ResourceRequest;
 
 namespace ContentExtensions {
 
-typedef uint8_t SerializedActionByte;
+struct Action;
+using SerializedActionByte = uint8_t;
 
 enum class ActionType : uint8_t {
     BlockLoad,
@@ -64,14 +66,13 @@ static inline bool hasStringArgument(ActionType actionType)
     return false;
 }
 
-struct BlockedStatus {
-    bool blockedLoad { false };
-    bool blockedCookies { false };
-    bool madeHTTPS { false };
-    HashSet<std::pair<String, String>> notifications;
+struct ActionsFromContentRuleList {
+    String contentRuleListIdentifier;
+    bool sawIgnorePreviousRules { false };
+    Vector<Action> actions;
 };
 
-WEBCORE_EXPORT void applyBlockedStatusToRequest(const BlockedStatus&, Page*, ResourceRequest&);
+WEBCORE_EXPORT void applyResultsToRequest(ContentRuleListResults&&, Page*, ResourceRequest&);
 
 } // namespace ContentExtensions
 
index 04e95fa..89b2d43 100644 (file)
@@ -287,7 +287,7 @@ std::error_code compileRuleList(ContentExtensionCompilationClient& client, Strin
 {
 #if !ASSERT_DISABLED
     callOnMainThread([ruleJSON = ruleJSON.isolatedCopy(), parsedRuleList = parsedRuleList.isolatedCopy()] {
-        ASSERT(parseRuleList(ruleJSON) == parsedRuleList);
+        ASSERT(parseRuleList(ruleJSON).value() == parsedRuleList);
     });
 #endif
 
index cefb279..286c80a 100644 (file)
@@ -342,7 +342,7 @@ static Expected<Vector<ContentExtensionRule>, std::error_code> loadEncodedRules(
         if (!rule.has_value())
             return makeUnexpected(rule.error());
         if (rule.value())
-            ruleList.append(*rule.value());
+            ruleList.append(WTFMove(*rule.value()));
     }
 
     return ruleList;
@@ -374,7 +374,7 @@ Expected<Vector<ContentExtensionRule>, std::error_code> parseRuleList(const Stri
     dataLogF("Time spent loading extension %f\n", (loadExtensionEndTime - loadExtensionStartTime).seconds());
 #endif
 
-    return *ruleList;
+    return ruleList;
 }
 
 } // namespace ContentExtensions
index ddc2258..93d3843 100644 (file)
@@ -127,12 +127,18 @@ Trigger Trigger::isolatedCopy() const
 
 Action Action::isolatedCopy() const
 {
-    return {
-        m_extensionIdentifier.isolatedCopy(),
-        m_type,
-        m_actionID,
-        m_stringArgument.isolatedCopy()
-    };
+    if (hasStringArgument(m_type)) {
+        return {
+            m_type,
+            m_stringArgument.isolatedCopy(),
+            m_actionID
+        };
+    } else {
+        return {
+            m_type,
+            m_actionID
+        };
+    }
 }
 
 } // namespace ContentExtensions
index cebf13e..398e74c 100644 (file)
@@ -148,11 +148,11 @@ struct Action {
     {
         ASSERT(!hasStringArgument(type));
     }
+    Action(Action&&) = default;
 
     bool operator==(const Action& other) const
     {
         return m_type == other.m_type
-            && m_extensionIdentifier == other.m_extensionIdentifier
             && m_actionID == other.m_actionID
             && m_stringArgument == other.m_stringArgument;
     }
@@ -161,8 +161,6 @@ struct Action {
     static ActionType deserializeType(const SerializedActionByte* actions, const uint32_t actionsLength, uint32_t location);
     static uint32_t serializedLength(const SerializedActionByte* actions, const uint32_t actionsLength, uint32_t location);
 
-    void setExtensionIdentifier(const String& extensionIdentifier) { m_extensionIdentifier = extensionIdentifier; }
-    const String& extensionIdentifier() const { return m_extensionIdentifier; }
     ActionType type() const { return m_type; }
     uint32_t actionID() const { return m_actionID; }
     const String& stringArgument() const { return m_stringArgument; }
@@ -170,14 +168,6 @@ struct Action {
     WEBCORE_EXPORT Action isolatedCopy() const;
     
 private:
-    Action(String&& extensionIdentifier, ActionType type, uint32_t actionID, String&& stringArgument)
-        : m_extensionIdentifier(WTFMove(extensionIdentifier))
-        , m_type(type)
-        , m_actionID(actionID)
-        , m_stringArgument(WTFMove(stringArgument))
-    { }
-
-    String m_extensionIdentifier;
     ActionType m_type;
     uint32_t m_actionID;
     String m_stringArgument;
index d0eaba0..31a774d 100644 (file)
@@ -33,6 +33,7 @@
 #include "CompiledContentExtension.h"
 #include "ContentExtension.h"
 #include "ContentExtensionsDebugging.h"
+#include "ContentRuleListResults.h"
 #include "DFABytecodeInterpreter.h"
 #include "Document.h"
 #include "DocumentLoader.h"
@@ -70,7 +71,7 @@ void ContentExtensionsBackend::removeAllContentExtensions()
     m_contentExtensions.clear();
 }
 
-std::pair<Vector<Action>, Vector<String>> ContentExtensionsBackend::actionsForResourceLoad(const ResourceLoadInfo& resourceLoadInfo) const
+auto ContentExtensionsBackend::actionsForResourceLoad(const ResourceLoadInfo& resourceLoadInfo) const -> Vector<ActionsFromContentRuleList>
 {
 #if CONTENT_EXTENSIONS_PERFORMANCE_REPORTING
     MonotonicTime addedTimeStart = MonotonicTime::now();
@@ -84,10 +85,13 @@ std::pair<Vector<Action>, Vector<String>> ContentExtensionsBackend::actionsForRe
     ASSERT_WITH_MESSAGE(urlString.isAllASCII(), "A decoded URL should only contain ASCII characters. The matching algorithm assumes the input is ASCII.");
     const auto urlCString = urlString.utf8();
 
-    Vector<Action> finalActions;
-    Vector<String> stylesheetIdentifiers;
-    ResourceFlags flags = resourceLoadInfo.getResourceFlags();
+    Vector<ActionsFromContentRuleList> actionsVector;
+    actionsVector.reserveInitialCapacity(m_contentExtensions.size());
+    const ResourceFlags flags = resourceLoadInfo.getResourceFlags();
     for (auto& contentExtension : m_contentExtensions.values()) {
+        ActionsFromContentRuleList actionsStruct;
+        actionsStruct.contentRuleListIdentifier = contentExtension->identifier();
+
         const CompiledContentExtension& compiledExtension = contentExtension->compiledExtension();
         
         DFABytecodeInterpreter withoutConditionsInterpreter(compiledExtension.filtersWithoutConditionsBytecode(), compiledExtension.filtersWithoutConditionsBytecodeLength());
@@ -100,7 +104,6 @@ std::pair<Vector<Action>, Vector<String>> ContentExtensionsBackend::actionsForRe
         const SerializedActionByte* actions = compiledExtension.actions();
         const unsigned actionsLength = compiledExtension.actionsLength();
         
-        bool sawIgnorePreviousRules = false;
         const Vector<uint32_t>& universalWithConditions = contentExtension->universalActionsWithConditions(topURL);
         const Vector<uint32_t>& universalWithoutConditions = contentExtension->universalActionsWithoutConditions();
         if (!withoutConditionsActions.isEmpty() || !withConditionsActions.isEmpty() || !universalWithConditions.isEmpty() || !universalWithoutConditions.isEmpty()) {
@@ -119,22 +122,20 @@ std::pair<Vector<Action>, Vector<String>> ContentExtensionsBackend::actionsForRe
             // Add actions in reverse order to properly deal with IgnorePreviousRules.
             for (unsigned i = actionLocations.size(); i; i--) {
                 Action action = Action::deserialize(actions, actionsLength, actionLocations[i - 1]);
-                action.setExtensionIdentifier(contentExtension->identifier());
                 if (action.type() == ActionType::IgnorePreviousRules) {
-                    sawIgnorePreviousRules = true;
+                    actionsStruct.sawIgnorePreviousRules = true;
                     break;
                 }
-                finalActions.append(action);
+                actionsStruct.actions.append(WTFMove(action));
             }
         }
-        if (!sawIgnorePreviousRules)
-            stylesheetIdentifiers.append(contentExtension->identifier());
+        actionsVector.uncheckedAppend(WTFMove(actionsStruct));
     }
 #if CONTENT_EXTENSIONS_PERFORMANCE_REPORTING
     MonotonicTime addedTimeEnd = MonotonicTime::now();
     dataLogF("Time added: %f microseconds %s \n", (addedTimeEnd - addedTimeStart).microseconds(), resourceLoadInfo.resourceURL.string().utf8().data());
 #endif
-    return { WTFMove(finalActions), WTFMove(stylesheetIdentifiers) };
+    return actionsVector;
 }
 
 void ContentExtensionsBackend::forEach(const WTF::Function<void(const String&, ContentExtension&)>& apply)
@@ -149,7 +150,7 @@ StyleSheetContents* ContentExtensionsBackend::globalDisplayNoneStyleSheet(const
     return contentExtension ? contentExtension->globalDisplayNoneStyleSheet() : nullptr;
 }
 
-BlockedStatus ContentExtensionsBackend::processContentExtensionRulesForLoad(const URL& url, ResourceType resourceType, DocumentLoader& initiatingDocumentLoader)
+ContentRuleListResults ContentExtensionsBackend::processContentRuleListsForLoad(const URL& url, ResourceType resourceType, DocumentLoader& initiatingDocumentLoader)
 {
     if (m_contentExtensions.isEmpty())
         return { };
@@ -171,60 +172,70 @@ BlockedStatus ContentExtensionsBackend::processContentExtensionRulesForLoad(cons
     ResourceLoadInfo resourceLoadInfo = { url, mainDocumentURL, resourceType };
     auto actions = actionsForResourceLoad(resourceLoadInfo);
 
-    bool willBlockLoad = false;
-    bool willBlockCookies = false;
-    bool willMakeHTTPS = false;
-    HashSet<std::pair<String, String>> notifications;
-    for (const auto& action : actions.first) {
-        switch (action.type()) {
-        case ContentExtensions::ActionType::BlockLoad:
-            willBlockLoad = true;
-            break;
-        case ContentExtensions::ActionType::BlockCookies:
-            willBlockCookies = true;
-            break;
-        case ContentExtensions::ActionType::CSSDisplayNoneSelector:
-            if (resourceType == ResourceType::Document)
-                initiatingDocumentLoader.addPendingContentExtensionDisplayNoneSelector(action.extensionIdentifier(), action.stringArgument(), action.actionID());
-            else if (currentDocument)
-                currentDocument->extensionStyleSheets().addDisplayNoneSelector(action.extensionIdentifier(), action.stringArgument(), action.actionID());
-            break;
-        case ContentExtensions::ActionType::Notify:
-            notifications.add(std::make_pair(action.extensionIdentifier(), action.stringArgument()));
-            break;
-        case ContentExtensions::ActionType::MakeHTTPS: {
-            if ((url.protocolIs("http") || url.protocolIs("ws"))
-                && (!url.port() || WTF::isDefaultPortForProtocol(url.port().value(), url.protocol())))
-                willMakeHTTPS = true;
-            break;
-        }
-        case ContentExtensions::ActionType::IgnorePreviousRules:
-            RELEASE_ASSERT_NOT_REACHED();
+    ContentRuleListResults results;
+    results.results.reserveInitialCapacity(actions.size());
+    for (const auto& actionsFromContentRuleList : actions) {
+        const String& contentRuleListIdentifier = actionsFromContentRuleList.contentRuleListIdentifier;
+        ContentRuleListResults::Result result;
+        for (const auto& action : actionsFromContentRuleList.actions) {
+            switch (action.type()) {
+            case ContentExtensions::ActionType::BlockLoad:
+                results.summary.blockedLoad = true;
+                result.blockedLoad = true;
+                break;
+            case ContentExtensions::ActionType::BlockCookies:
+                results.summary.blockedCookies = true;
+                result.blockedCookies = true;
+                break;
+            case ContentExtensions::ActionType::CSSDisplayNoneSelector:
+                if (resourceType == ResourceType::Document)
+                    initiatingDocumentLoader.addPendingContentExtensionDisplayNoneSelector(contentRuleListIdentifier, action.stringArgument(), action.actionID());
+                else if (currentDocument)
+                    currentDocument->extensionStyleSheets().addDisplayNoneSelector(contentRuleListIdentifier, action.stringArgument(), action.actionID());
+                break;
+            case ContentExtensions::ActionType::Notify:
+                results.summary.hasNotifications = true;
+                result.notifications.append(action.stringArgument());
+                break;
+            case ContentExtensions::ActionType::MakeHTTPS: {
+                if ((url.protocolIs("http") || url.protocolIs("ws"))
+                    && (!url.port() || WTF::isDefaultPortForProtocol(url.port().value(), url.protocol()))) {
+                    results.summary.madeHTTPS = true;
+                    result.madeHTTPS = true;
+                }
+                break;
+            }
+            case ContentExtensions::ActionType::IgnorePreviousRules:
+                RELEASE_ASSERT_NOT_REACHED();
+            }
         }
-    }
 
-    for (const auto& identifier : actions.second) {
-        if (auto* styleSheetContents = globalDisplayNoneStyleSheet(identifier)) {
-            if (resourceType == ResourceType::Document)
-                initiatingDocumentLoader.addPendingContentExtensionSheet(identifier, *styleSheetContents);
-            else if (currentDocument)
-                currentDocument->extensionStyleSheets().maybeAddContentExtensionSheet(identifier, *styleSheetContents);
+        if (!actionsFromContentRuleList.sawIgnorePreviousRules) {
+            if (auto* styleSheetContents = globalDisplayNoneStyleSheet(contentRuleListIdentifier)) {
+                if (resourceType == ResourceType::Document)
+                    initiatingDocumentLoader.addPendingContentExtensionSheet(contentRuleListIdentifier, *styleSheetContents);
+                else if (currentDocument)
+                    currentDocument->extensionStyleSheets().maybeAddContentExtensionSheet(contentRuleListIdentifier, *styleSheetContents);
+            }
         }
+
+        results.results.uncheckedAppend({ contentRuleListIdentifier, WTFMove(result) });
     }
 
     if (currentDocument) {
-        if (willMakeHTTPS) {
+        if (results.summary.madeHTTPS) {
             ASSERT(url.protocolIs("http") || url.protocolIs("ws"));
             String newProtocol = url.protocolIs("http") ? "https"_s : "wss"_s;
             currentDocument->addConsoleMessage(MessageSource::ContentBlocker, MessageLevel::Info, makeString("Content blocker promoted URL from ", url.string(), " to ", newProtocol));
         }
-        if (willBlockLoad)
+        if (results.summary.blockedLoad)
             currentDocument->addConsoleMessage(MessageSource::ContentBlocker, MessageLevel::Info, makeString("Content blocker prevented frame displaying ", mainDocumentURL.string(), " from loading a resource from ", url.string()));
     }
-    return { willBlockLoad, willBlockCookies, willMakeHTTPS, WTFMove(notifications) };
+
+    return results;
 }
 
-BlockedStatus ContentExtensionsBackend::processContentExtensionRulesForPingLoad(const URL& url, const URL& mainDocumentURL)
+ContentRuleListResults ContentExtensionsBackend::processContentRuleListsForPingLoad(const URL& url, const URL& mainDocumentURL)
 {
     if (m_contentExtensions.isEmpty())
         return { };
@@ -232,30 +243,31 @@ BlockedStatus ContentExtensionsBackend::processContentExtensionRulesForPingLoad(
     ResourceLoadInfo resourceLoadInfo = { url, mainDocumentURL, ResourceType::Raw };
     auto actions = actionsForResourceLoad(resourceLoadInfo);
 
-    bool willBlockLoad = false;
-    bool willBlockCookies = false;
-    bool willMakeHTTPS = false;
-    for (const auto& action : actions.first) {
-        switch (action.type()) {
-        case ContentExtensions::ActionType::BlockLoad:
-            willBlockLoad = true;
-            break;
-        case ContentExtensions::ActionType::BlockCookies:
-            willBlockCookies = true;
-            break;
-        case ContentExtensions::ActionType::MakeHTTPS:
-            if ((url.protocolIs("http") || url.protocolIs("ws")) && (!url.port() || WTF::isDefaultPortForProtocol(url.port().value(), url.protocol())))
-                willMakeHTTPS = true;
-            break;
-        case ContentExtensions::ActionType::CSSDisplayNoneSelector:
-        case ContentExtensions::ActionType::Notify:
-            break;
-        case ContentExtensions::ActionType::IgnorePreviousRules:
-            RELEASE_ASSERT_NOT_REACHED();
+    ContentRuleListResults results;
+    for (const auto& actionsFromContentRuleList : actions) {
+        for (const auto& action : actionsFromContentRuleList.actions) {
+            switch (action.type()) {
+            case ContentExtensions::ActionType::BlockLoad:
+                results.summary.blockedLoad = true;
+                break;
+            case ContentExtensions::ActionType::BlockCookies:
+                results.summary.blockedCookies = true;
+                break;
+            case ContentExtensions::ActionType::MakeHTTPS:
+                if ((url.protocolIs("http") || url.protocolIs("ws")) && (!url.port() || WTF::isDefaultPortForProtocol(url.port().value(), url.protocol())))
+                    results.summary.madeHTTPS = true;
+                break;
+            case ContentExtensions::ActionType::CSSDisplayNoneSelector:
+            case ContentExtensions::ActionType::Notify:
+                // We currently have not implemented notifications from the NetworkProcess to the UIProcess.
+                break;
+            case ContentExtensions::ActionType::IgnorePreviousRules:
+                RELEASE_ASSERT_NOT_REACHED();
+            }
         }
     }
 
-    return { willBlockLoad, willBlockCookies, willMakeHTTPS, { } };
+    return results;
 }
 
 const String& ContentExtensionsBackend::displayNoneCSSRule()
@@ -264,15 +276,12 @@ const String& ContentExtensionsBackend::displayNoneCSSRule()
     return rule;
 }
 
-void applyBlockedStatusToRequest(const BlockedStatus& status, Page* page, ResourceRequest& request)
+void applyResultsToRequest(ContentRuleListResults&& results, Page* page, ResourceRequest& request)
 {
-    if (page && !status.notifications.isEmpty())
-        page->chrome().client().contentRuleListNotification(request.url(), status.notifications);
-
-    if (status.blockedCookies)
+    if (results.summary.blockedCookies)
         request.setAllowCookies(false);
 
-    if (status.madeHTTPS) {
+    if (results.summary.madeHTTPS) {
         const URL& originalURL = request.url();
         ASSERT(originalURL.protocolIs("http"));
         ASSERT(!originalURL.port() || WTF::isDefaultPortForProtocol(originalURL.port().value(), originalURL.protocol()));
@@ -283,6 +292,13 @@ void applyBlockedStatusToRequest(const BlockedStatus& status, Page* page, Resour
             newURL.setPort(WTF::defaultPortForProtocol("https").value());
         request.setURL(newURL);
     }
+
+    if (page && results.shouldNotifyApplication()) {
+        results.results.removeAllMatching([](const auto& pair) {
+            return !pair.second.shouldNotifyApplication();
+        });
+        page->chrome().client().contentRuleListNotification(request.url(), results);
+    }
 }
     
 } // namespace ContentExtensions
index 34cfaca..c7375a3 100644 (file)
@@ -60,15 +60,15 @@ public:
     WEBCORE_EXPORT void removeAllContentExtensions();
 
     // - Internal WebCore Interface.
-    WEBCORE_EXPORT std::pair<Vector<Action>, Vector<String>> actionsForResourceLoad(const ResourceLoadInfo&) const;
+    WEBCORE_EXPORT Vector<ActionsFromContentRuleList> actionsForResourceLoad(const ResourceLoadInfo&) const;
     WEBCORE_EXPORT StyleSheetContents* globalDisplayNoneStyleSheet(const String& identifier) const;
 
-    BlockedStatus processContentExtensionRulesForLoad(const URL&, ResourceType, DocumentLoader& initiatingDocumentLoader);
-    WEBCORE_EXPORT BlockedStatus processContentExtensionRulesForPingLoad(const URL&, const URL& mainDocumentURL);
+    ContentRuleListResults processContentRuleListsForLoad(const URL&, ResourceType, DocumentLoader& initiatingDocumentLoader);
+    WEBCORE_EXPORT ContentRuleListResults processContentRuleListsForPingLoad(const URL&, const URL& mainDocumentURL);
 
     static const String& displayNoneCSSRule();
 
-    void forEach(const WTF::Function<void(const String&, ContentExtension&)>&);
+    void forEach(const Function<void(const String&, ContentExtension&)>&);
 
 private:
     HashMap<String, Ref<ContentExtension>> m_contentExtensions;
diff --git a/Source/WebCore/contentextensions/ContentRuleListResults.h b/Source/WebCore/contentextensions/ContentRuleListResults.h
new file mode 100644 (file)
index 0000000..9a7be5a
--- /dev/null
@@ -0,0 +1,174 @@
+/*
+ * Copyright (C) 2019 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 <wtf/KeyValuePair.h>
+#include <wtf/Vector.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+    
+struct ContentRuleListResults {
+    struct Result {
+        bool blockedLoad { false };
+        bool madeHTTPS { false };
+        bool blockedCookies { false };
+        Vector<String> notifications;
+        
+        bool shouldNotifyApplication() const
+        {
+            return blockedLoad
+                || madeHTTPS
+                || blockedCookies
+                || !notifications.isEmpty();
+        }
+
+        template<class Encoder> void encode(Encoder&) const;
+        template<class Decoder> static Optional<Result> decode(Decoder&);
+    };
+    struct Summary {
+        bool blockedLoad { false };
+        bool madeHTTPS { false };
+        bool blockedCookies { false };
+        bool hasNotifications { false };
+
+        template<class Encoder> void encode(Encoder&) const;
+        template<class Decoder> static Optional<Summary> decode(Decoder&);
+    };
+    using ContentRuleListIdentifier = String;
+
+    Summary summary;
+    Vector<std::pair<ContentRuleListIdentifier, Result>> results;
+    
+    bool shouldNotifyApplication() const
+    {
+        return summary.blockedLoad
+            || summary.madeHTTPS
+            || summary.blockedCookies
+            || summary.hasNotifications;
+    }
+    
+    template<class Encoder> void encode(Encoder& encoder) const
+    {
+        encoder << summary;
+        encoder << results;
+    }
+    template<class Decoder> static Optional<ContentRuleListResults> decode(Decoder& decoder)
+    {
+        Optional<Summary> summary;
+        decoder >> summary;
+        if (!summary)
+            return WTF::nullopt;
+        
+        Optional<Vector<std::pair<ContentRuleListIdentifier, Result>>> results;
+        decoder >> results;
+        if (!results)
+            return WTF::nullopt;
+        
+        return {{
+            WTFMove(*summary),
+            WTFMove(*results)
+        }};
+    }
+};
+
+template<class Encoder> void ContentRuleListResults::Result::encode(Encoder& encoder) const
+{
+    encoder << blockedLoad;
+    encoder << madeHTTPS;
+    encoder << blockedCookies;
+    encoder << notifications;
+}
+
+template<class Decoder> auto ContentRuleListResults::Result::decode(Decoder& decoder) -> Optional<Result>
+{
+    Optional<bool> blockedLoad;
+    decoder >> blockedLoad;
+    if (!blockedLoad)
+        return WTF::nullopt;
+    
+    Optional<bool> madeHTTPS;
+    decoder >> madeHTTPS;
+    if (!madeHTTPS)
+        return WTF::nullopt;
+    
+    Optional<bool> blockedCookies;
+    decoder >> blockedCookies;
+    if (!blockedCookies)
+        return WTF::nullopt;
+    
+    Optional<Vector<String>> notifications;
+    decoder >> notifications;
+    if (!notifications)
+        return WTF::nullopt;
+
+    return {{
+        WTFMove(*blockedLoad),
+        WTFMove(*madeHTTPS),
+        WTFMove(*blockedCookies),
+        WTFMove(*notifications)
+    }};
+}
+
+template<class Encoder> void ContentRuleListResults::Summary::encode(Encoder& encoder) const
+{
+    encoder << blockedLoad;
+    encoder << madeHTTPS;
+    encoder << blockedCookies;
+    encoder << hasNotifications;
+}
+
+template<class Decoder> auto ContentRuleListResults::Summary::decode(Decoder& decoder) -> Optional<Summary>
+{
+    Optional<bool> blockedLoad;
+    decoder >> blockedLoad;
+    if (!blockedLoad)
+        return WTF::nullopt;
+    
+    Optional<bool> madeHTTPS;
+    decoder >> madeHTTPS;
+    if (!madeHTTPS)
+        return WTF::nullopt;
+    
+    Optional<bool> blockedCookies;
+    decoder >> blockedCookies;
+    if (!blockedCookies)
+        return WTF::nullopt;
+    
+    Optional<bool> hasNotifications;
+    decoder >> hasNotifications;
+    if (!hasNotifications)
+        return WTF::nullopt;
+    
+    return {{
+        WTFMove(*blockedLoad),
+        WTFMove(*madeHTTPS),
+        WTFMove(*blockedCookies),
+        WTFMove(*hasNotifications),
+    }};
+}
+
+}
index 7a6b40f..7e5ed1e 100644 (file)
@@ -25,6 +25,7 @@
 #include "CSSParser.h"
 #include "CSSStyleSheet.h"
 #include "CachedCSSStyleSheet.h"
+#include "ContentRuleListResults.h"
 #include "Document.h"
 #include "Frame.h"
 #include "FrameLoader.h"
@@ -511,8 +512,8 @@ bool StyleSheetContents::subresourcesAllowReuse(CachePolicy cachePolicy, FrameLo
         auto* documentLoader = loader.documentLoader();
         if (page && documentLoader) {
             const auto& request = resource.resourceRequest();
-            auto blockedStatus = page->userContentProvider().processContentExtensionRulesForLoad(request.url(), toResourceType(resource.type()), *documentLoader);
-            if (blockedStatus.blockedLoad || blockedStatus.madeHTTPS)
+            auto results = page->userContentProvider().processContentRuleListsForLoad(request.url(), toResourceType(resource.type()), *documentLoader);
+            if (results.summary.blockedLoad || results.summary.madeHTTPS)
                 return true;
         }
 #else
index 9b2e963..2e8bdab 100644 (file)
@@ -36,6 +36,7 @@
 #include "CSSValueKeywords.h"
 #include "ChromeClient.h"
 #include "CommonVM.h"
+#include "ContentRuleListResults.h"
 #include "ContentSecurityPolicy.h"
 #include "ContentType.h"
 #include "CookieJar.h"
@@ -1519,7 +1520,7 @@ void HTMLMediaElement::loadResource(const URL& initialURL, ContentType& contentT
 
 #if ENABLE(CONTENT_EXTENSIONS)
     if (auto documentLoader = makeRefPtr(frame->loader().documentLoader())) {
-        if (page->userContentProvider().processContentExtensionRulesForLoad(url, ResourceType::Media, *documentLoader).blockedLoad) {
+        if (page->userContentProvider().processContentRuleListsForLoad(url, ResourceType::Media, *documentLoader).summary.blockedLoad) {
             mediaLoadingFailed(MediaPlayer::FormatError);
             return;
         }
index 20f0a6f..8ffd7de 100644 (file)
@@ -45,6 +45,7 @@
 #include "ChromeClient.h"
 #include "CommonVM.h"
 #include "ContentFilter.h"
+#include "ContentRuleListResults.h"
 #include "ContentSecurityPolicy.h"
 #include "DOMWindow.h"
 #include "DatabaseManager.h"
@@ -3064,9 +3065,10 @@ unsigned long FrameLoader::loadResourceSynchronously(const ResourceRequest& requ
     if (error.isNull()) {
         if (auto* page = m_frame.page()) {
             if (m_documentLoader) {
-                auto blockedStatus = page->userContentProvider().processContentExtensionRulesForLoad(newRequest.url(), ResourceType::Raw, *m_documentLoader);
-                applyBlockedStatusToRequest(blockedStatus, page, newRequest);
-                if (blockedStatus.blockedLoad) {
+                auto results = page->userContentProvider().processContentRuleListsForLoad(newRequest.url(), ResourceType::Raw, *m_documentLoader);
+                bool blockedLoad = results.summary.blockedLoad;
+                ContentExtensions::applyResultsToRequest(WTFMove(results), page, newRequest);
+                if (blockedLoad) {
                     newRequest = { };
                     error = ResourceError(errorDomainWebKitInternal, 0, initialRequest.url(), emptyString());
                     response = { };
index 2c0b2a3..54c18a7 100644 (file)
@@ -34,6 +34,7 @@
 #include "config.h"
 #include "PingLoader.h"
 
+#include "ContentRuleListResults.h"
 #include "ContentSecurityPolicy.h"
 #include "Document.h"
 #include "Frame.h"
@@ -59,7 +60,7 @@ namespace WebCore {
 #if !ENABLE(CONTENT_EXTENSIONS)
 
 // Returns true if we should block the load.
-static inline bool processContentExtensionRulesForLoad(const Frame&, ResourceRequest&, ResourceType)
+static inline bool processContentRuleListsForLoad(const Frame&, ResourceRequest&, ResourceType)
 {
     return false;
 }
@@ -67,7 +68,7 @@ static inline bool processContentExtensionRulesForLoad(const Frame&, ResourceReq
 #else
 
 // Returns true if we should block the load.
-static bool processContentExtensionRulesForLoad(const Frame& frame, ResourceRequest& request, ResourceType resourceType)
+static bool processContentRuleListsForLoad(const Frame& frame, ResourceRequest& request, ResourceType resourceType)
 {
     auto* documentLoader = frame.loader().documentLoader();
     if (!documentLoader)
@@ -75,9 +76,10 @@ static bool processContentExtensionRulesForLoad(const Frame& frame, ResourceRequ
     auto* page = frame.page();
     if (!page)
         return false;
-    auto status = page->userContentProvider().processContentExtensionRulesForLoad(request.url(), resourceType, *documentLoader);
-    applyBlockedStatusToRequest(status, page, request);
-    return status.blockedLoad;
+    auto results = page->userContentProvider().processContentRuleListsForLoad(request.url(), resourceType, *documentLoader);
+    bool result = results.summary.blockedLoad;
+    ContentExtensions::applyResultsToRequest(WTFMove(results), page, request);
+    return result;
 }
 
 #endif
@@ -93,7 +95,7 @@ void PingLoader::loadImage(Frame& frame, const URL& url)
     }
 
     ResourceRequest request(url);
-    if (processContentExtensionRulesForLoad(frame, request, ResourceType::Image))
+    if (processContentRuleListsForLoad(frame, request, ResourceType::Image))
         return;
 
     document.contentSecurityPolicy()->upgradeInsecureRequestIfNeeded(request, ContentSecurityPolicy::InsecureRequestType::Load);
@@ -119,7 +121,7 @@ void PingLoader::sendPing(Frame& frame, const URL& pingURL, const URL& destinati
         return;
 
     ResourceRequest request(pingURL);
-    if (processContentExtensionRulesForLoad(frame, request, ResourceType::Raw))
+    if (processContentRuleListsForLoad(frame, request, ResourceType::Raw))
         return;
 
     auto& document = *frame.document();
@@ -154,7 +156,7 @@ void PingLoader::sendViolationReport(Frame& frame, const URL& reportURL, Ref<For
     ASSERT(frame.document());
 
     ResourceRequest request(reportURL);
-    if (processContentExtensionRulesForLoad(frame, request, ResourceType::Raw))
+    if (processContentRuleListsForLoad(frame, request, ResourceType::Raw))
         return;
 
     auto& document = *frame.document();
index 6c2b131..54898ef 100644 (file)
@@ -32,6 +32,7 @@
 
 #include "ApplicationCacheHost.h"
 #include "AuthenticationChallenge.h"
+#include "ContentRuleListResults.h"
 #include "DataURLDecoder.h"
 #include "DiagnosticLoggingClient.h"
 #include "DiagnosticLoggingKeys.h"
@@ -355,9 +356,10 @@ void ResourceLoader::willSendRequestInternal(ResourceRequest&& request, const Re
     if (!redirectResponse.isNull() && frameLoader()) {
         Page* page = frameLoader()->frame().page();
         if (page && m_documentLoader) {
-            auto blockedStatus = page->userContentProvider().processContentExtensionRulesForLoad(request.url(), m_resourceType, *m_documentLoader);
-            applyBlockedStatusToRequest(blockedStatus, page, request);
-            if (blockedStatus.blockedLoad) {
+            auto results = page->userContentProvider().processContentRuleListsForLoad(request.url(), m_resourceType, *m_documentLoader);
+            bool blockedLoad = results.summary.blockedLoad;
+            ContentExtensions::applyResultsToRequest(WTFMove(results), page, request);
+            if (blockedLoad) {
                 RELEASE_LOG_IF_ALLOWED("willSendRequestinternal: resource load canceled because of content blocker (frame = %p, frameLoader = %p, resourceID = %lu)", frame(), frameLoader(), identifier());
                 didFail(blockedByContentBlockerError());
                 completionHandler({ });
index 3ab9d76..26aa729 100644 (file)
@@ -40,6 +40,7 @@
 #include "ChromeClient.h"
 #include "ContentExtensionError.h"
 #include "ContentExtensionRule.h"
+#include "ContentRuleListResults.h"
 #include "ContentSecurityPolicy.h"
 #include "CrossOriginAccessControl.h"
 #include "DOMWindow.h"
@@ -808,9 +809,11 @@ ResourceErrorOr<CachedResourceHandle<CachedResource>> CachedResourceLoader::requ
     if (frame() && frame()->page() && m_documentLoader) {
         const auto& resourceRequest = request.resourceRequest();
         auto* page = frame()->page();
-        auto blockedStatus = page->userContentProvider().processContentExtensionRulesForLoad(resourceRequest.url(), toResourceType(type), *m_documentLoader);
-        request.applyBlockedStatus(blockedStatus, page);
-        if (blockedStatus.blockedLoad) {
+        auto results = page->userContentProvider().processContentRuleListsForLoad(resourceRequest.url(), toResourceType(type), *m_documentLoader);
+        bool blockedLoad = results.summary.blockedLoad;
+        bool madeHTTPS = results.summary.madeHTTPS;
+        request.applyResults(WTFMove(results), page);
+        if (blockedLoad) {
             RELEASE_LOG_IF_ALLOWED("requestResource: Resource blocked by content blocker (frame = %p)", frame());
             if (type == CachedResource::Type::MainResource) {
                 CachedResourceHandle<CachedResource> resource = createResource(type, WTFMove(request), page->sessionID(), &page->cookieJar());
@@ -821,7 +824,7 @@ ResourceErrorOr<CachedResourceHandle<CachedResource>> CachedResourceLoader::requ
             }
             return makeUnexpected(ResourceError { errorDomainWebKitInternal, 0, url, "Resource blocked by content blocker"_s, ResourceError::Type::AccessControl });
         }
-        if (blockedStatus.madeHTTPS
+        if (madeHTTPS
             && type == CachedResource::Type::MainResource
             && m_documentLoader->isLoadingMainResource()) {
             // This is to make sure the correct 'new' URL shows in the location bar.
index 49f4519..39bbca2 100644 (file)
@@ -226,9 +226,9 @@ void CachedResourceRequest::removeFragmentIdentifierIfNeeded()
 
 #if ENABLE(CONTENT_EXTENSIONS)
 
-void CachedResourceRequest::applyBlockedStatus(const ContentExtensions::BlockedStatus& blockedStatus, Page* page)
+void CachedResourceRequest::applyResults(ContentRuleListResults&& results, Page* page)
 {
-    ContentExtensions::applyBlockedStatusToRequest(blockedStatus, page, m_resourceRequest);
+    ContentExtensions::applyResultsToRequest(WTFMove(results), page, m_resourceRequest);
 }
 
 #endif
index b6643d1..613f274 100644 (file)
 
 namespace WebCore {
 
-namespace ContentExtensions {
-struct BlockedStatus;
-}
-
+struct ContentRuleListResults;
 class Document;
 class FrameLoader;
 struct ServiceWorkerRegistrationData;
@@ -91,7 +88,7 @@ public:
 
     void removeFragmentIdentifierIfNeeded();
 #if ENABLE(CONTENT_EXTENSIONS)
-    void applyBlockedStatus(const ContentExtensions::BlockedStatus&, Page*);
+    void applyResults(ContentRuleListResults&&, Page*);
 #endif
     void setDomainForCachePartition(Document&);
     void setDomainForCachePartition(const String&);
index 28c251a..cff2860 100644 (file)
@@ -101,6 +101,7 @@ class Widget;
 class MediaPlayerRequestInstallMissingPluginsCallback;
 #endif
 
+struct ContentRuleListResults;
 struct DateTimeChooserParameters;
 struct GraphicsDeviceAdapter;
 struct ShareDataWithParsedURL;
@@ -383,7 +384,7 @@ public:
     virtual void enableSuddenTermination() { }
     virtual void disableSuddenTermination() { }
 
-    virtual void contentRuleListNotification(const URL&, const HashSet<std::pair<String, String>>&) { };
+    virtual void contentRuleListNotification(const URL&, const ContentRuleListResults&) { };
 
 #if PLATFORM(WIN)
     virtual void setLastSetCursorToCurrentCursor() = 0;
index f10aae8..2c984f3 100644 (file)
@@ -37,6 +37,7 @@
 #include "ComposedTreeIterator.h"
 #include "ContentExtensionActions.h"
 #include "ContentExtensionRule.h"
+#include "ContentRuleListResults.h"
 #include "Crypto.h"
 #include "CustomElementRegistry.h"
 #include "DOMApplicationCache.h"
@@ -2351,11 +2352,9 @@ ExceptionOr<RefPtr<WindowProxy>> DOMWindow::open(DOMWindow& activeWindow, DOMWin
         && firstFrame->page()
         && firstFrame->mainFrame().document()
         && firstFrame->mainFrame().document()->loader()) {
-        ResourceLoadInfo resourceLoadInfo { firstFrame->document()->completeURL(urlString), firstFrame->mainFrame().document()->url(), ResourceType::Popup };
-        for (auto& action : firstFrame->page()->userContentProvider().actionsForResourceLoad(resourceLoadInfo, *firstFrame->mainFrame().document()->loader()).first) {
-            if (action.type() == ContentExtensions::ActionType::BlockLoad)
-                return RefPtr<WindowProxy> { nullptr };
-        }
+        auto results = firstFrame->page()->userContentProvider().processContentRuleListsForLoad(firstFrame->document()->completeURL(urlString), ResourceType::Popup, *firstFrame->mainFrame().document()->loader());
+        if (results.summary.blockedLoad)
+            return RefPtr<WindowProxy> { nullptr };
     }
 #endif
 
index 97511d0..7ccfee1 100644 (file)
@@ -35,6 +35,7 @@
 #if ENABLE(CONTENT_EXTENSIONS)
 #include "ContentExtensionCompiler.h"
 #include "ContentExtensionsBackend.h"
+#include "ContentRuleListResults.h"
 #endif
 
 namespace WebCore {
@@ -101,15 +102,15 @@ static bool contentExtensionsEnabled(const DocumentLoader& documentLoader)
     return true;
 }
     
-ContentExtensions::BlockedStatus UserContentProvider::processContentExtensionRulesForLoad(const URL& url, ResourceType resourceType, DocumentLoader& initiatingDocumentLoader)
+ContentRuleListResults UserContentProvider::processContentRuleListsForLoad(const URL& url, ResourceType resourceType, DocumentLoader& initiatingDocumentLoader)
 {
     if (!contentExtensionsEnabled(initiatingDocumentLoader))
         return { };
 
-    return userContentExtensionBackend().processContentExtensionRulesForLoad(url, resourceType, initiatingDocumentLoader);
+    return userContentExtensionBackend().processContentRuleListsForLoad(url, resourceType, initiatingDocumentLoader);
 }
 
-std::pair<Vector<ContentExtensions::Action>, Vector<String>> UserContentProvider::actionsForResourceLoad(const ResourceLoadInfo& resourceLoadInfo, DocumentLoader& initiatingDocumentLoader)
+Vector<ContentExtensions::ActionsFromContentRuleList> UserContentProvider::actionsForResourceLoad(const ResourceLoadInfo& resourceLoadInfo, DocumentLoader& initiatingDocumentLoader)
 {
     if (!contentExtensionsEnabled(initiatingDocumentLoader))
         return { };
index fa69203..00e9693 100644 (file)
@@ -89,9 +89,9 @@ public:
 #if ENABLE(CONTENT_EXTENSIONS)
     // FIXME: These don't really belong here. They should probably bundled up in the ContentExtensionsBackend
     // which should always exist.
-    ContentExtensions::BlockedStatus processContentExtensionRulesForLoad(const URL&, ResourceType, DocumentLoader& initiatingDocumentLoader);
-    std::pair<Vector<ContentExtensions::Action>, Vector<String>> actionsForResourceLoad(const ResourceLoadInfo&, DocumentLoader& initiatingDocumentLoader);
-    WEBCORE_EXPORT void forEachContentExtension(const WTF::Function<void(const String&, ContentExtensions::ContentExtension&)>&, DocumentLoader& initiatingDocumentLoader);
+    ContentRuleListResults processContentRuleListsForLoad(const URL&, ResourceType, DocumentLoader& initiatingDocumentLoader);
+    Vector<ContentExtensions::ActionsFromContentRuleList> actionsForResourceLoad(const ResourceLoadInfo&, DocumentLoader& initiatingDocumentLoader);
+    WEBCORE_EXPORT void forEachContentExtension(const Function<void(const String&, ContentExtensions::ContentExtension&)>&, DocumentLoader& initiatingDocumentLoader);
 #endif
 
 protected:
index c21ce04..cf4e27a 100644 (file)
@@ -1,3 +1,33 @@
+2019-03-21  Alex Christensen  <achristensen@webkit.org>
+
+        Add SPI to inform applications of WKContentRuleList actions
+        https://bugs.webkit.org/show_bug.cgi?id=195965
+        <rdar://problem/42664365>
+
+        Reviewed by Geoff Garen.
+
+        * NetworkProcess/NetworkLoadChecker.cpp:
+        (WebKit::NetworkLoadChecker::checkRequest):
+        (WebKit::NetworkLoadChecker::processContentRuleListsForLoad):
+        (WebKit::NetworkLoadChecker::processContentExtensionRulesForLoad): Deleted.
+        * NetworkProcess/NetworkLoadChecker.h:
+        * UIProcess/API/APINavigationClient.h:
+        (API::NavigationClient::contentRuleListNotification):
+        * UIProcess/API/C/WKPage.cpp:
+        (WKPageSetPageNavigationClient):
+        * UIProcess/API/Cocoa/WKNavigationDelegatePrivate.h:
+        * UIProcess/Cocoa/NavigationState.h:
+        * UIProcess/Cocoa/NavigationState.mm:
+        (WebKit::NavigationState::setNavigationDelegate):
+        (WebKit::NavigationState::NavigationClient::contentRuleListNotification):
+        * UIProcess/WebPageProxy.cpp:
+        (WebKit::WebPageProxy::contentRuleListNotification):
+        * UIProcess/WebPageProxy.h:
+        * UIProcess/WebPageProxy.messages.in:
+        * WebProcess/WebCoreSupport/WebChromeClient.cpp:
+        (WebKit::WebChromeClient::contentRuleListNotification):
+        * WebProcess/WebCoreSupport/WebChromeClient.h:
+
 2019-03-21  Simon Fraser  <simon.fraser@apple.com>
 
         Add an internal feature flag to disable the -webkit-overflow-scrolling CSS property
index c3faf53..d14b1de 100644 (file)
@@ -30,6 +30,7 @@
 #include "Logging.h"
 #include "NetworkCORSPreflightChecker.h"
 #include "NetworkProcess.h"
+#include <WebCore/ContentRuleListResults.h>
 #include <WebCore/ContentSecurityPolicy.h>
 #include <WebCore/CrossOriginAccessControl.h>
 #include <WebCore/CrossOriginPreflightResultCache.h>
@@ -240,13 +241,13 @@ void NetworkLoadChecker::checkRequest(ResourceRequest&& request, ContentSecurity
         }
 
 #if ENABLE(CONTENT_EXTENSIONS)
-        this->processContentExtensionRulesForLoad(WTFMove(request), [this, weakThis = WTFMove(weakThis), handler = WTFMove(handler), originalRequest = WTFMove(originalRequest)](auto result) mutable {
+        this->processContentRuleListsForLoad(WTFMove(request), [this, weakThis = WTFMove(weakThis), handler = WTFMove(handler), originalRequest = WTFMove(originalRequest)](auto result) mutable {
             if (!result.has_value()) {
                 ASSERT(result.error().isCancellation());
                 handler(WTFMove(result.error()));
                 return;
             }
-            if (result.value().status.blockedLoad) {
+            if (result.value().results.summary.blockedLoad) {
                 handler(this->accessControlErrorForValidationHandler("Blocked by content extension"_s));
                 return;
             }
@@ -452,12 +453,12 @@ ContentSecurityPolicy* NetworkLoadChecker::contentSecurityPolicy()
 }
 
 #if ENABLE(CONTENT_EXTENSIONS)
-void NetworkLoadChecker::processContentExtensionRulesForLoad(ResourceRequest&& request, ContentExtensionCallback&& callback)
+void NetworkLoadChecker::processContentRuleListsForLoad(ResourceRequest&& request, ContentExtensionCallback&& callback)
 {
     // FIXME: Enable content blockers for navigation loads.
     if (!m_checkContentExtensions || !m_userContentControllerIdentifier || m_options.mode == FetchOptions::Mode::Navigate) {
-        ContentExtensions::BlockedStatus status;
-        callback(ContentExtensionResult { WTFMove(request), status });
+        ContentRuleListResults results;
+        callback(ContentExtensionResult { WTFMove(request), results });
         return;
     }
 
@@ -467,9 +468,9 @@ void NetworkLoadChecker::processContentExtensionRulesForLoad(ResourceRequest&& r
             return;
         }
 
-        auto status = backend.processContentExtensionRulesForPingLoad(request.url(), m_mainDocumentURL);
-        applyBlockedStatusToRequest(status, nullptr, request);
-        callback(ContentExtensionResult { WTFMove(request), status });
+        auto results = backend.processContentRuleListsForPingLoad(request.url(), m_mainDocumentURL);
+        WebCore::ContentExtensions::applyResultsToRequest(ContentRuleListResults { results }, nullptr, request);
+        callback(ContentExtensionResult { WTFMove(request), results });
     });
 }
 #endif // ENABLE(CONTENT_EXTENSIONS)
index d7e02a5..829f7c2 100644 (file)
@@ -112,11 +112,11 @@ private:
 #if ENABLE(CONTENT_EXTENSIONS)
     struct ContentExtensionResult {
         WebCore::ResourceRequest request;
-        const WebCore::ContentExtensions::BlockedStatus& status;
+        const WebCore::ContentRuleListResults& results;
     };
     using ContentExtensionResultOrError = Expected<ContentExtensionResult, WebCore::ResourceError>;
     using ContentExtensionCallback = CompletionHandler<void(ContentExtensionResultOrError)>;
-    void processContentExtensionRulesForLoad(WebCore::ResourceRequest&&, ContentExtensionCallback&&);
+    void processContentRuleListsForLoad(WebCore::ResourceRequest&&, ContentExtensionCallback&&);
 #endif
 
     void applyHTTPSUpgradeIfNeeded(WebCore::ResourceRequest&&, CompletionHandler<void(WebCore::ResourceRequest&&)>&&) const;
index 1ca1b29..0adf5c5 100644 (file)
@@ -23,8 +23,7 @@
  * THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#ifndef APIObject_h
-#define APIObject_h
+#pragma once
 
 #include <wtf/RefCounted.h>
 #include <wtf/RefPtr.h>
@@ -107,6 +106,7 @@ public:
         CacheManager,
         ColorPickerResultListener,
         ContentRuleList,
+        ContentRuleListAction,
         ContentRuleListStore,
         ContextMenuListener,
         CookieManager,
@@ -282,5 +282,3 @@ inline API::Object* Object::unwrap(void* object)
 } // namespace Object
 
 #undef DELEGATE_REF_COUNTING_TO_COCOA
-
-#endif // APIObject_h
index c0a4505..c3be21c 100644 (file)
@@ -68,6 +68,7 @@
 #import "WKWindowFeaturesInternal.h"
 #import "_WKAttachmentInternal.h"
 #import "_WKAutomationSessionInternal.h"
+#import "_WKContentRuleListActionInternal.h"
 #import "_WKDownloadInternal.h"
 #import "_WKExperimentalFeatureInternal.h"
 #import "_WKFrameHandleInternal.h"
@@ -304,6 +305,10 @@ void* Object::newObject(size_t size, Type type)
         wrapper = [WKContentRuleList alloc];
         break;
 
+    case Type::ContentRuleListAction:
+        wrapper = [_WKContentRuleListAction alloc];
+        break;
+
     case Type::ContentRuleListStore:
         wrapper = [WKContentRuleListStore alloc];
         break;
index 8527cfb..803b576 100644 (file)
@@ -293,6 +293,7 @@ UIProcess/WebURLSchemeTask.cpp
 
 UIProcess/API/APIAttachment.cpp
 UIProcess/API/APIContentRuleList.cpp
+UIProcess/API/APIContentRuleListAction.cpp
 UIProcess/API/APIContentRuleListStore.cpp
 UIProcess/API/APIExperimentalFeature.cpp
 UIProcess/API/APIFrameInfo.cpp
index 61ec29c..eb504f9 100644 (file)
@@ -241,6 +241,7 @@ UIProcess/API/Cocoa/_WKApplicationManifest.mm
 UIProcess/API/Cocoa/_WKAttachment.mm
 UIProcess/API/Cocoa/_WKAutomationSession.mm
 UIProcess/API/Cocoa/_WKAutomationSessionConfiguration.mm
+UIProcess/API/Cocoa/_WKContentRuleListAction.mm
 UIProcess/API/Cocoa/_WKContextMenuElementInfo.mm
 UIProcess/API/Cocoa/_WKDownload.mm
 UIProcess/API/Cocoa/_WKElementAction.mm
diff --git a/Source/WebKit/UIProcess/API/APIContentRuleListAction.cpp b/Source/WebKit/UIProcess/API/APIContentRuleListAction.cpp
new file mode 100644 (file)
index 0000000..1816032
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2019 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 "APIContentRuleListAction.h"
+
+namespace API {
+
+Ref<ContentRuleListAction> ContentRuleListAction::create(WebCore::ContentRuleListResults::Result&& result)
+{
+    return adoptRef(*new ContentRuleListAction(WTFMove(result)));
+}
+
+ContentRuleListAction::ContentRuleListAction(WebCore::ContentRuleListResults::Result&& result)
+    : m_result(WTFMove(result))
+{
+}
+
+ContentRuleListAction::~ContentRuleListAction() = default;
+
+bool ContentRuleListAction::blockedLoad() const
+{
+    return m_result.blockedLoad;
+}
+
+bool ContentRuleListAction::madeHTTPS() const
+{
+    return m_result.madeHTTPS;
+}
+
+bool ContentRuleListAction::blockedCookies() const
+{
+    return m_result.blockedCookies;
+}
+
+const Vector<WTF::String>& ContentRuleListAction::notifications() const
+{
+    return m_result.notifications;
+}
+
+} // namespace API
diff --git a/Source/WebKit/UIProcess/API/APIContentRuleListAction.h b/Source/WebKit/UIProcess/API/APIContentRuleListAction.h
new file mode 100644 (file)
index 0000000..63bfd17
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2019 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 "APIObject.h"
+
+#include <WebCore/ContentRuleListResults.h>
+
+namespace API {
+
+class ContentRuleListAction final : public ObjectImpl<Object::Type::ContentRuleListAction> {
+public:
+    static Ref<ContentRuleListAction> create(WebCore::ContentRuleListResults::Result&&);
+    virtual ~ContentRuleListAction();
+
+    bool blockedLoad() const;
+    bool madeHTTPS() const;
+    bool blockedCookies() const;
+    const Vector<WTF::String>& notifications() const;
+
+private:
+    ContentRuleListAction(WebCore::ContentRuleListResults::Result&&);
+
+    WebCore::ContentRuleListResults::Result m_result;
+};
+    
+} // namespace API
index ccf86d6..1105780 100644 (file)
@@ -41,6 +41,7 @@
 #include <wtf/Forward.h>
 
 namespace WebCore {
+struct ContentRuleListResults;
 class ResourceError;
 class ResourceRequest;
 class ResourceResponse;
@@ -115,7 +116,7 @@ public:
         listener->use();
     }
     
-    virtual void contentRuleListNotification(WebKit::WebPageProxy&, WTF::URL&&, Vector<WTF::String>&&, Vector<WTF::String>&&) { };
+    virtual void contentRuleListNotification(WebKit::WebPageProxy&, WTF::URL&&, WebCore::ContentRuleListResults&&) { };
     
 #if ENABLE(NETSCAPE_PLUGIN_API)
     virtual bool didFailToInitializePlugIn(WebKit::WebPageProxy&, API::Dictionary&) { return false; }
index f8f39ab..cc3c764 100644 (file)
@@ -75,6 +75,7 @@
 #include "WebProcessPool.h"
 #include "WebProcessProxy.h"
 #include "WebProtectionSpace.h"
+#include <WebCore/ContentRuleListResults.h>
 #include <WebCore/Page.h>
 #include <WebCore/SSLKeyGenerator.h>
 #include <WebCore/SecurityOriginData.h>
@@ -2243,20 +2244,24 @@ void WKPageSetPageNavigationClient(WKPageRef pageRef, const WKPageNavigationClie
             m_client.didRemoveNavigationGestureSnapshot(toAPI(&page), m_client.base.clientInfo);
         }
         
-        void contentRuleListNotification(WebPageProxy& page, URL&& url, Vector<String>&& listIdentifiers, Vector<String>&& notifications) final
+        void contentRuleListNotification(WebPageProxy& page, URL&& url, ContentRuleListResults&& results) final
         {
             if (!m_client.contentRuleListNotification)
                 return;
 
             Vector<RefPtr<API::Object>> apiListIdentifiers;
-            for (const auto& identifier : listIdentifiers)
-                apiListIdentifiers.append(API::String::create(identifier));
-
             Vector<RefPtr<API::Object>> apiNotifications;
-            for (const auto& notification : notifications)
-                apiNotifications.append(API::String::create(notification));
+            for (const auto& pair : results.results) {
+                const String& listIdentifier = pair.first;
+                const auto& result = pair.second;
+                for (const String& notification : result.notifications) {
+                    apiListIdentifiers.append(API::String::create(listIdentifier));
+                    apiNotifications.append(API::String::create(notification));
+                }
+            }
 
-            m_client.contentRuleListNotification(toAPI(&page), toURLRef(url.string().impl()), toAPI(API::Array::create(WTFMove(apiListIdentifiers)).ptr()), toAPI(API::Array::create(WTFMove(apiNotifications)).ptr()), m_client.base.clientInfo);
+            if (!apiNotifications.isEmpty())
+                m_client.contentRuleListNotification(toAPI(&page), toURLRef(url.string().impl()), toAPI(API::Array::create(WTFMove(apiListIdentifiers)).ptr()), toAPI(API::Array::create(WTFMove(apiNotifications)).ptr()), m_client.base.clientInfo);
         }
 #if ENABLE(NETSCAPE_PLUGIN_API)
         void decidePolicyForPluginLoad(WebPageProxy& page, PluginModuleLoadPolicy currentPluginLoadPolicy, API::Dictionary& pluginInformation, CompletionHandler<void(PluginModuleLoadPolicy, const String&)>&& completionHandler) override
index 9a1321c..35bbec1 100644 (file)
@@ -29,6 +29,7 @@
 #import <WebKit/WKWebViewPrivate.h>
 #import <WebKit/_WKSameDocumentNavigationType.h>
 
+@class _WKContentRuleListAction;
 @class _WKWebsitePolicies;
 
 #if !TARGET_OS_IPHONE
@@ -93,6 +94,7 @@ static const WKNavigationResponsePolicy _WKNavigationResponsePolicyBecomeDownloa
 - (void)_webView:(WKWebView *)webView didFailNavigation:(WKNavigation *)navigation withError:(NSError *)error userInfo:(id <NSSecureCoding>)userInfo WK_API_AVAILABLE(macosx(10.13.4), ios(11.3));
 
 - (void)_webView:(WKWebView *)webView URL:(NSURL *)url contentRuleListIdentifiers:(NSArray<NSString *> *)identifiers notifications:(NSArray<NSString *> *)notifications WK_API_AVAILABLE(macosx(10.13.4), ios(11.3));
+- (void)_webView:(WKWebView *)webView contentRuleListWithIdentifier:(NSString *)identifier performedAction:(_WKContentRuleListAction *)action forURL:(NSURL *)url WK_API_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA));
 - (void)_webView:(WKWebView *)webView webContentProcessDidTerminateWithReason:(_WKProcessTerminationReason)reason WK_API_AVAILABLE(macosx(10.14), ios(12.0));
 
 #if TARGET_OS_IPHONE
diff --git a/Source/WebKit/UIProcess/API/Cocoa/_WKContentRuleListAction.h b/Source/WebKit/UIProcess/API/Cocoa/_WKContentRuleListAction.h
new file mode 100644 (file)
index 0000000..a7ec9d2
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+#import <Foundation/Foundation.h>
+#import <WebKit/WKFoundation.h>
+
+WK_CLASS_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA))
+@interface _WKContentRuleListAction : NSObject
+
+@property (nonatomic, readonly) BOOL blockedLoad;
+@property (nonatomic, readonly) BOOL blockedCookies;
+@property (nonatomic, readonly) BOOL madeHTTPS;
+@property (nonatomic, readonly, copy) NSArray<NSString *> *notifications;
+
+@end
diff --git a/Source/WebKit/UIProcess/API/Cocoa/_WKContentRuleListAction.mm b/Source/WebKit/UIProcess/API/Cocoa/_WKContentRuleListAction.mm
new file mode 100644 (file)
index 0000000..24d4678
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+#import "config.h"
+#import "_WKContentRuleListActionInternal.h"
+
+@implementation _WKContentRuleListAction
+
+- (void)dealloc
+{
+    _action->~ContentRuleListAction();
+    
+    [super dealloc];
+}
+
+- (BOOL)blockedLoad
+{
+    return _action->blockedLoad();
+}
+
+- (BOOL)blockedCookies
+{
+    return _action->blockedCookies();
+}
+
+- (BOOL)madeHTTPS
+{
+    return _action->madeHTTPS();
+}
+
+- (NSArray<NSString *> *)notifications
+{
+    const auto& vector = _action->notifications();
+    if (vector.isEmpty())
+        return nil;
+
+    NSMutableArray<NSString *> *array = [[[NSMutableArray alloc] initWithCapacity:vector.size()] autorelease];
+    for (const auto& notification : vector)
+        [array addObject:notification];
+    return array;
+}
+
+- (API::Object&)_apiObject
+{
+    return *_action;
+}
+
+@end
diff --git a/Source/WebKit/UIProcess/API/Cocoa/_WKContentRuleListActionInternal.h b/Source/WebKit/UIProcess/API/Cocoa/_WKContentRuleListActionInternal.h
new file mode 100644 (file)
index 0000000..9edb523
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+#import "_WKContentRuleListAction.h"
+
+#import "APIContentRuleListAction.h"
+#import "WKObject.h"
+
+namespace WebKit {
+
+template<> struct WrapperTraits<API::ContentRuleListAction> {
+    using WrapperClass = _WKContentRuleListAction;
+};
+
+}
+
+@interface _WKContentRuleListAction () <WKObject> {
+@package
+    API::ObjectStorage<API::ContentRuleListAction> _action;
+}
+@end
index 3e69609..1f0d5f4 100644 (file)
@@ -133,7 +133,7 @@ private:
         bool didChangeBackForwardList(WebPageProxy&, WebBackForwardListItem*, const Vector<Ref<WebBackForwardListItem>>&) final;
 #endif
 
-        void contentRuleListNotification(WebPageProxy&, URL&&, Vector<String>&&, Vector<String>&&) final;
+        void contentRuleListNotification(WebPageProxy&, URL&&, WebCore::ContentRuleListResults&&) final;
         void decidePolicyForNavigationAction(WebPageProxy&, Ref<API::NavigationAction>&&, Ref<WebFramePolicyListenerProxy>&&, API::Object* userData) override;
         void decidePolicyForNavigationResponse(WebPageProxy&, Ref<API::NavigationResponse>&&, Ref<WebFramePolicyListenerProxy>&&, API::Object* userData) override;
 
@@ -219,6 +219,7 @@ private:
         bool webViewWillSnapshotBackForwardListItem : 1;
         bool webViewNavigationGestureSnapshotWasRemoved : 1;
         bool webViewURLContentRuleListIdentifiersNotifications : 1;
+        bool webViewContentRuleListWithIdentifierPerformedActionForURL : 1;
 #if USE(QUICK_LOOK)
         bool webViewDidStartLoadForQuickLookDocumentInMainFrame : 1;
         bool webViewDidFinishLoadForQuickLookDocumentInMainFrame : 1;
index 466e74b..524063a 100644 (file)
@@ -26,6 +26,7 @@
 #import "config.h"
 #import "NavigationState.h"
 
+#import "APIContentRuleListAction.h"
 #import "APIFrameInfo.h"
 #import "APINavigationData.h"
 #import "APINavigationResponse.h"
 #import "WebPageProxy.h"
 #import "WebProcessProxy.h"
 #import "WebProtectionSpace.h"
+#import "_WKContentRuleListActionInternal.h"
 #import "_WKErrorRecoveryAttempting.h"
 #import "_WKFrameHandleInternal.h"
 #import "_WKRenderingProgressEventsInternal.h"
 #import "_WKSameDocumentNavigationTypeInternal.h"
 #import "_WKWebsitePoliciesInternal.h"
+#import <WebCore/ContentRuleListResults.h>
 #import <WebCore/Credential.h>
 #import <WebCore/SSLKeyGenerator.h>
 #import <WebCore/SecurityOriginData.h>
@@ -177,6 +180,8 @@ void NavigationState::setNavigationDelegate(id <WKNavigationDelegate> delegate)
     m_navigationDelegateMethods.webViewWillSnapshotBackForwardListItem = [delegate respondsToSelector:@selector(_webView:willSnapshotBackForwardListItem:)];
     m_navigationDelegateMethods.webViewNavigationGestureSnapshotWasRemoved = [delegate respondsToSelector:@selector(_webViewDidRemoveNavigationGestureSnapshot:)];
     m_navigationDelegateMethods.webViewURLContentRuleListIdentifiersNotifications = [delegate respondsToSelector:@selector(_webView:URL:contentRuleListIdentifiers:notifications:)];
+    m_navigationDelegateMethods.webViewContentRuleListWithIdentifierPerformedActionForURL = [delegate respondsToSelector:@selector(_webView:contentRuleListWithIdentifier:performedAction:forURL:)];
+
 #if USE(QUICK_LOOK)
     m_navigationDelegateMethods.webViewDidStartLoadForQuickLookDocumentInMainFrame = [delegate respondsToSelector:@selector(_webView:didStartLoadForQuickLookDocumentInMainFrameWithFileName:uti:)];
     m_navigationDelegateMethods.webViewDidFinishLoadForQuickLookDocumentInMainFrame = [delegate respondsToSelector:@selector(_webView:didFinishLoadForQuickLookDocumentInMainFrame:)];
@@ -617,26 +622,39 @@ void NavigationState::NavigationClient::decidePolicyForNavigationAction(WebPageP
     }
 }
 
-void NavigationState::NavigationClient::contentRuleListNotification(WebPageProxy&, URL&& url, Vector<String>&& listIdentifiers, Vector<String>&& notifications)
+void NavigationState::NavigationClient::contentRuleListNotification(WebPageProxy&, URL&& url, ContentRuleListResults&& results)
 {
-    if (!m_navigationState.m_navigationDelegateMethods.webViewURLContentRuleListIdentifiersNotifications)
+    if (!m_navigationState.m_navigationDelegateMethods.webViewURLContentRuleListIdentifiersNotifications
+        && !m_navigationState.m_navigationDelegateMethods.webViewContentRuleListWithIdentifierPerformedActionForURL)
         return;
 
     auto navigationDelegate = m_navigationState.m_navigationDelegate.get();
     if (!navigationDelegate)
         return;
 
-    ASSERT(listIdentifiers.size() == notifications.size());
+    RetainPtr<NSMutableArray<NSString *>> identifiers;
+    RetainPtr<NSMutableArray<NSString *>> notifications;
+
+    for (const auto& pair : results.results) {
+        const String& listIdentifier = pair.first;
+        const auto& result = pair.second;
+        for (const String& notification : result.notifications) {
+            if (!identifiers)
+                identifiers = adoptNS([NSMutableArray new]);
+            if (!notifications)
+                notifications = adoptNS([NSMutableArray new]);
+            [identifiers addObject:listIdentifier];
+            [notifications addObject:notification];
+        }
+    }
 
-    auto identifiers = adoptNS([[NSMutableArray alloc] initWithCapacity:listIdentifiers.size()]);
-    for (auto& identifier : listIdentifiers)
-        [identifiers addObject:identifier];
+    if (notifications && m_navigationState.m_navigationDelegateMethods.webViewURLContentRuleListIdentifiersNotifications)
+        [(id <WKNavigationDelegatePrivate>)navigationDelegate _webView:m_navigationState.m_webView URL:url contentRuleListIdentifiers:identifiers.get() notifications:notifications.get()];
 
-    auto nsNotifications = adoptNS([[NSMutableArray alloc] initWithCapacity:notifications.size()]);
-    for (auto& notification : notifications)
-        [nsNotifications addObject:notification];
-    
-    [(id <WKNavigationDelegatePrivate>)navigationDelegate _webView:m_navigationState.m_webView URL:url contentRuleListIdentifiers:identifiers.get() notifications:nsNotifications.get()];
+    if (m_navigationState.m_navigationDelegateMethods.webViewContentRuleListWithIdentifierPerformedActionForURL) {
+        for (auto&& pair : WTFMove(results.results))
+            [(id <WKNavigationDelegatePrivate>)navigationDelegate _webView:m_navigationState.m_webView contentRuleListWithIdentifier:pair.first performedAction:wrapper(API::ContentRuleListAction::create(WTFMove(pair.second)).get()) forURL:url];
+    }
 }
     
 void NavigationState::NavigationClient::decidePolicyForNavigationResponse(WebPageProxy& page, Ref<API::NavigationResponse>&& navigationResponse, Ref<WebFramePolicyListenerProxy>&& listener, API::Object* userData)
index 7efaf3a..56e5762 100644 (file)
@@ -4837,9 +4837,9 @@ void WebPageProxy::willSubmitForm(uint64_t frameID, uint64_t sourceFrameID, cons
     });
 }
 
-void WebPageProxy::contentRuleListNotification(URL&& url, Vector<String>&& identifiers, Vector<String>&& notifications)
+void WebPageProxy::contentRuleListNotification(URL&& url, ContentRuleListResults&& results)
 {
-    m_navigationClient->contentRuleListNotification(*this, WTFMove(url), WTFMove(identifiers), WTFMove(notifications));
+    m_navigationClient->contentRuleListNotification(*this, WTFMove(url), WTFMove(results));
 }
     
 void WebPageProxy::didNavigateWithNavigationData(const WebNavigationDataStore& store, uint64_t frameID) 
index 4c05c24..70245f1 100644 (file)
@@ -197,6 +197,7 @@ enum class WritingDirection : uint8_t;
 
 struct ApplicationManifest;
 struct BackForwardItemIdentifier;
+struct ContentRuleListResults;
 struct DataListSuggestionInformation;
 struct DictionaryPopupInfo;
 struct ExceptionDetails;
@@ -1606,8 +1607,8 @@ private:
     void beginSafeBrowsingCheck(const URL&, bool, WebFramePolicyListenerProxy&);
 
     void willSubmitForm(uint64_t frameID, uint64_t sourceFrameID, const Vector<std::pair<String, String>>& textFieldValues, uint64_t listenerID, const UserData&);
-        
-    void contentRuleListNotification(URL&&, Vector<String>&& identifiers, Vector<String>&& notifications);
+
+    void contentRuleListNotification(URL&&, WebCore::ContentRuleListResults&&);
 
     // History client
     void didNavigateWithNavigationData(const WebNavigationDataStore&, uint64_t frameID);
index da17fb4..a500ae6 100644 (file)
@@ -491,7 +491,7 @@ messages -> WebPageProxy {
 
     DidResignInputElementStrongPasswordAppearance(WebKit::UserData userData)
 
-    ContentRuleListNotification(URL url, Vector<String> identifiers, Vector<String> notifications)
+    ContentRuleListNotification(URL url, struct WebCore::ContentRuleListResults results)
 
 #if ENABLE(WIRELESS_PLAYBACK_TARGET) && !PLATFORM(IOS_FAMILY)
     AddPlaybackTargetPickerClient(uint64_t contextId)
index bc1336d..c8126db 100644 (file)
                5C26958520043212005C439B /* WKOpenPanelParametersPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 5C26958420042F12005C439B /* WKOpenPanelParametersPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; };
                5C298DA01C3DF02100470AFE /* PendingDownload.h in Headers */ = {isa = PBXBuildFile; fileRef = 5C298D9E1C3DEF2900470AFE /* PendingDownload.h */; };
                5C359C0D2154739F009E7948 /* WKDeprecated.h in Headers */ = {isa = PBXBuildFile; fileRef = 5C359C0C21547321009E7948 /* WKDeprecated.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               5C4609E7224317B4009943C2 /* _WKContentRuleListAction.h in Headers */ = {isa = PBXBuildFile; fileRef = 5C4609E222430E4C009943C2 /* _WKContentRuleListAction.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               5C4609E8224317BB009943C2 /* _WKContentRuleListActionInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 5C4609E422430E4D009943C2 /* _WKContentRuleListActionInternal.h */; };
                5C4B9D8B210A8CCF008F14D1 /* UndoOrRedo.h in Headers */ = {isa = PBXBuildFile; fileRef = 5C4B9D8A210A8C46008F14D1 /* UndoOrRedo.h */; };
                5C5CEC30220911C700D6BBB0 /* WKMain.h in Headers */ = {isa = PBXBuildFile; fileRef = 5C5CEC2E2209114800D6BBB0 /* WKMain.h */; settings = {ATTRIBUTES = (Private, ); }; };
                5C5CEC32220912B300D6BBB0 /* AuxiliaryProcessMain.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5C5CEC31220912AF00D6BBB0 /* AuxiliaryProcessMain.cpp */; };
                5C2B1AF5223C1FD200B91CF7 /* DownloadProxyMapCocoa.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = DownloadProxyMapCocoa.mm; sourceTree = "<group>"; };
                5C359C0C21547321009E7948 /* WKDeprecated.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKDeprecated.h; sourceTree = "<group>"; };
                5C3AEA8E1FE1F1DF002318D3 /* WebsitePoliciesData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebsitePoliciesData.cpp; sourceTree = "<group>"; };
+               5C4609E222430E4C009943C2 /* _WKContentRuleListAction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = _WKContentRuleListAction.h; sourceTree = "<group>"; };
+               5C4609E322430E4D009943C2 /* _WKContentRuleListAction.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = _WKContentRuleListAction.mm; sourceTree = "<group>"; };
+               5C4609E422430E4D009943C2 /* _WKContentRuleListActionInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = _WKContentRuleListActionInternal.h; sourceTree = "<group>"; };
+               5C4609E522430FA6009943C2 /* APIContentRuleListAction.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = APIContentRuleListAction.cpp; sourceTree = "<group>"; };
+               5C4609E622430FA7009943C2 /* APIContentRuleListAction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = APIContentRuleListAction.h; sourceTree = "<group>"; };
                5C46C0AC21B7198B00BC5991 /* WebsiteDataStoreConfiguration.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebsiteDataStoreConfiguration.cpp; sourceTree = "<group>"; };
                5C46C0AD21B7198C00BC5991 /* WebsiteDataStoreConfiguration.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebsiteDataStoreConfiguration.h; sourceTree = "<group>"; };
                5C46C0AE21B71AE200BC5991 /* _WKWebsiteDataStoreConfigurationInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = _WKWebsiteDataStoreConfigurationInternal.h; sourceTree = "<group>"; };
                                99788ACA1F421DCA00C08000 /* _WKAutomationSessionConfiguration.mm */,
                                990D28A81C6404B000986977 /* _WKAutomationSessionDelegate.h */,
                                990D28AF1C65203900986977 /* _WKAutomationSessionInternal.h */,
+                               5C4609E222430E4C009943C2 /* _WKContentRuleListAction.h */,
+                               5C4609E322430E4D009943C2 /* _WKContentRuleListAction.mm */,
+                               5C4609E422430E4D009943C2 /* _WKContentRuleListActionInternal.h */,
                                1A5704F61BE01FF400874AF1 /* _WKContextMenuElementInfo.h */,
                                1A5704F51BE01FF400874AF1 /* _WKContextMenuElementInfo.mm */,
                                83891B681A68BEBC0030F386 /* _WKDiagnosticLoggingDelegate.h */,
                                990D28B31C6526D400986977 /* APIAutomationSessionClient.h */,
                                7C89D2B11A6B068C003A5FDE /* APIContentRuleList.cpp */,
                                7C89D2B21A6B068C003A5FDE /* APIContentRuleList.h */,
+                               5C4609E522430FA6009943C2 /* APIContentRuleListAction.cpp */,
+                               5C4609E622430FA7009943C2 /* APIContentRuleListAction.h */,
                                7C3A06A51AAB903E009D74BA /* APIContentRuleListStore.cpp */,
                                7C3A06A61AAB903E009D74BA /* APIContentRuleListStore.h */,
                                076E884D1A13CADF005E90FC /* APIContextMenuClient.h */,
                                99788ACB1F421DDA00C08000 /* _WKAutomationSessionConfiguration.h in Headers */,
                                990D28AC1C6420CF00986977 /* _WKAutomationSessionDelegate.h in Headers */,
                                990D28B11C65208D00986977 /* _WKAutomationSessionInternal.h in Headers */,
+                               5C4609E7224317B4009943C2 /* _WKContentRuleListAction.h in Headers */,
+                               5C4609E8224317BB009943C2 /* _WKContentRuleListActionInternal.h in Headers */,
                                1A5704F81BE01FF400874AF1 /* _WKContextMenuElementInfo.h in Headers */,
                                83891B691A68BEBC0030F386 /* _WKDiagnosticLoggingDelegate.h in Headers */,
                                A1A4FE5A18DCE9FA00B5EA8A /* _WKDownload.h in Headers */,
index dd00bf2..a18def0 100644 (file)
@@ -58,6 +58,7 @@
 #include <WebCore/ApplicationCacheStorage.h>
 #include <WebCore/AXObjectCache.h>
 #include <WebCore/ColorChooser.h>
+#include <WebCore/ContentRuleListResults.h>
 #include <WebCore/DataListSuggestionPicker.h>
 #include <WebCore/DatabaseTracker.h>
 #include <WebCore/DocumentLoader.h>
@@ -909,18 +910,12 @@ void WebChromeClient::scheduleCompositingLayerFlush()
         m_page.drawingArea()->scheduleCompositingLayerFlush();
 }
 
-void WebChromeClient::contentRuleListNotification(const URL& url, const HashSet<std::pair<String, String>>& notificationPairs)
+void WebChromeClient::contentRuleListNotification(const URL& url, const ContentRuleListResults& results)
 {
-    Vector<String> identifiers;
-    Vector<String> notifications;
-    identifiers.reserveInitialCapacity(notificationPairs.size());
-    notifications.reserveInitialCapacity(notificationPairs.size());
-    for (auto& notification : notificationPairs) {
-        identifiers.uncheckedAppend(notification.first);
-        notifications.uncheckedAppend(notification.second);
-    }
-
-    m_page.send(Messages::WebPageProxy::ContentRuleListNotification(url, identifiers, notifications));
+#if ENABLE(CONTENT_EXTENSIONS)
+    ASSERT(results.shouldNotifyApplication());
+    m_page.send(Messages::WebPageProxy::ContentRuleListNotification(url, results));
+#endif
 }
 
 bool WebChromeClient::adjustLayerFlushThrottling(LayerFlushThrottleState::Flags flags)
index 20cb3e6..5992c89 100644 (file)
@@ -214,7 +214,7 @@ private:
     void scheduleCompositingLayerFlush() final;
     bool adjustLayerFlushThrottling(WebCore::LayerFlushThrottleState::Flags) final;
 
-    void contentRuleListNotification(const URL&, const HashSet<std::pair<String, String>>&) final;
+    void contentRuleListNotification(const URL&, const WebCore::ContentRuleListResults&) final;
 
 #if PLATFORM(WIN)
     void setLastSetCursorToCurrentCursor() final { }
index 6b80f0a..7ec2c50 100644 (file)
@@ -1,3 +1,25 @@
+2019-03-21  Alex Christensen  <achristensen@webkit.org>
+
+        Add SPI to inform applications of WKContentRuleList actions
+        https://bugs.webkit.org/show_bug.cgi?id=195965
+        <rdar://problem/42664365>
+
+        Reviewed by Geoff Garen.
+
+        * TestWebKitAPI/Tests/WebCore/ContentExtensions.cpp:
+        (TestWebKitAPI::allActionsForResourceLoad):
+        (TestWebKitAPI::testRequest):
+        (TestWebKitAPI::TEST_F):
+        * TestWebKitAPI/Tests/WebKitCocoa/ContentRuleListNotification.mm:
+        (Notification::description):
+        (Notification::operator== const):
+        (toVector):
+        (-[ContentRuleListNotificationDelegate _webView:URL:contentRuleListIdentifiers:notifications:]):
+        (-[ContentRuleListNotificationDelegate _webView:contentRuleListWithIdentifier:performedActionOnURL:blockedLoad:blockedCookies:madeHTTPS:notifications:]):
+        (makeContentRuleList):
+        (TEST):
+        (makeWarnContentRuleList): Deleted.
+
 2019-03-21  Timothy Hatcher  <timothy@apple.com>
 
         Style check error "WK_MAC_TBA is neither a version number nor WK_IOS_TBA" is confusing.
index ec6604e..f5600f6 100644 (file)
@@ -74,7 +74,7 @@ class AbstractExecutive(object):
         if not process_name_filter:
             process_name_filter = lambda process_name: True
 
-        running_pids = self.running_pids(process_name_filter)
+        running_pids, undef = self.running_pids(process_name_filter)
         if not running_pids:
             return
         pid = running_pids[-1]
index 77cbce8..07ade58 100644 (file)
@@ -268,12 +268,13 @@ class Executive(AbstractExecutive):
     def running_pids(self, process_name_filter=None):
         if self._is_native_win:
             # FIXME: running_pids isn't implemented on native Windows yet...
-            return []
+            return [], []
 
         if not process_name_filter:
             process_name_filter = lambda process_name: True
 
         running_pids = []
+        running_names = []
         if self._is_cygwin:
             ps_process = self.run_command(['ps', '-e'], ignore_errors=True)
             for line in ps_process.splitlines():
@@ -282,6 +283,7 @@ class Executive(AbstractExecutive):
                     pid, ppid, pgid, winpid, tty, uid, stime, process_name = tokens
                     if process_name_filter(process_name):
                         running_pids.append(int(pid))
+                        running_names.append(os.path.basename(process_name))
                         self.pid_to_system_pid[int(pid)] = int(winpid)
                 except ValueError as e:
                     pass
@@ -295,10 +297,11 @@ class Executive(AbstractExecutive):
                     pid, process_name = line.strip().split(' ', 1)
                     if process_name_filter(process_name):
                         running_pids.append(int(pid))
+                        running_names.append(os.path.basename(process_name))
                 except ValueError as e:
                     pass
 
-        return sorted(running_pids)
+        return running_pids, running_names
 
     def _windows_image_name(self, process_name):
         name, extension = os.path.splitext(process_name)
index dc063ad..d6d5db8 100644 (file)
@@ -82,12 +82,15 @@ class MockExecutive(object):
 
     def running_pids(self, process_name_filter):
         running_pids = []
+        running_names = []
         for process_name, process_pid in self._running_pids.iteritems():
             if process_name_filter(process_name):
                 running_pids.append(process_pid)
+                running_names.append(process_name)
 
         _log.info("MOCK running_pids: %s" % running_pids)
-        return running_pids
+        _log.info("MOCK running_names: %s" % running_names)
+        return running_pids, running_names
 
     def run_and_throw_if_fail(self, args, quiet=False, cwd=None, env=None):
         if self._should_log:
index 78900e7..30cded6 100644 (file)
@@ -231,8 +231,9 @@ class ExecutiveTest(unittest.TestCase):
             return  # This function isn't implemented on Windows yet.
 
         executive = Executive()
-        pids = executive.running_pids()
+        pids, names = executive.running_pids()
         self.assertIn(os.getpid(), pids)
+        self.assertIn(os.path.basename(sys.executable), names)
 
     def serial_test_run_in_parallel(self):
         # We run this test serially to avoid overloading the machine and throwing off the timing.
index e989465..7fa7096 100644 (file)
@@ -22,6 +22,7 @@
 
 import logging
 import os
+import re
 import time
 
 from webkitpy.common.memoized import memoized
@@ -60,7 +61,16 @@ class DarwinPort(ApplePort):
         if not self.get_option('leaks'):
             return
         # We could use http://code.google.com/p/psutil/ to get the process_name from the pid.
-        self._leak_detector.check_for_leaks(process_name, process_pid)
+        if self.get_option('webkit_test_runner'):
+            # FIXME: This assumes no other processes spawning WebKit2 processes are running.
+            webkit_process_re = re.compile('.*/com\.apple\.WebKit\.\S+\.Development$')
+            process_name_filter = lambda process_name: re.match(webkit_process_re, process_name)
+            process_ids, process_names = self._executive.running_pids(process_name_filter) or []
+            process_ids.insert(0, process_pid)
+            process_names.insert(0, process_name)
+            self._leak_detector.check_for_leaks(process_names, process_ids)
+        else:
+            self._leak_detector.check_for_leaks(process_name, process_pid)
 
     def print_leaks_summary(self):
         if not self.get_option('leaks'):
index d07e095..a1ec21c 100644 (file)
@@ -118,14 +118,19 @@ class LeakDetector(object):
 
     def check_for_leaks(self, process_name, process_pid):
         _log.debug("Checking for leaks in %s" % process_name)
+        pids = process_pid if isinstance(process_pid, list) else [process_pid]
+        names = process_name if isinstance(process_name, list) else [process_name]
         try:
-            leaks_filename = self.leaks_file_name(process_name, process_pid)
-            leaks_output_path = self._filesystem.join(self._port.results_directory(), leaks_filename)
-            # Oddly enough, run-leaks (or the underlying leaks tool) does not seem to always output utf-8,
-            # thus we pass decode_output=False.  Without this code we've seen errors like:
-            # "UnicodeDecodeError: 'utf8' codec can't decode byte 0x88 in position 779874: unexpected code byte"
-            self._port._run_script("run-leaks", self._leaks_args(process_name, process_pid), include_configuration_arguments=False, decode_output=False)
-            leaks_output = self._filesystem.read_binary_file(leaks_output_path)
+            for i in range(len(pids)):
+                pid = pids[i]
+                name = names[i]
+                leaks_filename = self.leaks_file_name(name, pid)
+                leaks_output_path = self._filesystem.join(self._port.results_directory(), leaks_filename)
+                # Oddly enough, run-leaks (or the underlying leaks tool) does not seem to always output utf-8,
+                # thus we pass decode_output=False.  Without this code we've seen errors like:
+                # "UnicodeDecodeError: 'utf8' codec can't decode byte 0x88 in position 779874: unexpected code byte"
+                self._port._run_script("run-leaks", self._leaks_args(name, pid), include_configuration_arguments=False, decode_output=False)
+                leaks_output = self._filesystem.read_binary_file(leaks_output_path)
         except ScriptError as e:
             _log.warn("Failed to run leaks tool: %s" % e.message_with_output())
             return
index 188b8bd..9fde270 100644 (file)
@@ -179,9 +179,22 @@ private:
     CompiledContentExtensionData m_data;
 };
 
+static std::pair<Vector<WebCore::ContentExtensions::Action>, Vector<String>> allActionsForResourceLoad(const ContentExtensions::ContentExtensionsBackend& backend, const ResourceLoadInfo& info)
+{
+    Vector<ContentExtensions::Action> actions;
+    Vector<String> identifiersApplyingStylesheets;
+    for (auto&& actionsFromContentRuleList : backend.actionsForResourceLoad(info)) {
+        for (auto&& action : WTFMove(actionsFromContentRuleList.actions))
+            actions.append(WTFMove(action));
+        if (!actionsFromContentRuleList.sawIgnorePreviousRules)
+            identifiersApplyingStylesheets.append(actionsFromContentRuleList.contentRuleListIdentifier);
+    }
+    return { WTFMove(actions), WTFMove(identifiersApplyingStylesheets) };
+}
+
 void static testRequest(const ContentExtensions::ContentExtensionsBackend& contentExtensionsBackend, const ResourceLoadInfo& resourceLoadInfo, Vector<ContentExtensions::ActionType> expectedActions, size_t stylesheets = 1)
 {
-    auto actions = contentExtensionsBackend.actionsForResourceLoad(resourceLoadInfo);
+    auto actions = allActionsForResourceLoad(contentExtensionsBackend, resourceLoadInfo);
     unsigned expectedSize = actions.first.size();
     EXPECT_EQ(expectedActions.size(), expectedSize);
     if (expectedActions.size() != expectedSize)
@@ -918,37 +931,38 @@ static const char* jsonWithStringsToCombine = "["
 
 TEST_F(ContentExtensionTest, StringParameters)
 {
+    using namespace ContentExtensions;
     auto backend1 = makeBackend("[{\"action\":{\"type\":\"notify\",\"notification\":\"testnotification\"},\"trigger\":{\"url-filter\":\"matches\"}}]");
-    ASSERT_TRUE(actionsEqual(backend1.actionsForResourceLoad(mainDocumentRequest("test:///matches")), {{ ContentExtensions::ActionType::Notify, "testnotification" }}));
+    ASSERT_TRUE(actionsEqual(allActionsForResourceLoad(backend1, mainDocumentRequest("test:///matches")), Vector<Action>::from(Action { ContentExtensions::ActionType::Notify, "testnotification" })));
 
     auto backend2 = makeBackend(jsonWithStringsToCombine);
-    ASSERT_TRUE(actionsEqual(backend2.actionsForResourceLoad(mainDocumentRequest("http://A")), {{ ContentExtensions::ActionType::Notify, "AAA" }}));
-    ASSERT_TRUE(actionsEqual(backend2.actionsForResourceLoad(mainDocumentRequest("http://B")), {{ ContentExtensions::ActionType::Notify, "BBB" }}));
-    ASSERT_TRUE(actionsEqual(backend2.actionsForResourceLoad(mainDocumentRequest("http://C")), {{ ContentExtensions::ActionType::CSSDisplayNoneSelector, "CCC,selectorCombinedWithC" }}));
-    ASSERT_TRUE(actionsEqual(backend2.actionsForResourceLoad(mainDocumentRequest("http://D")), {{ ContentExtensions::ActionType::CSSDisplayNoneSelector, "DDD" }}));
-    ASSERT_TRUE(actionsEqual(backend2.actionsForResourceLoad(mainDocumentRequest("http://E")), { }, true));
-    ASSERT_TRUE(actionsEqual(backend2.actionsForResourceLoad(mainDocumentRequest("http://F")), { ContentExtensions::ActionType::BlockLoad }));
-    ASSERT_TRUE(actionsEqual(backend2.actionsForResourceLoad(mainDocumentRequest("http://G")), {{ ContentExtensions::ActionType::Notify, "GGG" }}));
-    ASSERT_TRUE(actionsEqual(backend2.actionsForResourceLoad(mainDocumentRequest("http://GIK")), {{ ContentExtensions::ActionType::Notify, "GGG" }}));
-    ASSERT_TRUE(actionsEqual(backend2.actionsForResourceLoad(mainDocumentRequest("http://AJ")), {
-        { ContentExtensions::ActionType::Notify, "AAA" },
-        { ContentExtensions::ActionType::Notify, "AAA" } // ignore-previous-rules makes the AAA actions need to be unique.
-    }));
+    ASSERT_TRUE(actionsEqual(allActionsForResourceLoad(backend2, mainDocumentRequest("http://A")), Vector<Action>::from(Action { ContentExtensions::ActionType::Notify, "AAA" })));
+    ASSERT_TRUE(actionsEqual(allActionsForResourceLoad(backend2, mainDocumentRequest("http://B")), Vector<Action>::from(Action { ContentExtensions::ActionType::Notify, "BBB" })));
+    ASSERT_TRUE(actionsEqual(allActionsForResourceLoad(backend2, mainDocumentRequest("http://C")), Vector<Action>::from(Action { ContentExtensions::ActionType::CSSDisplayNoneSelector, "CCC,selectorCombinedWithC" })));
+    ASSERT_TRUE(actionsEqual(allActionsForResourceLoad(backend2, mainDocumentRequest("http://D")), Vector<Action>::from(Action { ContentExtensions::ActionType::CSSDisplayNoneSelector, "DDD" })));
+    ASSERT_TRUE(actionsEqual(allActionsForResourceLoad(backend2, mainDocumentRequest("http://E")), { }, true));
+    ASSERT_TRUE(actionsEqual(allActionsForResourceLoad(backend2, mainDocumentRequest("http://F")), Vector<Action>::from(Action { ContentExtensions::ActionType::BlockLoad })));
+    ASSERT_TRUE(actionsEqual(allActionsForResourceLoad(backend2, mainDocumentRequest("http://G")), Vector<Action>::from(Action { ContentExtensions::ActionType::Notify, "GGG" })));
+    ASSERT_TRUE(actionsEqual(allActionsForResourceLoad(backend2, mainDocumentRequest("http://GIK")), Vector<Action>::from(Action { ContentExtensions::ActionType::Notify, "GGG" })));
+    ASSERT_TRUE(actionsEqual(allActionsForResourceLoad(backend2, mainDocumentRequest("http://AJ")), Vector<Action>::from(
+        Action { ContentExtensions::ActionType::Notify, "AAA" },
+        Action { ContentExtensions::ActionType::Notify, "AAA" } // ignore-previous-rules makes the AAA actions need to be unique.
+    )));
     // FIXME: Add a test that matches actions with AAA with ignore-previous-rules between them and makes sure we only get one notification.
-    ASSERT_TRUE(actionsEqual(backend2.actionsForResourceLoad(mainDocumentRequest("http://AE")), { }, true));
-    ASSERT_TRUE(actionsEqual(backend2.actionsForResourceLoad(mainDocumentRequest("http://ABCDE")), { }, true));
-    ASSERT_TRUE(actionsEqual(backend2.actionsForResourceLoad(mainDocumentRequest("http://ABCDEFG")), {
-        { ContentExtensions::ActionType::Notify, "GGG" },
-        { ContentExtensions::ActionType::BlockLoad }
-    }, true));
-    ASSERT_TRUE(actionsEqual(backend2.actionsForResourceLoad(mainDocumentRequest("http://FG")), {
-        { ContentExtensions::ActionType::Notify, "GGG" },
-        { ContentExtensions::ActionType::BlockLoad }
-    }));
-    ASSERT_TRUE(actionsEqual(backend2.actionsForResourceLoad(mainDocumentRequest("http://EFG")), {
-        { ContentExtensions::ActionType::Notify, "GGG" },
-        { ContentExtensions::ActionType::BlockLoad }
-    }, true));
+    ASSERT_TRUE(actionsEqual(allActionsForResourceLoad(backend2, mainDocumentRequest("http://AE")), { }, true));
+    ASSERT_TRUE(actionsEqual(allActionsForResourceLoad(backend2, mainDocumentRequest("http://ABCDE")), { }, true));
+    ASSERT_TRUE(actionsEqual(allActionsForResourceLoad(backend2, mainDocumentRequest("http://ABCDEFG")), Vector<Action>::from(
+        Action { ContentExtensions::ActionType::Notify, "GGG" },
+        Action { ContentExtensions::ActionType::BlockLoad }
+    ), true));
+    ASSERT_TRUE(actionsEqual(allActionsForResourceLoad(backend2, mainDocumentRequest("http://FG")), Vector<Action>::from(
+        Action { ContentExtensions::ActionType::Notify, "GGG" },
+        Action { ContentExtensions::ActionType::BlockLoad }
+    )));
+    ASSERT_TRUE(actionsEqual(allActionsForResourceLoad(backend2, mainDocumentRequest("http://EFG")), Vector<Action>::from(
+        Action { ContentExtensions::ActionType::Notify, "GGG" },
+        Action { ContentExtensions::ActionType::BlockLoad }
+    ), true));
 }
 
 template<typename T, size_t cStringLength>
index 44c55af..6b1a0f6 100644 (file)
 #import <WebKit/WKURLSchemeHandler.h>
 #import <WebKit/WKUserContentController.h>
 #import <WebKit/WKWebView.h>
+#import <WebKit/_WKContentRuleListAction.h>
 #import <wtf/RetainPtr.h>
+#import <wtf/URL.h>
+#import <wtf/text/WTFString.h>
 
 static bool receivedNotification;
 static bool receivedAlert;
 
+struct Notification {
+    String identifier;
+    String url;
+    bool blockedLoad { false };
+    bool blockedCookies { false };
+    bool madeHTTPS { false };
+    Vector<String> notifications;
+    
+    bool operator==(const Notification& other) const
+    {
+        return identifier == other.identifier
+            && url == other.url
+            && blockedLoad == other.blockedLoad
+            && blockedCookies == other.blockedCookies
+            && madeHTTPS == other.madeHTTPS
+            && notifications == other.notifications;
+    }
+};
+
+static Vector<String> toVector(NSArray<NSString *> *array)
+{
+    Vector<String> vector;
+    vector.reserveInitialCapacity(array.count);
+    for (NSString *string in array)
+        vector.append(string);
+    return vector;
+}
+
+static Vector<Notification> notificationList;
+static RetainPtr<NSURL> notificationURL;
+static RetainPtr<NSString> notificationIdentifier;
+
 @interface ContentRuleListNotificationDelegate : NSObject <WKNavigationDelegatePrivate, WKURLSchemeHandler, WKUIDelegate>
 @end
 
@@ -43,14 +78,19 @@ static bool receivedAlert;
 
 - (void)_webView:(WKWebView *)webView URL:(NSURL *)url contentRuleListIdentifiers:(NSArray<NSString *> *)identifiers notifications:(NSArray<NSString *> *)notifications
 {
-    EXPECT_STREQ(url.absoluteString.UTF8String, "apitest:///match");
+    notificationURL = url;
     EXPECT_EQ(identifiers.count, 1u);
-    EXPECT_STREQ([identifiers objectAtIndex:0].UTF8String, "testidentifier");
+    notificationIdentifier = [identifiers objectAtIndex:0];
     EXPECT_EQ(notifications.count, 1u);
     EXPECT_STREQ([notifications objectAtIndex:0].UTF8String, "testnotification");
     receivedNotification = true;
 }
 
+- (void)_webView:(WKWebView *)webView contentRuleListWithIdentifier:(NSString *)identifier performedAction:(_WKContentRuleListAction *)action forURL:(NSURL *)url
+{
+    notificationList.append({ identifier, url.absoluteString, !!action.blockedLoad, !!action.blockedCookies, !!action.madeHTTPS, toVector(action.notifications) });
+}
+
 - (void)webView:(WKWebView *)webView startURLSchemeTask:(id <WKURLSchemeTask>)urlSchemeTask
 {
     [urlSchemeTask didReceiveResponse:[[[NSURLResponse alloc] initWithURL:urlSchemeTask.request.URL MIMEType:@"text/html" expectedContentLength:0 textEncodingName:nil] autorelease]];
@@ -69,11 +109,13 @@ static bool receivedAlert;
 
 @end
 
-static RetainPtr<WKContentRuleList> makeWarnContentRuleList()
+static NSString *notificationSource = @"[{\"action\":{\"type\":\"notify\",\"notification\":\"testnotification\"},\"trigger\":{\"url-filter\":\"match\"}}]";
+
+static RetainPtr<WKContentRuleList> makeContentRuleList(NSString *source, NSString *identifier = @"testidentifier")
 {
     __block bool doneCompiling = false;
     __block RetainPtr<WKContentRuleList> contentRuleList;
-    [[WKContentRuleListStore defaultStore] compileContentRuleListForIdentifier:@"testidentifier" encodedContentRuleList:@"[{\"action\":{\"type\":\"notify\",\"notification\":\"testnotification\"},\"trigger\":{\"url-filter\":\"match\"}}]" completionHandler:^(WKContentRuleList *list, NSError *error) {
+    [[WKContentRuleListStore defaultStore] compileContentRuleListForIdentifier:identifier encodedContentRuleList:source completionHandler:^(WKContentRuleList *list, NSError *error) {
         EXPECT_TRUE(list);
         contentRuleList = list;
         doneCompiling = true;
@@ -86,19 +128,21 @@ TEST(WebKit, ContentRuleListNotificationMainResource)
 {
     auto delegate = adoptNS([[ContentRuleListNotificationDelegate alloc] init]);
     auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
-    [[configuration userContentController] addContentRuleList:makeWarnContentRuleList().get()];
+    [[configuration userContentController] addContentRuleList:makeContentRuleList(notificationSource).get()];
     [configuration setURLSchemeHandler:delegate.get() forURLScheme:@"apitest"];
     auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
     [webView setNavigationDelegate:delegate.get()];
     [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"apitest:///match"]]];
     TestWebKitAPI::Util::run(&receivedNotification);
+    EXPECT_STREQ([notificationURL absoluteString].UTF8String, "apitest:///match");
+    EXPECT_STREQ([notificationIdentifier UTF8String], "testidentifier");
 }
 
 TEST(WebKit, ContentRuleListNotificationSubresource)
 {
     auto delegate = adoptNS([[ContentRuleListNotificationDelegate alloc] init]);
     auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
-    [[configuration userContentController] addContentRuleList:makeWarnContentRuleList().get()];
+    [[configuration userContentController] addContentRuleList:makeContentRuleList(notificationSource).get()];
     [configuration setURLSchemeHandler:delegate.get() forURLScheme:@"apitest"];
     auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
     [webView setNavigationDelegate:delegate.get()];
@@ -106,4 +150,28 @@ TEST(WebKit, ContentRuleListNotificationSubresource)
     [webView loadHTMLString:@"<script>fetch('match').then(function(response){alert('fetch complete')})</script>" baseURL:[NSURL URLWithString:@"apitest:///"]];
     TestWebKitAPI::Util::run(&receivedAlert);
     EXPECT_TRUE(receivedNotification);
+    EXPECT_STREQ([notificationURL absoluteString].UTF8String, "apitest:///match");
+    EXPECT_STREQ([notificationIdentifier UTF8String], "testidentifier");
+}
+
+TEST(WebKit, PerformedActionForURL)
+{
+    NSString *firstList = @"[{\"action\":{\"type\":\"notify\",\"notification\":\"testnotification\"},\"trigger\":{\"url-filter\":\"notify\"}}]";
+    NSString *secondList = @"[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"block\"}}]";
+    auto delegate = adoptNS([[ContentRuleListNotificationDelegate alloc] init]);
+    auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
+    [[configuration userContentController] addContentRuleList:makeContentRuleList(firstList, @"firstList").get()];
+    [[configuration userContentController] addContentRuleList:makeContentRuleList(secondList, @"secondList").get()];
+    [configuration setURLSchemeHandler:delegate.get() forURLScheme:@"apitest"];
+    auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
+    [webView setNavigationDelegate:delegate.get()];
+    [webView setUIDelegate:delegate.get()];
+    [webView loadHTMLString:@"<script>fetch('notify').then(function(){fetch('block').then().catch(function(){alert('test complete')})})</script>" baseURL:[NSURL URLWithString:@"apitest:///"]];
+    TestWebKitAPI::Util::run(&receivedAlert);
+    
+    Vector<Notification> expectedNotifications {
+        { "firstList", "apitest:///notify", false, false, false, { "testnotification" } },
+        { "secondList", "apitest:///block", true, false, false, { } }
+    };
+    EXPECT_TRUE(expectedNotifications == notificationList);
 }
index f547fd1..3197f62 100644 (file)
 
 + (NSPoint)mouseLocation
 {
+    return NSMakePoint(0, 0);
+    /*
     WKPoint location = WTR::TestController::singleton().eventSenderProxy()->position();
     return [WTR::TestController::singleton().mainWebView()->platformWindow() convertBaseToScreen:NSMakePoint(location.x, location.y)];
+     */
 }
 
 @end