Title: [258054] trunk
Revision
258054
Author
[email protected]
Date
2020-03-06 20:48:50 -0800 (Fri, 06 Mar 2020)

Log Message

UIProcess needs mechanism to specify AppBound domains
https://bugs.webkit.org/show_bug.cgi?id=208528
<rdar://problem/59980340>

Reviewed by Brent Fulgham.

Source/WebKit:

Adds functionality to read app-bound domains from the Info.plist on
background thread via the WebFramePolicyListenerProxy and report
whether a domain is app-bound.

* UIProcess/API/Cocoa/WKWebsiteDataStore.mm:
(-[WKWebsiteDataStore _appBoundDomains:]):
* UIProcess/API/Cocoa/WKWebsiteDataStorePrivate.h:
Test API call to get appBoundDomains.

* UIProcess/WebFramePolicyListenerProxy.cpp:
(WebKit::WebFramePolicyListenerProxy::WebFramePolicyListenerProxy):
(WebKit::WebFramePolicyListenerProxy::didReceiveAppBoundDomainResult):
(WebFramePolicyListenerProxy::didReceiveSafeBrowsingResults):
(WebFramePolicyListenerProxy::use):
(WebFramePolicyListenerProxy::download):
(WebFramePolicyListenerProxy::ignore):
* UIProcess/WebFramePolicyListenerProxy.h:
(WebKit::WebFramePolicyListenerProxy::create):
* UIProcess/WebFrameProxy.cpp:
(WebKit::WebFrameProxy::setUpPolicyListenerProxy):
* UIProcess/WebFrameProxy.h:
* UIProcess/WebPageProxy.cpp:
Added a new function to WebFramePolicyListenerProxy to wait for the
app-bound domains to be read before completing a navigation. Each
other function must now check if m_isNavigatingToAppBoundDomain has
been set before sending a full reply. Also added an enum class
ShouldExpectAppBoundDomainResult to tell the listener not to wait for
the results in unecessary cases.

(WebKit::WebPageProxy::isAppBoundDomain const): Deleted
(WebKit::WebPageProxy::setIsNavigatingToAppBoundDomain):
(WebKit::WebPageProxy::decidePolicyForNavigationAction):
After the listener responds with the results, set the new
value in WebPageProxy. We no longer need to check for isAppBound
domain now that we have received the value.

(WebKit::WebPageProxy::decidePolicyForNewWindowAction):
(WebKit::WebPageProxy::decidePolicyForResponseShared):
No need to listen for app-bound domain response here.

* UIProcess/WebPageProxy.h:
* UIProcess/WebsiteData/Cocoa/WebsiteDataStoreCocoa.mm:
(WebKit::appBoundDomains):
(WebKit::appBoundDomainQueue):
Add a separate static queue for reading app-bound domains to avoid
raciness.

(WebKit::WebsiteDataStore::beginAppBoundDomainCheck):
(WebKit::WebsiteDataStore::getAppBoundDomainsForTesting):
* UIProcess/WebsiteData/WebsiteDataStore.h:
Read the app-bound domain list on the background thread, and once
done, call the listener on the main thread.

Tools:

Added test app-bound domains to the plist and tested that the domains
are properly stored in the website data store after a navigation.

* TestWebKitAPI/Info.plist:
* TestWebKitAPI/Tests/WebKitCocoa/InAppBrowserPrivacy.mm:
(TEST):

Modified Paths

Diff

Modified: trunk/Source/WebKit/ChangeLog (258053 => 258054)


--- trunk/Source/WebKit/ChangeLog	2020-03-07 04:32:32 UTC (rev 258053)
+++ trunk/Source/WebKit/ChangeLog	2020-03-07 04:48:50 UTC (rev 258054)
@@ -1,3 +1,64 @@
+2020-03-06  Kate Cheney  <[email protected]>
+
+        UIProcess needs mechanism to specify AppBound domains
+        https://bugs.webkit.org/show_bug.cgi?id=208528
+        <rdar://problem/59980340>
+
+        Reviewed by Brent Fulgham.
+
+        Adds functionality to read app-bound domains from the Info.plist on
+        background thread via the WebFramePolicyListenerProxy and report
+        whether a domain is app-bound. 
+
+        * UIProcess/API/Cocoa/WKWebsiteDataStore.mm:
+        (-[WKWebsiteDataStore _appBoundDomains:]):
+        * UIProcess/API/Cocoa/WKWebsiteDataStorePrivate.h:
+        Test API call to get appBoundDomains.
+
+        * UIProcess/WebFramePolicyListenerProxy.cpp:
+        (WebKit::WebFramePolicyListenerProxy::WebFramePolicyListenerProxy):
+        (WebKit::WebFramePolicyListenerProxy::didReceiveAppBoundDomainResult):
+        (WebFramePolicyListenerProxy::didReceiveSafeBrowsingResults):
+        (WebFramePolicyListenerProxy::use):
+        (WebFramePolicyListenerProxy::download):
+        (WebFramePolicyListenerProxy::ignore):
+        * UIProcess/WebFramePolicyListenerProxy.h:
+        (WebKit::WebFramePolicyListenerProxy::create):
+        * UIProcess/WebFrameProxy.cpp:
+        (WebKit::WebFrameProxy::setUpPolicyListenerProxy):
+        * UIProcess/WebFrameProxy.h:
+        * UIProcess/WebPageProxy.cpp:
+        Added a new function to WebFramePolicyListenerProxy to wait for the
+        app-bound domains to be read before completing a navigation. Each
+        other function must now check if m_isNavigatingToAppBoundDomain has
+        been set before sending a full reply. Also added an enum class
+        ShouldExpectAppBoundDomainResult to tell the listener not to wait for
+        the results in unecessary cases.
+
+        (WebKit::WebPageProxy::isAppBoundDomain const): Deleted
+        (WebKit::WebPageProxy::setIsNavigatingToAppBoundDomain):
+        (WebKit::WebPageProxy::decidePolicyForNavigationAction):
+        After the listener responds with the results, set the new
+        value in WebPageProxy. We no longer need to check for isAppBound
+        domain now that we have received the value.
+
+        (WebKit::WebPageProxy::decidePolicyForNewWindowAction):
+        (WebKit::WebPageProxy::decidePolicyForResponseShared):
+        No need to listen for app-bound domain response here.
+
+        * UIProcess/WebPageProxy.h:
+        * UIProcess/WebsiteData/Cocoa/WebsiteDataStoreCocoa.mm:
+        (WebKit::appBoundDomains):
+        (WebKit::appBoundDomainQueue):
+        Add a separate static queue for reading app-bound domains to avoid
+        raciness.
+
+        (WebKit::WebsiteDataStore::beginAppBoundDomainCheck):
+        (WebKit::WebsiteDataStore::getAppBoundDomainsForTesting):
+        * UIProcess/WebsiteData/WebsiteDataStore.h:
+        Read the app-bound domain list on the background thread, and once
+        done, call the listener on the main thread.
+
 2020-03-06  David Kilzer  <[email protected]>
 
         IPC hardening for WebPageProxy::SaveImageToLibrary message

Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataStore.mm (258053 => 258054)


--- trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataStore.mm	2020-03-07 04:32:32 UTC (rev 258053)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataStore.mm	2020-03-07 04:48:50 UTC (rev 258054)
@@ -600,4 +600,15 @@
     return wrapper(_websiteDataStore->configuration().copy());
 }
 
+- (void)_appBoundDomains:(void (^)(NSArray<NSString *> *))completionHandler
+{
+    _websiteDataStore->appBoundDomainsForTesting([completionHandler = makeBlockPtr(completionHandler)](auto& domains) mutable {
+        Vector<RefPtr<API::Object>> apiDomains;
+        apiDomains.reserveInitialCapacity(domains.size());
+        for (auto& domain : domains)
+            apiDomains.uncheckedAppend(API::String::create(domain.string()));
+        completionHandler(wrapper(API::Array::create(WTFMove(apiDomains))));
+    });
+}
+
 @end

Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataStorePrivate.h (258053 => 258054)


--- trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataStorePrivate.h	2020-03-07 04:32:32 UTC (rev 258053)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataStorePrivate.h	2020-03-07 04:48:50 UTC (rev 258054)
@@ -77,6 +77,7 @@
 - (void)_clearResourceLoadStatistics:(void (^)(void))completionHandler WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));
 - (void)_isRegisteredAsSubresourceUnderFirstParty:(NSURL *)firstPartyURL thirdParty:(NSURL *)thirdPartyURL completionHandler:(void (^)(BOOL))completionHandler WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));
 - (void)_processStatisticsAndDataRecords:(void (^)(void))completionHandler WK_API_AVAILABLE(macos(10.15), ios(13.0));
+- (void)_appBoundDomains:(void (^)(NSArray<NSString *> *))completionHandler WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));
 
 @property (nullable, nonatomic, weak) id <_WKWebsiteDataStoreDelegate> _delegate WK_API_AVAILABLE(macos(10.15), ios(13.0));
 @property (nonatomic, readonly, copy) _WKWebsiteDataStoreConfiguration *_configuration;

Modified: trunk/Source/WebKit/UIProcess/WebFramePolicyListenerProxy.cpp (258053 => 258054)


