Introduce SPI _WKWebsitePolicies.websiteDataStore
authorachristensen@apple.com <achristensen@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 15 Dec 2017 23:14:33 +0000 (23:14 +0000)
committerachristensen@apple.com <achristensen@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 15 Dec 2017 23:14:33 +0000 (23:14 +0000)
https://bugs.webkit.org/show_bug.cgi?id=180880
<rdar://problem/35535328>

Reviewed by Andy Estes.

Source/WebKit:

The SPI doesn't do anything yet, but it already has some restrictions and tests!
WKWebView._updateWebsitePolicies can't be used to update a WKWebsiteDataStore.  Only during navigation.
Even during navigation, we are only supporting the default and ephemeral data stores right now.
This functionality won't be supported in the C API.  This is enforced with RELEASE_ASSERTs.
If we change our minds, we can change them and add restrictions similar to the ObjC restrictions.

* Shared/WebsitePoliciesData.cpp:
(WebKit::WebsitePoliciesData::encode const):
(WebKit::WebsitePoliciesData::decode):
* Shared/WebsitePoliciesData.h:
* UIProcess/API/APIWebsitePolicies.cpp:
(API::WebsitePolicies::WebsitePolicies):
(API::WebsitePolicies::setWebsiteDataStore):
(API::WebsitePolicies::data):
* UIProcess/API/APIWebsitePolicies.h:
* UIProcess/API/C/WKFramePolicyListener.cpp:
(WKFramePolicyListenerUseWithPolicies):
* UIProcess/API/C/WKPage.cpp:
(WKPageUpdateWebsitePolicies):
* UIProcess/API/Cocoa/WKWebView.mm:
(-[WKWebView _updateWebsitePolicies:]):
* UIProcess/API/Cocoa/_WKWebsitePolicies.h:
* UIProcess/API/Cocoa/_WKWebsitePolicies.mm:
(-[_WKWebsitePolicies websiteDataStore]):
(-[_WKWebsitePolicies setWebsiteDataStore:]):
* UIProcess/Cocoa/NavigationState.mm:
(WebKit::NavigationState::NavigationClient::decidePolicyForNavigationAction):

Tools:

* TestWebKitAPI/Tests/WebKitCocoa/WebsitePolicies.mm:
(-[WebsitePoliciesWebsiteDataStoreDelegate _webView:decidePolicyForNavigationAction:decisionHandler:]):
(-[WebsitePoliciesWebsiteDataStoreDelegate webView:startURLSchemeTask:]):
(-[WebsitePoliciesWebsiteDataStoreDelegate webView:stopURLSchemeTask:]):
(TEST):

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

13 files changed:
Source/WebKit/ChangeLog
Source/WebKit/Shared/WebsitePoliciesData.cpp
Source/WebKit/Shared/WebsitePoliciesData.h
Source/WebKit/UIProcess/API/APIWebsitePolicies.cpp
Source/WebKit/UIProcess/API/APIWebsitePolicies.h
Source/WebKit/UIProcess/API/C/WKFramePolicyListener.cpp
Source/WebKit/UIProcess/API/C/WKPage.cpp
Source/WebKit/UIProcess/API/Cocoa/WKWebView.mm
Source/WebKit/UIProcess/API/Cocoa/_WKWebsitePolicies.h
Source/WebKit/UIProcess/API/Cocoa/_WKWebsitePolicies.mm
Source/WebKit/UIProcess/Cocoa/NavigationState.mm
Tools/ChangeLog
Tools/TestWebKitAPI/Tests/WebKitCocoa/WebsitePolicies.mm

index 4836184..c62148f 100644 (file)
@@ -1,5 +1,41 @@
 2017-12-15  Alex Christensen  <achristensen@webkit.org>
 
