Device Orientation access permission should be denied unless explicitly granted by...
authorcdumez@apple.com <cdumez@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 12 Mar 2019 20:32:37 +0000 (20:32 +0000)
committercdumez@apple.com <cdumez@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 12 Mar 2019 20:32:37 +0000 (20:32 +0000)
https://bugs.webkit.org/show_bug.cgi?id=195625

Reviewed by Youenn Fablet.

Source/WebKit:

Device Orientation access permission should be denied unless explicitly granted by the client.
Previously, it was granted by default.

* UIProcess/API/APIUIClient.h:
(API::UIClient::shouldAllowDeviceOrientationAndMotionAccess):
* UIProcess/API/C/WKPage.cpp:
(WKPageSetPageUIClient):
* UIProcess/Cocoa/UIDelegate.mm:
(WebKit::UIDelegate::UIClient::shouldAllowDeviceOrientationAndMotionAccess):

Tools:

add API test coverage.

* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
* TestWebKitAPI/Tests/WebKitCocoa/DeviceOrientation.mm: Added.
(-[DeviceOrientationMessageHandler userContentController:didReceiveScriptMessage:]):
(-[DeviceOrientationPermissionUIDelegate initWithHandler:]):
(-[DeviceOrientationPermissionUIDelegate _webView:shouldAllowDeviceOrientationAndMotionAccessRequestedByFrame:decisionHandler:]):
(runDeviceOrientationTest):
(TEST):
* TestWebKitAPI/Tests/WebKitCocoa/WebsitePolicies.mm:
(-[WebsitePoliciesDeviceOrientationUIDelegate _webView:shouldAllowDeviceOrientationAndMotionAccessRequestedByFrame:decisionHandler:]):

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

Source/WebKit/ChangeLog
Source/WebKit/UIProcess/API/APIUIClient.h
Source/WebKit/UIProcess/API/C/WKPage.cpp
Source/WebKit/UIProcess/Cocoa/UIDelegate.mm
Tools/ChangeLog
Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj
Tools/TestWebKitAPI/Tests/WebKitCocoa/DeviceOrientation.mm [new file with mode: 0644]
Tools/TestWebKitAPI/Tests/WebKitCocoa/WebsitePolicies.mm

index 0fc1467..727dfed 100644 (file)
@@ -1,3 +1,20 @@
+2019-03-12  Chris Dumez  <cdumez@apple.com>
+
+        Device Orientation access permission should be denied unless explicitly granted by the client
+        https://bugs.webkit.org/show_bug.cgi?id=195625
+
+        Reviewed by Youenn Fablet.
+
+        Device Orientation access permission should be denied unless explicitly granted by the client.
+        Previously, it was granted by default.
+
+        * UIProcess/API/APIUIClient.h:
+        (API::UIClient::shouldAllowDeviceOrientationAndMotionAccess):
+        * UIProcess/API/C/WKPage.cpp:
+        (WKPageSetPageUIClient):
+        * UIProcess/Cocoa/UIDelegate.mm:
+        (WebKit::UIDelegate::UIClient::shouldAllowDeviceOrientationAndMotionAccess):
+
 2019-03-12  Antti Koivisto  <antti@apple.com>
 
         [iOS] Enable asynchronous frame scrolling by default
index c390c38..c2121ef 100644 (file)
@@ -174,7 +174,7 @@ public:
 #endif
 
 #if ENABLE(DEVICE_ORIENTATION)
-    virtual void shouldAllowDeviceOrientationAndMotionAccess(WebKit::WebPageProxy&, WebKit::WebFrameProxy& webFrameProxy, const WebCore::SecurityOriginData&, CompletionHandler<void(bool)>&& completionHandler) { completionHandler(true); }
+    virtual void shouldAllowDeviceOrientationAndMotionAccess(WebKit::WebPageProxy&, WebKit::WebFrameProxy& webFrameProxy, const WebCore::SecurityOriginData&, CompletionHandler<void(bool)>&& completionHandler) { completionHandler(false); }
 #endif
 
     virtual void didClickAutoFillButton(WebKit::WebPageProxy&, Object*) { }