--- trunk/Source/WebKit/UIProcess/WebFramePolicyListenerProxy.cpp	2020-03-07 04:32:32 UTC (rev 258053)
+++ trunk/Source/WebKit/UIProcess/WebFramePolicyListenerProxy.cpp	2020-03-07 04:48:50 UTC (rev 258054)
@@ -35,21 +35,36 @@
 
 namespace WebKit {
 
-WebFramePolicyListenerProxy::WebFramePolicyListenerProxy(Reply&& reply, ShouldExpectSafeBrowsingResult expect)
+WebFramePolicyListenerProxy::WebFramePolicyListenerProxy(Reply&& reply, ShouldExpectSafeBrowsingResult expectSafeBrowsingResult, ShouldExpectAppBoundDomainResult expectAppBoundDomainResult)
     : m_reply(WTFMove(reply))
 {
-    if (expect == ShouldExpectSafeBrowsingResult::No)
+    if (expectSafeBrowsingResult == ShouldExpectSafeBrowsingResult::No)
         didReceiveSafeBrowsingResults({ });
+    if (expectAppBoundDomainResult == ShouldExpectAppBoundDomainResult::No)
+        didReceiveAppBoundDomainResult({ });
 }
 
 WebFramePolicyListenerProxy::~WebFramePolicyListenerProxy() = default;
 
+void WebFramePolicyListenerProxy::didReceiveAppBoundDomainResult(bool isNavigatingToAppBoundDomain)
+{
+    ASSERT(RunLoop::isMain());
+
+    auto isAppBound = isNavigatingToAppBoundDomain ? NavigatingToAppBoundDomain::Yes : NavigatingToAppBoundDomain::No;
+    if (m_policyResult && m_safeBrowsingWarning) {
+        if (m_reply)
+            m_reply(WebCore::PolicyAction::Use, m_policyResult->first.get(), m_policyResult->second, WTFMove(*m_safeBrowsingWarning), isAppBound);
+    } else
+        m_isNavigatingToAppBoundDomain = isAppBound;
+}
+
 void WebFramePolicyListenerProxy::didReceiveSafeBrowsingResults(RefPtr<SafeBrowsingWarning>&& safeBrowsingWarning)
 {
+    ASSERT(isMainThread());
     ASSERT(!m_safeBrowsingWarning);
-    if (m_policyResult) {
+    if (m_policyResult && m_isNavigatingToAppBoundDomain) {
         if (m_reply)
-            m_reply(WebCore::PolicyAction::Use, m_policyResult->first.get(), m_policyResult->second, WTFMove(safeBrowsingWarning));
+            m_reply(WebCore::PolicyAction::Use, m_policyResult->first.get(), m_policyResult->second, WTFMove(safeBrowsingWarning), *m_isNavigatingToAppBoundDomain);
     } else
         m_safeBrowsingWarning = WTFMove(safeBrowsingWarning);
 }
@@ -56,9 +71,9 @@
 
 void WebFramePolicyListenerProxy::use(API::WebsitePolicies* policies, ProcessSwapRequestedByClient processSwapRequestedByClient)
 {
-    if (m_safeBrowsingWarning) {
+    if (m_safeBrowsingWarning && m_isNavigatingToAppBoundDomain) {
         if (m_reply)
-            m_reply(WebCore::PolicyAction::Use, policies, processSwapRequestedByClient, WTFMove(*m_safeBrowsingWarning));
+            m_reply(WebCore::PolicyAction::Use, policies, processSwapRequestedByClient, WTFMove(*m_safeBrowsingWarning), *m_isNavigatingToAppBoundDomain);
     } else if (!m_policyResult)
         m_policyResult = {{ policies, processSwapRequestedByClient }};
 }
@@ -66,13 +81,13 @@
 void WebFramePolicyListenerProxy::download()
 {
     if (m_reply)
-        m_reply(WebCore::PolicyAction::Download, nullptr, ProcessSwapRequestedByClient::No, { });
+        m_reply(WebCore::PolicyAction::Download, nullptr, ProcessSwapRequestedByClient::No, { }, { });
 }
 
 void WebFramePolicyListenerProxy::ignore()
 {
     if (m_reply)
-        m_reply(WebCore::PolicyAction::Ignore, nullptr, ProcessSwapRequestedByClient::No, { });
+        m_reply(WebCore::PolicyAction::Ignore, nullptr, ProcessSwapRequestedByClient::No, { }, { });
 }
 
 } // namespace WebKit

Modified: trunk/Source/WebKit/UIProcess/WebFramePolicyListenerProxy.h (258053 => 258054)


--- trunk/Source/WebKit/UIProcess/WebFramePolicyListenerProxy.h	2020-03-07 04:32:32 UTC (rev 258053)
+++ trunk/Source/WebKit/UIProcess/WebFramePolicyListenerProxy.h	2020-03-07 04:48:50 UTC (rev 258054)
@@ -26,6 +26,7 @@
 #pragma once
 
 #include "APIObject.h"
+#include "PolicyDecision.h"
 #include <WebCore/FrameLoaderTypes.h>
 #include <wtf/CompletionHandler.h>
 #include <wtf/Vector.h>
@@ -38,16 +39,17 @@
 
 class SafeBrowsingWarning;
 
-enum class ProcessSwapRequestedByClient { No, Yes };
-enum class ShouldExpectSafeBrowsingResult { No, Yes };
+enum class ProcessSwapRequestedByClient : bool { No, Yes };
+enum class ShouldExpectSafeBrowsingResult : bool { No, Yes };
+enum class ShouldExpectAppBoundDomainResult : bool { No, Yes };
 
 class WebFramePolicyListenerProxy : public API::ObjectImpl<API::Object::Type::FramePolicyListener> {
 public:
 
-    using Reply = CompletionHandler<void(WebCore::PolicyAction, API::WebsitePolicies*, ProcessSwapRequestedByClient, RefPtr<SafeBrowsingWarning>&&)>;
-    static Ref<WebFramePolicyListenerProxy> create(Reply&& reply, ShouldExpectSafeBrowsingResult expect)
+    using Reply = CompletionHandler<void(WebCore::PolicyAction, API::WebsitePolicies*, ProcessSwapRequestedByClient, RefPtr<SafeBrowsingWarning>&&, NavigatingToAppBoundDomain)>;
+    static Ref<WebFramePolicyListenerProxy> create(Reply&& reply, ShouldExpectSafeBrowsingResult expectSafeBrowsingResult, ShouldExpectAppBoundDomainResult expectAppBoundDomainResult)
     {
-        return adoptRef(*new WebFramePolicyListenerProxy(WTFMove(reply), expect));
+        return adoptRef(*new WebFramePolicyListenerProxy(WTFMove(reply), expectSafeBrowsingResult, expectAppBoundDomainResult));
     }
     ~WebFramePolicyListenerProxy();
 
@@ -56,12 +58,14 @@
     void ignore();
     
     void didReceiveSafeBrowsingResults(RefPtr<SafeBrowsingWarning>&&);
+    void didReceiveAppBoundDomainResult(bool);
 
 private:
-    WebFramePolicyListenerProxy(Reply&&, ShouldExpectSafeBrowsingResult);
+    WebFramePolicyListenerProxy(Reply&&, ShouldExpectSafeBrowsingResult, ShouldExpectAppBoundDomainResult);
 
     Optional<std::pair<RefPtr<API::WebsitePolicies>, ProcessSwapRequestedByClient>> m_policyResult;
     Optional<RefPtr<SafeBrowsingWarning>> m_safeBrowsingWarning;
+    Optional<NavigatingToAppBoundDomain> m_isNavigatingToAppBoundDomain;
     Reply m_reply;
 };
 

Modified: trunk/Source/WebKit/UIProcess/WebFrameProxy.cpp (258053 => 258054)


--- trunk/Source/WebKit/UIProcess/WebFrameProxy.cpp	2020-03-07 04:32:32 UTC (rev 258053)
+++ trunk/Source/WebKit/UIProcess/WebFrameProxy.cpp	2020-03-07 04:48:50 UTC (rev 258054)
@@ -193,14 +193,14 @@
     m_title = title;
 }
 
-WebFramePolicyListenerProxy& WebFrameProxy::setUpPolicyListenerProxy(CompletionHandler<void(PolicyAction, API::WebsitePolicies*, ProcessSwapRequestedByClient, RefPtr<SafeBrowsingWarning>&&)>&& completionHandler, ShouldExpectSafeBrowsingResult expect)
+WebFramePolicyListenerProxy& WebFrameProxy::setUpPolicyListenerProxy(CompletionHandler<void(PolicyAction, API::WebsitePolicies*, ProcessSwapRequestedByClient, RefPtr<SafeBrowsingWarning>&&, NavigatingToAppBoundDomain)>&& completionHandler, ShouldExpectSafeBrowsingResult expectSafeBrowsingResult, ShouldExpectAppBoundDomainResult expectAppBoundDomainResult)
 {
     if (m_activeListener)
         m_activeListener->ignore();
-    m_activeListener = WebFramePolicyListenerProxy::create([this, protectedThis = makeRef(*this), completionHandler = WTFMove(completionHandler)] (PolicyAction action, API::WebsitePolicies* policies, ProcessSwapRequestedByClient processSwapRequestedByClient, RefPtr<SafeBrowsingWarning>&& safeBrowsingWarning) mutable {
-        completionHandler(action, policies, processSwapRequestedByClient, WTFMove(safeBrowsingWarning));
+    m_activeListener = WebFramePolicyListenerProxy::create([this, protectedThis = makeRef(*this), completionHandler = WTFMove(completionHandler)] (PolicyAction action, API::WebsitePolicies* policies, ProcessSwapRequestedByClient processSwapRequestedByClient, RefPtr<SafeBrowsingWarning>&& safeBrowsingWarning, NavigatingToAppBoundDomain isNavigatingToAppBoundDomain) mutable {
+        completionHandler(action, policies, processSwapRequestedByClient, WTFMove(safeBrowsingWarning), isNavigatingToAppBoundDomain);
         m_activeListener = nullptr;
-    }, expect);
+    }, expectSafeBrowsingResult, expectAppBoundDomainResult);
     return *m_activeListener;
 }
 

Modified: trunk/Source/WebKit/UIProcess/WebFrameProxy.h (258053 => 258054)


--- trunk/Source/WebKit/UIProcess/WebFrameProxy.h	2020-03-07 04:32:32 UTC (rev 258053)
+++ trunk/Source/WebKit/UIProcess/WebFrameProxy.h	2020-03-07 04:48:50 UTC (rev 258054)
@@ -53,8 +53,8 @@
 class WebCertificateInfo;
 class WebFramePolicyListenerProxy;
 class WebsiteDataStore;
-enum class ShouldExpectSafeBrowsingResult;
-enum class ProcessSwapRequestedByClient;
+enum class ShouldExpectSafeBrowsingResult : bool;
+enum class ProcessSwapRequestedByClient : bool;
 struct WebsitePoliciesData;
 
 class WebFrameProxy : public API::ObjectImpl<API::Object::Type::Frame> {
@@ -120,7 +120,7 @@
     void didSameDocumentNavigation(const URL&); // eg. anchor navigation, session state change.
     void didChangeTitle(const String&);
 
-    WebFramePolicyListenerProxy& setUpPolicyListenerProxy(CompletionHandler<void(WebCore::PolicyAction, API::WebsitePolicies*, ProcessSwapRequestedByClient, RefPtr<SafeBrowsingWarning>&&)>&&, ShouldExpectSafeBrowsingResult);
+    WebFramePolicyListenerProxy& setUpPolicyListenerProxy(CompletionHandler<void(WebCore::PolicyAction, API::WebsitePolicies*, ProcessSwapRequestedByClient, RefPtr<SafeBrowsingWarning>&&, NavigatingToAppBoundDomain)>&&, ShouldExpectSafeBrowsingResult, ShouldExpectAppBoundDomainResult);
 
 #if ENABLE(CONTENT_FILTERING)
     void contentFilterDidBlockLoad(WebCore::ContentFilterUnblockHandler contentFilterUnblockHandler) { m_contentFilterUnblockHandler = WTFMove(contentFilterUnblockHandler); }

Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.cpp (258053 => 258054)


--- trunk/Source/WebKit/UIProcess/WebPageProxy.cpp	2020-03-07 04:32:32 UTC (rev 258053)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.cpp	2020-03-07 04:48:50 UTC (rev 258054)
@@ -279,7 +279,6 @@
 #if USE(APPLE_INTERNAL_SDK)
 #include <WebKitAdditions/WebPageProxyAdditions.h>
 #else
-#define WEB_PAGE_PROXY_ADDITIONS_ISAPPBOUNDDOMAIN
 #define WEB_PAGE_PROXY_ADDITIONS_SETISNAVIGATINGTOAPPBOUNDDOMAIN
 #endif
 
@@ -3095,23 +3094,11 @@
     PolicyCheckIdentifier m_identifier;
 };
 
-
-bool WebPageProxy::isAppBoundDomain(const WebCore::RegistrableDomain& domain) const
+void WebPageProxy::setIsNavigatingToAppBoundDomain(bool isMainFrame, const URL& requestURL, NavigatingToAppBoundDomain isNavigatingToAppBoundDomain)
 {
-    WEB_PAGE_PROXY_ADDITIONS_ISAPPBOUNDDOMAIN
-    return true;
-}
-
-bool WebPageProxy::isAppBoundDomain(const URL& url) const
-{
-    return isAppBoundDomain(RegistrableDomain(url));
-}
-
-void WebPageProxy::setIsNavigatingToAppBoundDomain(bool isMainFrame, const URL& requestURL)
-{
     if (m_preferences->isInAppBrowserPrivacyEnabled() && isMainFrame) {
         WEB_PAGE_PROXY_ADDITIONS_SETISNAVIGATINGTOAPPBOUNDDOMAIN
-        if (!isAppBoundDomain(requestURL)) {
+        if (isNavigatingToAppBoundDomain == NavigatingToAppBoundDomain::No) {
             m_configuration->setWebViewCategory(WebViewCategory::InAppBrowser);
             m_isNavigatingToAppBoundDomain = NavigatingToAppBoundDomain::No;
             m_hasNavigatedAwayFromAppBoundDomain = NavigatedAwayFromAppBoundDomain::Yes;
@@ -5013,8 +5000,6 @@
     if (navigationID && !fromAPI)
         m_pageLoadState.clearPendingAPIRequest(transaction);
 
-    setIsNavigatingToAppBoundDomain(frame.isMainFrame(), request.url());
-
     if (!checkURLReceivedFromCurrentOrPreviousWebProcess(process, request.url())) {
         RELEASE_LOG_ERROR_IF_ALLOWED(Process, "Ignoring request to load this main resource because it is outside the sandbox");
         sender->send(PolicyDecision { sender->identifier(), isNavigatingToAppBoundDomain(), hasNavigatedAwayFromAppBoundDomain(), PolicyAction::Ignore, 0, DownloadID(), WTF::nullopt });
@@ -5070,8 +5055,16 @@
     if (!m_preferences->safeBrowsingEnabled())
         shouldExpectSafeBrowsingResult = ShouldExpectSafeBrowsingResult::No;
 
-    auto listener = makeRef(frame.setUpPolicyListenerProxy([this, protectedThis = makeRef(*this), frame = makeRef(frame), sender = WTFMove(sender), navigation] (PolicyAction policyAction, API::WebsitePolicies* policies, ProcessSwapRequestedByClient processSwapRequestedByClient, RefPtr<SafeBrowsingWarning>&& safeBrowsingWarning) mutable {
+    ShouldExpectAppBoundDomainResult shouldExpectAppBoundDomainResult = ShouldExpectAppBoundDomainResult::No;
+#if PLATFORM(COCOA)
+    shouldExpectAppBoundDomainResult = ShouldExpectAppBoundDomainResult::Yes;
+#endif
+    
+    auto listener = makeRef(frame.setUpPolicyListenerProxy([this, protectedThis = makeRef(*this), frame = makeRef(frame), sender = WTFMove(sender), navigation] (PolicyAction policyAction, API::WebsitePolicies* policies, ProcessSwapRequestedByClient processSwapRequestedByClient, RefPtr<SafeBrowsingWarning>&& safeBrowsingWarning, NavigatingToAppBoundDomain isAppBoundDomain) mutable {
 
+        if (policyAction != PolicyAction::Ignore)
+            setIsNavigatingToAppBoundDomain(frame->isMainFrame(), navigation->currentRequest().url(), isAppBoundDomain);
+
         auto completionHandler = [this, protectedThis = protectedThis.copyRef(), frame = frame.copyRef(), sender = WTFMove(sender), navigation, processSwapRequestedByClient, policies = makeRefPtr(policies)] (PolicyAction policyAction) mutable {
             if (frame->isMainFrame()) {
                 if (!policies) {
@@ -5118,10 +5111,12 @@
         }
         completionHandler(policyAction);
 
-    }, shouldExpectSafeBrowsingResult));
+    }, shouldExpectSafeBrowsingResult, shouldExpectAppBoundDomainResult));
     if (shouldExpectSafeBrowsingResult == ShouldExpectSafeBrowsingResult::Yes)
         beginSafeBrowsingCheck(request.url(), frame.isMainFrame(), listener);
-
+#if PLATFORM(COCOA)
+    m_websiteDataStore->beginAppBoundDomainCheck(RegistrableDomain { request.url() }, listener);
+#endif
     API::Navigation* mainFrameNavigation = frame.isMainFrame() ? navigation.get() : nullptr;
     WebFrameProxy* originatingFrame = originatingFrameInfoData.frameID ? process->webFrame(*originatingFrameInfoData.frameID) : nullptr;
 
@@ -5251,7 +5246,7 @@
     MESSAGE_CHECK(m_process, frame);
     MESSAGE_CHECK_URL(m_process, request.url());
 
-    auto listener = makeRef(frame->setUpPolicyListenerProxy([this, protectedThis = makeRef(*this), identifier, listenerID, frameID] (PolicyAction policyAction, API::WebsitePolicies*, ProcessSwapRequestedByClient processSwapRequestedByClient, RefPtr<SafeBrowsingWarning>&& safeBrowsingWarning) mutable {
+    auto listener = makeRef(frame->setUpPolicyListenerProxy([this, protectedThis = makeRef(*this), identifier, listenerID, frameID] (PolicyAction policyAction, API::WebsitePolicies*, ProcessSwapRequestedByClient processSwapRequestedByClient, RefPtr<SafeBrowsingWarning>&& safeBrowsingWarning, NavigatingToAppBoundDomain isNavigatingToAppBoundDomain) mutable {
         // FIXME: Assert the API::WebsitePolicies* is nullptr here once clients of WKFramePolicyListenerUseWithPolicies go away.
         RELEASE_ASSERT(processSwapRequestedByClient == ProcessSwapRequestedByClient::No);
         ASSERT_UNUSED(safeBrowsingWarning, !safeBrowsingWarning);
@@ -5261,7 +5256,7 @@
         });
 
         receivedPolicyDecision(policyAction, nullptr, WTF::nullopt, WTFMove(sender));
-    }, ShouldExpectSafeBrowsingResult::No));
+    }, ShouldExpectSafeBrowsingResult::No, ShouldExpectAppBoundDomainResult::No));
 
     if (m_policyClient)
         m_policyClient->decidePolicyForNewWindowAction(*this, *frame, navigationActionData, request, frameName, WTFMove(listener), m_process->transformHandlesToObjects(userData.object()).get());
@@ -5297,10 +5292,9 @@
     MESSAGE_CHECK(process, frame);
     MESSAGE_CHECK_URL(process, request.url());
     MESSAGE_CHECK_URL(process, response.url());
-
     RefPtr<API::Navigation> navigation = navigationID ? m_navigationState->navigation(navigationID) : nullptr;
     auto listener = makeRef(frame->setUpPolicyListenerProxy([this, protectedThis = makeRef(*this), webPageID, frameID, identifier, listenerID, navigation = WTFMove(navigation),
-        process = process.copyRef()] (PolicyAction policyAction, API::WebsitePolicies*, ProcessSwapRequestedByClient processSwapRequestedByClient, RefPtr<SafeBrowsingWarning>&& safeBrowsingWarning) mutable {
+        process = process.copyRef()] (PolicyAction policyAction, API::WebsitePolicies*, ProcessSwapRequestedByClient processSwapRequestedByClient, RefPtr<SafeBrowsingWarning>&& safeBrowsingWarning, NavigatingToAppBoundDomain isNavigatingToAppBoundDomain) mutable {
         // FIXME: Assert the API::WebsitePolicies* is nullptr here once clients of WKFramePolicyListenerUseWithPolicies go away.
         RELEASE_ASSERT(processSwapRequestedByClient == ProcessSwapRequestedByClient::No);
         ASSERT_UNUSED(safeBrowsingWarning, !safeBrowsingWarning);
@@ -5310,8 +5304,7 @@
         });
         
         receivedPolicyDecision(policyAction, navigation.get(), WTF::nullopt, WTFMove(sender));
-    }, ShouldExpectSafeBrowsingResult::No));
-
+    }, ShouldExpectSafeBrowsingResult::No, ShouldExpectAppBoundDomainResult::No));
     if (m_policyClient)
         m_policyClient->decidePolicyForResponse(*this, *frame, response, request, canShowMIMEType, WTFMove(listener), process->transformHandlesToObjects(userData.object()).get());
     else {

Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.h (258053 => 258054)


--- trunk/Source/WebKit/UIProcess/WebPageProxy.h	2020-03-07 04:32:32 UTC (rev 258053)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.h	2020-03-07 04:48:50 UTC (rev 258054)
@@ -345,7 +345,7 @@
 struct UserMessage;
 
 enum class NegotiatedLegacyTLS : bool;
-enum class ProcessSwapRequestedByClient;
+enum class ProcessSwapRequestedByClient : bool;
 enum class UndoOrRedo : bool;
 enum class WebContentMode : uint8_t;
 
@@ -2265,9 +2265,7 @@
     void tryCloseTimedOut();
     void makeStorageSpaceRequest(WebCore::FrameIdentifier, const String& originIdentifier, const String& databaseName, const String& displayName, uint64_t currentQuota, uint64_t currentOriginUsage, uint64_t currentDatabaseUsage, uint64_t expectedUsage, CompletionHandler<void(uint64_t)>&&);
         
-    bool isAppBoundDomain(const WebCore::RegistrableDomain&) const;
-    bool isAppBoundDomain(const URL&) const;
-    void setIsNavigatingToAppBoundDomain(bool isMainFrame, const URL&);
+    void setIsNavigatingToAppBoundDomain(bool isMainFrame, const URL&, NavigatingToAppBoundDomain);
     NavigatingToAppBoundDomain isNavigatingToAppBoundDomain() const { return m_isNavigatingToAppBoundDomain; }
     NavigatedAwayFromAppBoundDomain hasNavigatedAwayFromAppBoundDomain() const { return m_hasNavigatedAwayFromAppBoundDomain; }
         

Modified: trunk/Source/WebKit/UIProcess/WebProcessPool.h (258053 => 258054)


--- trunk/Source/WebKit/UIProcess/WebProcessPool.h	2020-03-07 04:32:32 UTC (rev 258053)
+++ trunk/Source/WebKit/UIProcess/WebProcessPool.h	2020-03-07 04:48:50 UTC (rev 258054)
@@ -123,7 +123,7 @@
 int webProcessThroughputQOS();
 #endif
 
-enum class ProcessSwapRequestedByClient;
+enum class ProcessSwapRequestedByClient : bool;
 
 class WebProcessPool final : public API::ObjectImpl<API::Object::Type::ProcessPool>, public CanMakeWeakPtr<WebProcessPool>, private IPC::MessageReceiver {
 public:

Modified: trunk/Source/WebKit/UIProcess/WebsiteData/Cocoa/WebsiteDataStoreCocoa.mm (258053 => 258054)


--- trunk/Source/WebKit/UIProcess/WebsiteData/Cocoa/WebsiteDataStoreCocoa.mm	2020-03-07 04:32:32 UTC (rev 258053)
+++ trunk/Source/WebKit/UIProcess/WebsiteData/Cocoa/WebsiteDataStoreCocoa.mm	2020-03-07 04:48:50 UTC (rev 258054)
@@ -29,6 +29,7 @@
 #import "CookieStorageUtilsCF.h"
 #import "SandboxUtilities.h"
 #import "StorageManager.h"
+#import "WebFramePolicyListenerProxy.h"
 #import "WebPreferencesKeys.h"
 #import "WebResourceLoadStatisticsStore.h"
 #import "WebsiteDataStoreParameters.h"
@@ -44,6 +45,12 @@
 #import <wtf/URL.h>
 #import <wtf/text/StringBuilder.h>
 
+#if USE(APPLE_INTERNAL_SDK)
+#include <WebKitAdditions/WebsiteDataStoreAdditions.h>
+#else
+#define WEBSITE_DATA_STORE_ADDITIONS
+#endif
+
 #if PLATFORM(IOS_FAMILY)
 #import <UIKit/UIApplication.h>
 #import <pal/ios/ManagedConfigurationSoftLink.h>
@@ -61,6 +68,14 @@
 
 static NSString * const WebKitNetworkLoadThrottleLatencyMillisecondsDefaultsKey = @"WebKitNetworkLoadThrottleLatencyMilliseconds";
 
+static WorkQueue& appBoundDomainQueue()
+{
+    static auto& queue = WorkQueue::create("com.apple.WebKit.AppBoundDomains", WorkQueue::Type::Serial).leakRef();
+    return queue;
+}
+
+static std::atomic<bool> hasInitializedAppBoundDomains = false;
+
 #if ENABLE(RESOURCE_LOAD_STATISTICS)
 WebCore::ThirdPartyCookieBlockingMode WebsiteDataStore::thirdPartyCookieBlockingMode() const
 {
@@ -244,6 +259,8 @@
 {
     ASSERT(!dataStores().contains(this));
     dataStores().add(this);
+
+    initializeAppBoundDomains();
 }
 
 void WebsiteDataStore::platformDestroy()
@@ -419,4 +436,75 @@
     return url.absoluteURL.path.fileSystemRepresentation;
 }
 
+static HashSet<WebCore::RegistrableDomain>& appBoundDomains()
+{
+    ASSERT(RunLoop::isMain());
+    static NeverDestroyed<HashSet<WebCore::RegistrableDomain>> appBoundDomains;
+    return appBoundDomains;
 }
+
+void WebsiteDataStore::initializeAppBoundDomains()
+{
+    ASSERT(RunLoop::isMain());
+
+    if (hasInitializedAppBoundDomains)
+        return;
+    
+    static const auto maxAppBoundDomainCount = 10;
+    
+    appBoundDomainQueue().dispatch([] () mutable {
+        if (hasInitializedAppBoundDomains)
+            return;
+        
+        NSArray<NSString *> *domains = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"WKAppBoundDomains"];
+        
+        RunLoop::main().dispatch([domains = retainPtr(domains)] {
+            for (NSString *domain in domains.get()) {
+                URL url { URL(), domain };
+                if (!url.isValid())
+                    continue;
+                WebCore::RegistrableDomain appBoundDomain { url };
+                if (appBoundDomain.isEmpty())
+                    continue;
+                appBoundDomains().add(appBoundDomain);
+                if (appBoundDomains().size() >= maxAppBoundDomainCount)
+                    break;
+            }
+            WEBSITE_DATA_STORE_ADDITIONS
+            hasInitializedAppBoundDomains = true;
+        });
+    });
+}
+
+void WebsiteDataStore::ensureAppBoundDomains(CompletionHandler<void(const HashSet<WebCore::RegistrableDomain>&)>&& completionHandler) const
+{
+    if (hasInitializedAppBoundDomains) {
+        completionHandler(appBoundDomains());
+        return;
+    }
+
+    appBoundDomainQueue().dispatch([completionHandler = WTFMove(completionHandler)] () mutable {
+        RunLoop::main().dispatch([completionHandler = WTFMove(completionHandler)] () mutable {
+            ASSERT(hasInitializedAppBoundDomains);
+            completionHandler(appBoundDomains());
+        });
+    });
+}
+
+void WebsiteDataStore::beginAppBoundDomainCheck(WebCore::RegistrableDomain&& domain, WebFramePolicyListenerProxy& listener)
+{
+    ASSERT(RunLoop::isMain());
+
+    ensureAppBoundDomains([domain = WTFMove(domain), listener = makeRef(listener)] (auto& domains) mutable {
+        listener->didReceiveAppBoundDomainResult(domains.contains(domain));
+    });
+}
+
+void WebsiteDataStore::appBoundDomainsForTesting(CompletionHandler<void(const HashSet<WebCore::RegistrableDomain>&)>&& completionHandler) const
+{
+    ensureAppBoundDomains([completionHandler = WTFMove(completionHandler)] (auto& domains) mutable {
+        completionHandler(domains);
+    });
+}
+
+}

Modified: trunk/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.h (258053 => 258054)


--- trunk/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.h	2020-03-07 04:32:32 UTC (rev 258053)
+++ trunk/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStore.h	2020-03-07 04:48:50 UTC (rev 258054)
@@ -28,6 +28,7 @@
 #include "LocalStorageDatabaseTracker.h"
 #include "NetworkSessionCreationParameters.h"
 #include "WebDeviceOrientationAndMotionAccessController.h"
+#include "WebFramePolicyListenerProxy.h"
 #include "WebPageProxyIdentifier.h"
 #include "WebResourceLoadStatisticsStore.h"
 #include "WebsiteDataStoreClient.h"
@@ -282,7 +283,12 @@
     void hasAppBoundSession(CompletionHandler<void(bool)>&&) const;
     void setInAppBrowserPrivacyEnabled(bool enabled, CompletionHandler<void()>&&);
 
+    void beginAppBoundDomainCheck(WebCore::RegistrableDomain&&, WebFramePolicyListenerProxy&);
+    void appBoundDomainsForTesting(CompletionHandler<void(const HashSet<WebCore::RegistrableDomain>&)>&&) const;
+    void ensureAppBoundDomains(CompletionHandler<void(const HashSet<WebCore::RegistrableDomain>&)>&&) const;
+
 private:
+    void initializeAppBoundDomains();
     void fetchDataAndApply(OptionSet<WebsiteDataType>, OptionSet<WebsiteDataFetchOption>, RefPtr<WorkQueue>&&, Function<void(Vector<WebsiteDataRecord>)>&& apply);
 
     void platformInitialize();

Modified: trunk/Tools/ChangeLog (258053 => 258054)


--- trunk/Tools/ChangeLog	2020-03-07 04:32:32 UTC (rev 258053)
+++ trunk/Tools/ChangeLog	2020-03-07 04:48:50 UTC (rev 258054)
@@ -1,3 +1,18 @@
+2020-03-06  Kate Cheney  <[email protected]>
+
+        UIProcess needs mechanism to specify AppBound domains
+        https://bugs.webkit.org/show_bug.cgi?id=208528
+        <rdar://problem/59980340>
+
+        Reviewed by Brent Fulgham.
+
+        Added test app-bound domains to the plist and tested that the domains
+        are properly stored in the website data store after a navigation.
+
+        * TestWebKitAPI/Info.plist:
+        * TestWebKitAPI/Tests/WebKitCocoa/InAppBrowserPrivacy.mm:
+        (TEST):
+
 2020-03-06  Alex Christensen  <[email protected]>
 
         Add SPI to disable cross origin access control checks

Modified: trunk/Tools/TestWebKitAPI/Info.plist (258053 => 258054)


--- trunk/Tools/TestWebKitAPI/Info.plist	2020-03-07 04:32:32 UTC (rev 258053)
+++ trunk/Tools/TestWebKitAPI/Info.plist	2020-03-07 04:48:50 UTC (rev 258054)
@@ -2,6 +2,25 @@
 <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
 <plist version="1.0">
 <dict>
+	<key>WKAppBoundDomains</key>
+	<array>
+		<string>testDomain1</string>
+		<string>https://sub.domain.webkit.org/road/to/nowhere/</string>
+		<string>https://webkit.org</string>
+		<string>https://localhost:8000</string>
+		<string>http://localhost/road/to/nowhere/</string>
+		<string>file:///some/file</string>
+		<string>127.0.0.1</string>
+		<string></string>
+		<string>   </string>
+		<string>https://sub.domain.webkit.org</string>
+		<string>https://www.apple.com/</string>
+		<string>https://webkit.org</string>
+		<string>https://www.apple.com/iphone/</string>
+		<string>http://www.example.com/</string>
+		<string>http://bar.com/</string>
+		<string>http://foo.com/</string>
+	</array>
 	<key>CFBundleName</key>
 	<string>${PRODUCT_NAME}</string>
 	<key>CFBundleIdentifier</key>

Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/InAppBrowserPrivacy.mm (258053 => 258054)


--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/InAppBrowserPrivacy.mm	2020-03-07 04:32:32 UTC (rev 258053)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/InAppBrowserPrivacy.mm	2020-03-07 04:48:50 UTC (rev 258054)
@@ -29,13 +29,17 @@
 #import "TestNavigationDelegate.h"
 #import "TestWKWebView.h"
 #import "WKWebViewConfigurationExtras.h"
+#import <WebCore/RegistrableDomain.h>
+#import <WebCore/RuntimeApplicationChecks.h>
 #import <WebKit/WKPreferencesPrivate.h>
 #import <WebKit/WKUserContentControllerPrivate.h>
+#import <WebKit/WKWebsiteDataStorePrivate.h>
 #import <wtf/text/WTFString.h>
 
+static bool isDone;
+
 #if USE(APPLE_INTERNAL_SDK)
 
-static bool isDone;
 static NSString * const userScriptSource = @"window.wkUserScriptInjected = true";
 
 @interface TestInAppBrowserScriptMessageHandler : NSObject <WKScriptMessageHandler>
@@ -50,7 +54,7 @@
 
 @end
 
-TEST(WebKit, NonAppBoundDomainFailedUserScripts)
+TEST(InAppBrowserPrivacy, NonAppBoundDomainFailedUserScripts)
 {
     auto messageHandler = adoptNS([[TestInAppBrowserScriptMessageHandler alloc] init]);
     auto userScript = adoptNS([[WKUserScript alloc] initWithSource:userScriptSource injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:YES]);
@@ -95,7 +99,7 @@
     TestWebKitAPI::Util::run(&isDone);
 }
 
-TEST(WebKit, NonAppBoundDomainFailedUserAgentScripts)
+TEST(InAppBrowserPrivacy, NonAppBoundDomainFailedUserAgentScripts)
 {
     WKWebViewConfiguration *configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"WebProcessPlugInWithInternals" configureJSCForTesting:YES];
     [[configuration preferences] _setInAppBrowserPrivacyEnabled:NO];
@@ -132,7 +136,7 @@
     TestWebKitAPI::Util::run(&isDone);
 }
 