+        Introduce SPI _WKWebsitePolicies.websiteDataStore
+        https://bugs.webkit.org/show_bug.cgi?id=180880
+        <rdar://problem/35535328>
+
+        Reviewed by Andy Estes.
+
+        The SPI doesn't do anything yet, but it already has some restrictions and tests!
+        WKWebView._updateWebsitePolicies can't be used to update a WKWebsiteDataStore.  Only during navigation.
+        Even during navigation, we are only supporting the default and ephemeral data stores right now.
+        This functionality won't be supported in the C API.  This is enforced with RELEASE_ASSERTs.
+        If we change our minds, we can change them and add restrictions similar to the ObjC restrictions.
+
+        * Shared/WebsitePoliciesData.cpp:
+        (WebKit::WebsitePoliciesData::encode const):
+        (WebKit::WebsitePoliciesData::decode):
+        * Shared/WebsitePoliciesData.h:
+        * UIProcess/API/APIWebsitePolicies.cpp:
+        (API::WebsitePolicies::WebsitePolicies):
+        (API::WebsitePolicies::setWebsiteDataStore):
+        (API::WebsitePolicies::data):
+        * UIProcess/API/APIWebsitePolicies.h:
+        * UIProcess/API/C/WKFramePolicyListener.cpp:
+        (WKFramePolicyListenerUseWithPolicies):
+        * UIProcess/API/C/WKPage.cpp:
+        (WKPageUpdateWebsitePolicies):
+        * UIProcess/API/Cocoa/WKWebView.mm:
+        (-[WKWebView _updateWebsitePolicies:]):
+        * UIProcess/API/Cocoa/_WKWebsitePolicies.h:
+        * UIProcess/API/Cocoa/_WKWebsitePolicies.mm:
+        (-[_WKWebsitePolicies websiteDataStore]):
+        (-[_WKWebsitePolicies setWebsiteDataStore:]):
+        * UIProcess/Cocoa/NavigationState.mm:
+        (WebKit::NavigationState::NavigationClient::decidePolicyForNavigationAction):
+
+2017-12-15  Alex Christensen  <achristensen@webkit.org>
+
         Fix GTK build.
 
         * UIProcess/API/glib/WebKitPolicyDecision.cpp:
index 6750e69..4b927f5 100644 (file)
@@ -37,6 +37,7 @@ void WebsitePoliciesData::encode(IPC::Encoder& encoder) const
     encoder << autoplayPolicy;
     encoder << allowedAutoplayQuirks;
     encoder << customHeaderFields;
+    encoder << websiteDataStoreParameters;
 }
 
 std::optional<WebsitePoliciesData> WebsitePoliciesData::decode(IPC::Decoder& decoder)
@@ -61,11 +62,17 @@ std::optional<WebsitePoliciesData> WebsitePoliciesData::decode(IPC::Decoder& dec
     if (!customHeaderFields)
         return std::nullopt;
     
+    std::optional<std::optional<WebsiteDataStoreParameters>> websiteDataStoreParameters;
+    decoder >> websiteDataStoreParameters;
+    if (!websiteDataStoreParameters)
+        return std::nullopt;
+    
     return { {
         WTFMove(*contentBlockersEnabled),
         WTFMove(*allowedAutoplayQuirks),
         WTFMove(*autoplayPolicy),
         WTFMove(*customHeaderFields),
+        WTFMove(*websiteDataStoreParameters),
     } };
 }
 
index 2e826a0..8c5ab33 100644 (file)
@@ -27,6 +27,7 @@
 
 #include "WebsiteAutoplayPolicy.h"
 #include "WebsiteAutoplayQuirk.h"
+#include "WebsiteDataStoreParameters.h"
 #include <WebCore/HTTPHeaderField.h>
 #include <wtf/OptionSet.h>
 