index a8a1685..d9cb3c6 100644 (file)
@@ -1903,7 +1903,7 @@ void WKPageSetPageUIClient(WKPageRef pageRef, const WKPageUIClientBase* wkClient
         void shouldAllowDeviceOrientationAndMotionAccess(WebPageProxy& page, WebFrameProxy&, const WebCore::SecurityOriginData& originData, CompletionHandler<void(bool)>&& completionHandler) final
         {
             if (!m_client.shouldAllowDeviceOrientationAndMotionAccess)
-                return completionHandler(true);
+                return completionHandler(false);
 
             auto origin = API::SecurityOrigin::create(originData.securityOrigin());
             completionHandler(m_client.shouldAllowDeviceOrientationAndMotionAccess(toAPI(&page), toAPI(origin.ptr()), m_client.base.clientInfo));
index 3ec3e3c..96b88bf 100644 (file)
@@ -847,11 +847,11 @@ bool UIDelegate::UIClient::runOpenPanel(WebPageProxy*, WebFrameProxy* webFramePr
 void UIDelegate::UIClient::shouldAllowDeviceOrientationAndMotionAccess(WebKit::WebPageProxy&, WebFrameProxy& webFrameProxy, const WebCore::SecurityOriginData& securityOriginData, CompletionHandler<void(bool)>&& completionHandler)
 {
     if (!m_uiDelegate.m_delegateMethods.webViewShouldAllowDeviceOrientationAndMotionAccessRequestedByFrameDecisionHandler)
-        return completionHandler(true);
+        return completionHandler(false);
 
     auto delegate = m_uiDelegate.m_delegate.get();
     if (!delegate)
-        return completionHandler(true);
+        return completionHandler(false);
 
     auto checker = CompletionHandlerCallChecker::create(delegate.get(), @selector(_webView:shouldAllowDeviceOrientationAndMotionAccessRequestedByFrame:decisionHandler:));
     [(id <WKUIDelegatePrivate>)delegate _webView:m_uiDelegate.m_webView shouldAllowDeviceOrientationAndMotionAccessRequestedByFrame:wrapper(API::FrameInfo::create(webFrameProxy, securityOriginData.securityOrigin())) decisionHandler:makeBlockPtr([completionHandler = WTFMove(completionHandler), checker = WTFMove(checker)] (BOOL granted) mutable {
index 12c2896..c4cda3b 100644 (file)
@@ -1,3 +1,22 @@
+2019-03-12  Chris Dumez  <cdumez@apple.com>
+
+        Device Orientation access permission should be denied unless explicitly granted by the client
+        https://bugs.webkit.org/show_bug.cgi?id=195625
+
+        Reviewed by Youenn Fablet.
+
+        add API test coverage.
+
+        * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
+        * TestWebKitAPI/Tests/WebKitCocoa/DeviceOrientation.mm: Added.
+        (-[DeviceOrientationMessageHandler userContentController:didReceiveScriptMessage:]):
+        (-[DeviceOrientationPermissionUIDelegate initWithHandler:]):
+        (-[DeviceOrientationPermissionUIDelegate _webView:shouldAllowDeviceOrientationAndMotionAccessRequestedByFrame:decisionHandler:]):
+        (runDeviceOrientationTest):
+        (TEST):
+        * TestWebKitAPI/Tests/WebKitCocoa/WebsitePolicies.mm:
+        (-[WebsitePoliciesDeviceOrientationUIDelegate _webView:shouldAllowDeviceOrientationAndMotionAccessRequestedByFrame:decisionHandler:]):
+
 2019-03-12  Jer Noble  <jer.noble@apple.com>
 
         Flaky API Test TestWebKitAPI.WebKitLegacy.ScrollingDoesNotPauseMedia
index f3a990d..765c99c 100644 (file)
                466C3843210637DE006A88DE /* notify-resourceLoadObserver.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 466C3842210637CE006A88DE /* notify-resourceLoadObserver.html */; };
                467C565321B5ED130057516D /* GetSessionCookie.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 467C565121B5ECDF0057516D /* GetSessionCookie.html */; };
                467C565421B5ED130057516D /* SetSessionCookie.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 467C565221B5ECDF0057516D /* SetSessionCookie.html */; };
+               46918EFC2237283C00468DFE /* DeviceOrientation.mm in Sources */ = {isa = PBXBuildFile; fileRef = 46918EFB2237283500468DFE /* DeviceOrientation.mm */; };
                46A911592108E6780078D40D /* CustomUserAgent.mm in Sources */ = {isa = PBXBuildFile; fileRef = 46A911582108E66B0078D40D /* CustomUserAgent.mm */; };
                46AE5A3720F9066D00E0873E /* SimpleServiceWorkerRegistrations-4.sqlite3 in Copy Resources */ = {isa = PBXBuildFile; fileRef = 4656A75720F9054F0002E21F /* SimpleServiceWorkerRegistrations-4.sqlite3 */; };
                46C519DA1D355AB200DAA51A /* LocalStorageNullEntries.mm in Sources */ = {isa = PBXBuildFile; fileRef = 46C519D81D355A7300DAA51A /* LocalStorageNullEntries.mm */; };
                466C3842210637CE006A88DE /* notify-resourceLoadObserver.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "notify-resourceLoadObserver.html"; sourceTree = "<group>"; };
                467C565121B5ECDF0057516D /* GetSessionCookie.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = GetSessionCookie.html; sourceTree = "<group>"; };
                467C565221B5ECDF0057516D /* SetSessionCookie.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = SetSessionCookie.html; sourceTree = "<group>"; };
+               46918EFB2237283500468DFE /* DeviceOrientation.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = DeviceOrientation.mm; sourceTree = "<group>"; };
                46A911582108E66B0078D40D /* CustomUserAgent.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = CustomUserAgent.mm; sourceTree = "<group>"; };
                46C519D81D355A7300DAA51A /* LocalStorageNullEntries.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = LocalStorageNullEntries.mm; sourceTree = "<group>"; };
                46C519E21D35629600DAA51A /* LocalStorageNullEntries.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = LocalStorageNullEntries.html; sourceTree = "<group>"; };
                                46A911582108E66B0078D40D /* CustomUserAgent.mm */,
                                2DC4CF761D2D9DD800ECCC94 /* DataDetection.mm */,
                                518EE51C20A78D3300E024F3 /* DecidePolicyForNavigationAction.mm */,
+                               46918EFB2237283500468DFE /* DeviceOrientation.mm */,
                                CEA7F57B20895F5B0078EF6E /* DidResignInputElementStrongPasswordAppearance.mm */,
                                518EE51A20A78CFB00E024F3 /* DoAfterNextPresentationUpdateAfterCrash.mm */,
                                518EE51620A78CDF00E024F3 /* DoubleDefersLoading.mm */,
                                2DC4CF771D2D9DD800ECCC94 /* DataDetection.mm in Sources */,
                                518EE51D20A78D3600E024F3 /* DecidePolicyForNavigationAction.mm in Sources */,
                                2D1646E21D1862CD00015A1A /* DeferredViewInWindowStateChange.mm in Sources */,
+                               46918EFC2237283C00468DFE /* DeviceOrientation.mm in Sources */,
                                7CCE7EB91A411A7E00447C4C /* DeviceScaleFactorInDashboardRegions.mm in Sources */,
                                7CCE7EBA1A411A7E00447C4C /* DeviceScaleFactorOnBack.mm in Sources */,
                                7C83E04D1D0A641800FEBCF3 /* DFACombiner.cpp in Sources */,
diff --git a/Tools/TestWebKitAPI/Tests/WebKitCocoa/DeviceOrientation.mm b/Tools/TestWebKitAPI/Tests/WebKitCocoa/DeviceOrientation.mm
new file mode 100644 (file)
index 0000000..1bbe74c
--- /dev/null
@@ -0,0 +1,159 @@
+/*
+ * 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"
+
+#if PLATFORM(IOS_FAMILY)
+
+#import "PlatformUtilities.h"
+#import "TestNavigationDelegate.h"
+#import "TestWKWebView.h"
+#import <WebKit/WKUIDelegatePrivate.h>
+#import <wtf/Function.h>
+#import <wtf/HashMap.h>
+#import <wtf/RetainPtr.h>
+#import <wtf/text/StringHash.h>
+#import <wtf/text/WTFString.h>
+
+static RetainPtr<NSMutableArray> receivedMessages = adoptNS([@[] mutableCopy]);
+static bool didReceiveMessage;
+
+@interface DeviceOrientationMessageHandler : NSObject <WKScriptMessageHandler>
+@end
+
+@implementation DeviceOrientationMessageHandler
+- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message
+{
+    if ([message body])
+        [receivedMessages addObject:[message body]];
+    else
+        [receivedMessages addObject:@""];
+
+    didReceiveMessage = true;
+}
+@end
+
+@interface DeviceOrientationPermissionUIDelegate : NSObject <WKUIDelegatePrivate> {
+}
+- (instancetype)initWithHandler:(Function<bool()>&&)decisionHandler;
+@end
+
+@implementation DeviceOrientationPermissionUIDelegate {
+Function<bool()> _decisionHandler;
+}
+
+- (instancetype)initWithHandler:(Function<bool()>&&)decisionHandler
+{
+    self = [super init];
+    _decisionHandler = WTFMove(decisionHandler);
+    return self;
+}
+
+- (void)_webView:(WKWebView *)webView shouldAllowDeviceOrientationAndMotionAccessRequestedByFrame:(WKFrameInfo *)requestingFrame decisionHandler:(void (^)(BOOL))decisionHandler
+{
+    decisionHandler(_decisionHandler());
+}
+
+@end
+
+enum class DeviceOrientationPermission { Granted, Denied, Default };
+static void runDeviceOrientationTest(DeviceOrientationPermission deviceOrientationPermission)
+{
+    auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
+
+    auto messageHandler = adoptNS([[DeviceOrientationMessageHandler alloc] init]);
+    [[configuration userContentController] addScriptMessageHandler:messageHandler.get() name:@"testHandler"];
+
+    auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
+
+    RetainPtr<DeviceOrientationPermissionUIDelegate> uiDelegate;
+    switch (deviceOrientationPermission) {
+    case DeviceOrientationPermission::Granted:
+        uiDelegate = adoptNS([[DeviceOrientationPermissionUIDelegate alloc] initWithHandler:[] { return true; }]);
+        break;
+    case DeviceOrientationPermission::Denied:
+        uiDelegate = adoptNS([[DeviceOrientationPermissionUIDelegate alloc] initWithHandler:[] { return false; }]);
+        break;
+    case DeviceOrientationPermission::Default:
+        break;
+    }
+    [webView setUIDelegate:uiDelegate.get()];
+
+    NSURLRequest *request = [NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]];
+    [webView loadRequest:request];
+
+    [webView _test_waitForDidFinishNavigation];
+
+    [webView evaluateJavaScript:@"DeviceOrientationEvent.requestPermission().then((granted) => { webkit.messageHandlers.testHandler.postMessage(granted) });" completionHandler: [&] (id result, NSError *error) { }];
+
+    TestWebKitAPI::Util::run(&didReceiveMessage);
+    didReceiveMessage = false;
+
+    switch (deviceOrientationPermission) {
+    case DeviceOrientationPermission::Granted:
+        EXPECT_WK_STREQ(@"granted", receivedMessages.get()[0]);
+        break;
+    case DeviceOrientationPermission::Denied:
+    case DeviceOrientationPermission::Default:
+        EXPECT_WK_STREQ(@"denied", receivedMessages.get()[0]);
+        break;
+    }
+
+    bool addedEventListener = false;
+    [webView evaluateJavaScript:@"addEventListener('deviceorientation', (e) => { webkit.messageHandlers.testHandler.postMessage('received-event') });" completionHandler: [&] (id result, NSError *error) {
+        addedEventListener = true;
+    }];
+
+    TestWebKitAPI::Util::run(&addedEventListener);
+    addedEventListener = false;
+
+    [webView _simulateDeviceOrientationChangeWithAlpha:1.0 beta:2.0 gamma:3.0];
+
+    if (deviceOrientationPermission == DeviceOrientationPermission::Granted) {
+        TestWebKitAPI::Util::run(&didReceiveMessage);
+        EXPECT_WK_STREQ(@"received-event", receivedMessages.get()[1]);
+    } else {
+        TestWebKitAPI::Util::sleep(0.1);
+        EXPECT_FALSE(didReceiveMessage);
+    }
+    didReceiveMessage = false;
+}
+
+TEST(DeviceOrientation, PermissionDeniedByDefault)
+{
+    runDeviceOrientationTest(DeviceOrientationPermission::Default);
+}
+
+TEST(DeviceOrientation, PermissionGranted)
+{
+    runDeviceOrientationTest(DeviceOrientationPermission::Granted);
+}
+
+TEST(DeviceOrientation, PermissionDenied)
+{
+    runDeviceOrientationTest(DeviceOrientationPermission::Denied);
+}
+
+#endif // PLATFORM(IOS_FAMILY)
index 52d42b7..f14293b 100644 (file)
@@ -1275,6 +1275,19 @@ addEventListener("deviceorientation", (event) => {
 
 @end
 
+@interface WebsitePoliciesDeviceOrientationUIDelegate : NSObject <WKUIDelegatePrivate> {
+}
+@end
+
+@implementation WebsitePoliciesDeviceOrientationUIDelegate
+
+- (void)_webView:(WKWebView *)webView shouldAllowDeviceOrientationAndMotionAccessRequestedByFrame:(WKFrameInfo *)requestingFrame decisionHandler:(void (^)(BOOL))decisionHandler
+{
+    decisionHandler(YES);
+}
+
+@end
+
 static void runWebsitePoliciesDeviceOrientationEventTest(bool websitePolicyValue)
 {
     auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
@@ -1287,6 +1300,8 @@ static void runWebsitePoliciesDeviceOrientationEventTest(bool websitePolicyValue
 
     auto delegate = adoptNS([[WebsitePoliciesDeviceOrientationDelegate alloc] initWithDeviceOrientationEventEnabled:websitePolicyValue]);
     [webView setNavigationDelegate:delegate.get()];
+    auto uiDelegate = adoptNS([[WebsitePoliciesDeviceOrientationUIDelegate alloc] init]);
+    [webView setUIDelegate:uiDelegate.get()];
 
     NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"test://localhost/main.html"]];
     [webView loadRequest:request];