-TEST(WebKit, SwapBackToAppBoundRejectsUserScript)
+TEST(InAppBrowserPrivacy, SwapBackToAppBoundRejectsUserScript)
 {
     auto messageHandler = adoptNS([[TestInAppBrowserScriptMessageHandler alloc] init]);
     auto userScript = adoptNS([[WKUserScript alloc] initWithSource:userScriptSource injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:YES]);
@@ -176,3 +180,22 @@
 }
 
 #endif // USE(APPLE_INTERNAL_SDK)
+
+TEST(InAppBrowserPrivacy, AppBoundDomains)
+{
+    isDone = false;
+    [[WKWebsiteDataStore defaultDataStore] _appBoundDomains:^(NSArray<NSString *> *domains) {
+        NSArray *domainsToCompare = [NSArray arrayWithObjects:@"apple.com", @"bar.com", @"example.com", @"foo.com", @"localhost", @"webkit.org", nil];
+
+        NSArray *sortedDomains = [domains sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)];
+
+        int length = [sortedDomains count];
+        EXPECT_EQ(length, 6);
+        for (int i = 0; i < length; i++)
+            EXPECT_WK_STREQ([sortedDomains objectAtIndex:i], [domainsToCompare objectAtIndex:i]);
+
+        isDone = true;
+    }];
+    TestWebKitAPI::Util::run(&isDone);
+}
+
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to