@@ -48,6 +49,7 @@ struct WebsitePoliciesData {
     OptionSet<WebsiteAutoplayQuirk> allowedAutoplayQuirks;
     WebsiteAutoplayPolicy autoplayPolicy { WebsiteAutoplayPolicy::Default };
     Vector<WebCore::HTTPHeaderField> customHeaderFields;
+    std::optional<WebsiteDataStoreParameters> websiteDataStoreParameters;
     
     void encode(IPC::Encoder&) const;
     static std::optional<WebsitePoliciesData> decode(IPC::Decoder&);
index a28ba26..f2bff67 100644 (file)
 #include "config.h"
 #include "APIWebsitePolicies.h"
 
+#include "APIWebsiteDataStore.h"
 #include "WebsitePoliciesData.h"
 
 namespace API {
 
+WebsitePolicies::WebsitePolicies() = default;
+
+WebsitePolicies::WebsitePolicies(bool contentBlockersEnabled, OptionSet<WebKit::WebsiteAutoplayQuirk> allowedAutoplayQuirks, WebKit::WebsiteAutoplayPolicy autoplayPolicy, Vector<WebCore::HTTPHeaderField>&& customHeaderFields, RefPtr<WebsiteDataStore>&& websiteDataStore)
+    : m_contentBlockersEnabled(contentBlockersEnabled)
+    , m_allowedAutoplayQuirks(allowedAutoplayQuirks)
+    , m_autoplayPolicy(autoplayPolicy)
+    , m_customHeaderFields(WTFMove(customHeaderFields))
+    , m_websiteDataStore(WTFMove(websiteDataStore))
+{ }
+
 WebsitePolicies::~WebsitePolicies()
 {
 }
 
+void WebsitePolicies::setWebsiteDataStore(RefPtr<WebsiteDataStore>&& websiteDataStore)
+{
+    m_websiteDataStore = WTFMove(websiteDataStore);
+}
+
 WebKit::WebsitePoliciesData WebsitePolicies::data()
 {
-    return { contentBlockersEnabled(), allowedAutoplayQuirks(), autoplayPolicy(), customHeaderFields() };
+    std::optional<WebKit::WebsiteDataStoreParameters> parameters;
+    if (m_websiteDataStore)
+        parameters = m_websiteDataStore->websiteDataStore().parameters();
+    return { contentBlockersEnabled(), allowedAutoplayQuirks(), autoplayPolicy(), customHeaderFields(), WTFMove(parameters) };
 }
 
 }
index d5c605f..7da6c02 100644 (file)
@@ -40,10 +40,12 @@ struct WebsitePoliciesData;
 
 namespace API {
 
+class WebsiteDataStore;
+
 class WebsitePolicies final : public API::ObjectImpl<API::Object::Type::WebsitePolicies> {
 public:
     static Ref<WebsitePolicies> create() { return adoptRef(*new WebsitePolicies); }
-    WebsitePolicies() = default;
+    WebsitePolicies();
     ~WebsitePolicies();
 
     bool contentBlockersEnabled() const { return m_contentBlockersEnabled; }
@@ -58,21 +60,20 @@ public:
     const Vector<WebCore::HTTPHeaderField>& customHeaderFields() const { return m_customHeaderFields; }
     Vector<WebCore::HTTPHeaderField>&& takeCustomHeaderFields() { return WTFMove(m_customHeaderFields); }
     void setCustomHeaderFields(Vector<WebCore::HTTPHeaderField>&& fields) { m_customHeaderFields = WTFMove(fields); }
+    
+    WebsiteDataStore* websiteDataStore() const { return m_websiteDataStore.get(); }
+    void setWebsiteDataStore(RefPtr<WebsiteDataStore>&&);
 
     WebKit::WebsitePoliciesData data();
 
 private:
-    WebsitePolicies(bool contentBlockersEnabled, OptionSet<WebKit::WebsiteAutoplayQuirk> allowedAutoplayQuirks, WebKit::WebsiteAutoplayPolicy autoplayPolicy, Vector<WebCore::HTTPHeaderField>&& customHeaderFields)
-        : m_contentBlockersEnabled(contentBlockersEnabled)
-        , m_allowedAutoplayQuirks(allowedAutoplayQuirks)
-        , m_autoplayPolicy(autoplayPolicy)
-        , m_customHeaderFields(WTFMove(customHeaderFields))
-    { }
+    WebsitePolicies(bool contentBlockersEnabled, OptionSet<WebKit::WebsiteAutoplayQuirk>, WebKit::WebsiteAutoplayPolicy, Vector<WebCore::HTTPHeaderField>&&, RefPtr<WebsiteDataStore>&&);
 
     bool m_contentBlockersEnabled { true };
     OptionSet<WebKit::WebsiteAutoplayQuirk> m_allowedAutoplayQuirks;
     WebKit::WebsiteAutoplayPolicy m_autoplayPolicy { WebKit::WebsiteAutoplayPolicy::Default };
     Vector<WebCore::HTTPHeaderField> m_customHeaderFields;
+    RefPtr<WebsiteDataStore> m_websiteDataStore;
 };
 
 } // namespace API
index cd842d2..b16610a 100644 (file)
@@ -46,7 +46,9 @@ void WKFramePolicyListenerUse(WKFramePolicyListenerRef policyListenerRef)
 
 void WKFramePolicyListenerUseWithPolicies(WKFramePolicyListenerRef policyListenerRef, WKWebsitePoliciesRef websitePolicies)
 {
-    toImpl(policyListenerRef)->use(toImpl(websitePolicies)->data());
+    auto data = toImpl(websitePolicies)->data();
+    RELEASE_ASSERT_WITH_MESSAGE(!data.websiteDataStoreParameters, "Setting WebsitePolicies.WebsiteDataStore is not supported in the C API.");
+    toImpl(policyListenerRef)->use(WTFMove(data));
 }
 
 void WKFramePolicyListenerDownload(WKFramePolicyListenerRef policyListenerRef)
index d5cd531..8dcf57a 100644 (file)
@@ -325,7 +325,9 @@ bool WKPageWillHandleHorizontalScrollEvents(WKPageRef pageRef)
 
 void WKPageUpdateWebsitePolicies(WKPageRef pageRef, WKWebsitePoliciesRef websitePoliciesRef)
 {
-    toImpl(pageRef)->updateWebsitePolicies(toImpl(websitePoliciesRef)->data());
+    auto data = toImpl(websitePoliciesRef)->data();
+    RELEASE_ASSERT_WITH_MESSAGE(!data.websiteDataStoreParameters, "Setting WebsitePolicies.WebsiteDataStore is not supported in the C API.");
+    toImpl(pageRef)->updateWebsitePolicies(WTFMove(data));
 }
 
 WKStringRef WKPageCopyTitle(WKPageRef pageRef)
index 89153c8..4845bef 100644 (file)
@@ -4238,7 +4238,10 @@ static int32_t activeOrientation(WKWebView *webView)
 
 - (void)_updateWebsitePolicies:(_WKWebsitePolicies *)websitePolicies
 {
-    _page->updateWebsitePolicies(websitePolicies->_websitePolicies->data());
+    auto data = websitePolicies->_websitePolicies->data();
+    if (data.websiteDataStoreParameters)
+        [NSException raise:NSInvalidArgumentException format:@"Updating WKWebsiteDataStore is only supported during decidePolicyForNavigationAction."];
+    _page->updateWebsitePolicies(WTFMove(data));
 }
 
 - (BOOL)_allowsRemoteInspection
index fb75b73..70422a7 100644 (file)
@@ -40,6 +40,8 @@ typedef NS_OPTIONS(NSUInteger, _WKWebsiteAutoplayQuirk) {
     _WKWebsiteAutoplayQuirkArbitraryUserGestures = 1 << 2,
 } WK_API_AVAILABLE(macosx(10.13), ios(11.0));
 
+@class WKWebsiteDataStore;
+
 WK_CLASS_AVAILABLE(macosx(10.12.3), ios(10.3))
 @interface _WKWebsitePolicies : NSObject
 
@@ -47,6 +49,7 @@ WK_CLASS_AVAILABLE(macosx(10.12.3), ios(10.3))
 @property (nonatomic) _WKWebsiteAutoplayQuirk allowedAutoplayQuirks WK_API_AVAILABLE(macosx(10.13), ios(11.0));
 @property (nonatomic) _WKWebsiteAutoplayPolicy autoplayPolicy WK_API_AVAILABLE(macosx(10.13), ios(11.0));
 @property (nonatomic, copy) NSDictionary<NSString *, NSString *> *customHeaderFields WK_API_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA));
+@property (nonatomic, strong) WKWebsiteDataStore *websiteDataStore WK_API_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA));
 
 @end
 
index c6d6967..ac960b4 100644 (file)
     _websitePolicies->setCustomHeaderFields(WTFMove(parsedFields));
 }
 
+- (WKWebsiteDataStore *)websiteDataStore
+{
+    auto* store = _websitePolicies->websiteDataStore();
+    return store ? WebKit::wrapper(*store) : nil;
+}
+
+- (void)setWebsiteDataStore:(WKWebsiteDataStore *)websiteDataStore
+{
+    _websitePolicies->setWebsiteDataStore(websiteDataStore->_websiteDataStore.get());
+}
+
 - (NSString *)description
 {
     return [NSString stringWithFormat:@"<%@: %p; contentBlockersEnabled = %d>", NSStringFromClass(self.class), self, self.contentBlockersEnabled];
index e6df598..c1a48d1 100644 (file)
@@ -466,8 +466,14 @@ void NavigationState::NavigationClient::decidePolicyForNavigationAction(WebPageP
         checker->didCallCompletionHandler();
 
         std::optional<WebsitePoliciesData> data;
-        if (websitePolicies)
+        if (websitePolicies) {
             data = websitePolicies->_websitePolicies->data();
+            if (data->websiteDataStoreParameters) {
+                auto& sessionID = data->websiteDataStoreParameters->networkSessionParameters.sessionID;
+                if (!sessionID.isEphemeral() && sessionID != PAL::SessionID::defaultSessionID())
+                    [NSException raise:NSInvalidArgumentException format:@"_WKWebsitePolicies.websiteDataStore must be nil, default, or non-persistent."];
+            }
+        }
 
         switch (actionPolicy) {
         case WKNavigationActionPolicyAllow:
index 8fcce84..2e0cfa5 100644 (file)
@@ -1,3 +1,17 @@
+2017-12-15  Alex Christensen  <achristensen@webkit.org>
+
+        Introduce SPI _WKWebsitePolicies.websiteDataStore
+        https://bugs.webkit.org/show_bug.cgi?id=180880
+        <rdar://problem/35535328>
+
+        Reviewed by Andy Estes.
+
+        * TestWebKitAPI/Tests/WebKitCocoa/WebsitePolicies.mm:
+        (-[WebsitePoliciesWebsiteDataStoreDelegate _webView:decidePolicyForNavigationAction:decisionHandler:]):
+        (-[WebsitePoliciesWebsiteDataStoreDelegate webView:startURLSchemeTask:]):
+        (-[WebsitePoliciesWebsiteDataStoreDelegate webView:stopURLSchemeTask:]):
+        (TEST):
+
 2017-12-15  Nael Ouedraogo  <nael.ouedraogo@crf.canon.fr>
 
         [GTK] Add proxy option to Minibrowser
index b040893..7472e65 100644 (file)
@@ -34,7 +34,9 @@
 #import <WebKit/WKURLSchemeTaskPrivate.h>
 #import <WebKit/WKUserContentControllerPrivate.h>
 #import <WebKit/WKWebViewPrivate.h>
+#import <WebKit/WKWebsiteDataStorePrivate.h>
 #import <WebKit/_WKUserContentExtensionStorePrivate.h>
+#import <WebKit/_WKWebsiteDataStoreConfiguration.h>
 #import <WebKit/_WKWebsitePolicies.h>
 #import <wtf/MainThread.h>
 #import <wtf/RetainPtr.h>
@@ -785,5 +787,63 @@ TEST(WebKit, CustomHeaderFields)
     TestWebKitAPI::Util::run(&fourthTestDone);
 }
 
+static bool done;
+
+@interface WebsitePoliciesWebsiteDataStoreDelegate : NSObject <WKNavigationDelegatePrivate, WKURLSchemeHandler>
+@end
+
+@implementation WebsitePoliciesWebsiteDataStoreDelegate
+
+- (void)_webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy, _WKWebsitePolicies *))decisionHandler
+{
+    if ([navigationAction.request.URL.path isEqualToString:@"/invalid"]) {
+        _WKWebsitePolicies *websitePolicies = [[[_WKWebsitePolicies alloc] init] autorelease];
+        websitePolicies.websiteDataStore = [[[WKWebsiteDataStore alloc] _initWithConfiguration:[[[_WKWebsiteDataStoreConfiguration alloc] init] autorelease]] autorelease];
+
+        bool sawException = false;
+        @try {
+            decisionHandler(WKNavigationActionPolicyAllow, websitePolicies);
+        } @catch (NSException *exception) {
+            sawException = true;
+        }
+        EXPECT_TRUE(sawException);
+
+        done = true;
+    }
+}
+
+- (void)webView:(WKWebView *)webView startURLSchemeTask:(id <WKURLSchemeTask>)urlSchemeTask
+{
+}
+
+- (void)webView:(WKWebView *)webView stopURLSchemeTask:(id <WKURLSchemeTask>)urlSchemeTask
+{
+}
+
+@end
+
+TEST(WebKit, UpdateWebsitePoliciesInvalid)
+{
+    auto delegate = adoptNS([[WebsitePoliciesWebsiteDataStoreDelegate alloc] init]);
+    auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
+    [configuration setURLSchemeHandler:delegate.get() forURLScheme:@"test"];
+    auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
+    [webView setNavigationDelegate:delegate.get()];
+
+    auto policies = adoptNS([[_WKWebsitePolicies alloc] init]);
+    [policies setWebsiteDataStore:[WKWebsiteDataStore nonPersistentDataStore]];
+    bool sawException = false;
+    @try {
+        [webView _updateWebsitePolicies:policies.get()];
+    } @catch (NSException *exception) {
+        sawException = true;
+    }
+    EXPECT_TRUE(sawException);
+    
+    [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"test:///invalid"]]];
+    TestWebKitAPI::Util::run(&done);
+}
+
+// FIXME: Use _WKWebsitePolicies.websiteDataStore and test that it is used.
 
 #endif // WK_API_ENABLED