Implement safe browsing in WebKit on WatchOS
authorachristensen@apple.com <achristensen@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 13 Dec 2018 00:41:21 +0000 (00:41 +0000)
committerachristensen@apple.com <achristensen@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 13 Dec 2018 00:41:21 +0000 (00:41 +0000)
https://bugs.webkit.org/show_bug.cgi?id=192641
<rdar://problem/46376188>

Reviewed by Geoff Garen.

Source/WebKit:

WatchOS has a few special requirements:
1. The margin size needs to be smaller and the title font smaller to fit on the screen.
2. The exclamation point cannot be beside the title or it won't fit on the screen.  I put it above the title.
3. The application must be told when the safe browsing warning has been shown.  I added a new delegate callback.
4. The UIScrollView's contentSize must be set even before the details are shown to be able to scroll down to the buttons.
   This was already an issue on small WKWebViews on iOS, so this fixes both operating systems.

* Configurations/WebKit.xcconfig:
* UIProcess/API/APIUIClient.h:
(API::UIClient::didShowSafeBrowsingWarning):
* UIProcess/API/Cocoa/WKUIDelegatePrivate.h:
* UIProcess/Cocoa/UIDelegate.h:
* UIProcess/Cocoa/UIDelegate.mm:
(WebKit::UIDelegate::setDelegate):
(WebKit::UIDelegate::UIClient::didShowSafeBrowsingWarning):
* UIProcess/Cocoa/WKSafeBrowsingWarning.mm:
(fontOfSize):
(buttonSize):
(-[WKSafeBrowsingWarning addContent]):
(-[WKSafeBrowsingWarning showDetailsClicked]):
(-[WKSafeBrowsingWarning updateContentSize]):
(buttonWidth): Deleted.
* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::decidePolicyForNavigationAction):

Source/WTF:

* wtf/Platform.h:
WatchOS has safe browsing, too!

Tools:

* TestWebKitAPI/Tests/WebKitCocoa/SafeBrowsing.mm:
(-[SafeBrowsingNavigationDelegate _webViewDidShowSafeBrowsingWarning:]):
(safeBrowsingView):
Add a test that the new delegate callback is called.

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

12 files changed:
Source/WTF/ChangeLog
Source/WTF/wtf/Platform.h
Source/WebKit/ChangeLog
Source/WebKit/Configurations/WebKit.xcconfig
Source/WebKit/UIProcess/API/APIUIClient.h
Source/WebKit/UIProcess/API/Cocoa/WKUIDelegatePrivate.h
Source/WebKit/UIProcess/Cocoa/UIDelegate.h
Source/WebKit/UIProcess/Cocoa/UIDelegate.mm
Source/WebKit/UIProcess/Cocoa/WKSafeBrowsingWarning.mm
Source/WebKit/UIProcess/WebPageProxy.cpp
Tools/ChangeLog
Tools/TestWebKitAPI/Tests/WebKitCocoa/SafeBrowsing.mm

index cd73df0..10a64b6 100644 (file)
@@ -1,3 +1,14 @@
+2018-12-12  Alex Christensen  <achristensen@webkit.org>
+
+        Implement safe browsing in WebKit on WatchOS
+        https://bugs.webkit.org/show_bug.cgi?id=192641
+        <rdar://problem/46376188>
+
+        Reviewed by Geoff Garen.
+
+        * wtf/Platform.h:
+        WatchOS has safe browsing, too!
+
 2018-12-11  Fujii Hironori  <Hironori.Fujii@sony.com>
 
         [Win][Clang] Fix compilation warnings of WTF
index 5148821..2753d1a 100644 (file)
 #define HAVE_SAFARI_SERVICES_FRAMEWORK 1
 #endif
 
-#if ((PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101300) || PLATFORM(IOS)) && !defined(__i386__)
+#if (PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101300 && !defined(__i386__)) || PLATFORM(IOS) || PLATFORM(WATCHOS)
 #define HAVE_SAFE_BROWSING 1
 #endif
 
index 05cf3a9..1f0c590 100644 (file)
@@ -1,3 +1,36 @@
+2018-12-12  Alex Christensen  <achristensen@webkit.org>
+
+        Implement safe browsing in WebKit on WatchOS
+        https://bugs.webkit.org/show_bug.cgi?id=192641
+        <rdar://problem/46376188>
+
+        Reviewed by Geoff Garen.
+
+        WatchOS has a few special requirements:
+        1. The margin size needs to be smaller and the title font smaller to fit on the screen.
+        2. The exclamation point cannot be beside the title or it won't fit on the screen.  I put it above the title.
+        3. The application must be told when the safe browsing warning has been shown.  I added a new delegate callback.
+        4. The UIScrollView's contentSize must be set even before the details are shown to be able to scroll down to the buttons.
+           This was already an issue on small WKWebViews on iOS, so this fixes both operating systems.
+
+        * Configurations/WebKit.xcconfig:
+        * UIProcess/API/APIUIClient.h:
+        (API::UIClient::didShowSafeBrowsingWarning):
+        * UIProcess/API/Cocoa/WKUIDelegatePrivate.h:
+        * UIProcess/Cocoa/UIDelegate.h:
+        * UIProcess/Cocoa/UIDelegate.mm:
+        (WebKit::UIDelegate::setDelegate):
+        (WebKit::UIDelegate::UIClient::didShowSafeBrowsingWarning):
+        * UIProcess/Cocoa/WKSafeBrowsingWarning.mm:
+        (fontOfSize):
+        (buttonSize):
+        (-[WKSafeBrowsingWarning addContent]):
+        (-[WKSafeBrowsingWarning showDetailsClicked]):
+        (-[WKSafeBrowsingWarning updateContentSize]):
+        (buttonWidth): Deleted.
+        * UIProcess/WebPageProxy.cpp:
+        (WebKit::WebPageProxy::decidePolicyForNavigationAction):
+
 2018-12-12  Commit Queue  <commit-queue@webkit.org>
 
         Unreviewed, rolling out r239129 and r239131.
index c7f1a6a..f2318ec 100644 (file)
@@ -111,6 +111,8 @@ WK_PROXIMITY_NETWORKING_LDFLAGS_watchos = -framework IDS -framework MobileWiFi -
 WK_SAFE_BROWSING_LDFLAGS = $(WK_SAFE_BROWSING_LDFLAGS_$(WK_PLATFORM_NAME));
 WK_SAFE_BROWSING_LDFLAGS_iphoneos = -framework SafariSafeBrowsing;
 WK_SAFE_BROWSING_LDFLAGS_iphonesimulator = -framework SafariSafeBrowsing;
+WK_SAFE_BROWSING_LDFLAGS_watchos = -framework SafariSafeBrowsing;
+WK_SAFE_BROWSING_LDFLAGS_watchsimulator = -framework SafariSafeBrowsing;
 WK_SAFE_BROWSING_LDFLAGS_iphoneos[sdk=iphone*10.*] = ;
 WK_SAFE_BROWSING_LDFLAGS_iphonesimulator[sdk=iphone*10.*] = ;
 WK_SAFE_BROWSING_LDFLAGS_macosx = $(WK_SAFE_BROWSING_LDFLAGS$(WK_MACOS_1013));
index 1d35272..43ff763 100644 (file)
@@ -180,6 +180,8 @@ public:
     virtual void imageOrMediaDocumentSizeChanged(const WebCore::IntSize&) { }
 
     virtual void didExceedBackgroundResourceLimitWhileInForeground(WebKit::WebPageProxy&, WKResourceLimit) { }
+    
+    virtual void didShowSafeBrowsingWarning() { }
 };
 
 } // namespace API
index 7f61a82..46c9517 100644 (file)
@@ -99,6 +99,7 @@ struct UIEdgeInsets;
 - (void)_webViewDidExitFullscreen:(WKWebView *)webView WK_API_AVAILABLE(macosx(10.11), ios(8.3));
 - (void)_webViewRequestPointerLock:(WKWebView *)webView WK_API_AVAILABLE(macosx(10.12.3));
 - (void)_webViewDidRequestPointerLock:(WKWebView *)webView completionHandler:(void (^)(BOOL))completionHandler WK_API_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA));
+- (void)_webViewDidShowSafeBrowsingWarning:(WKWebView *)webView WK_API_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA));
 - (void)_webViewDidLosePointerLock:(WKWebView *)webView WK_API_AVAILABLE(macosx(10.12.3));
 - (void)_webView:(WKWebView *)webView hasVideoInPictureInPictureDidChange:(BOOL)hasVideoInPictureInPicture WK_API_AVAILABLE(macosx(10.13), ios(11.0));
 
index c0da3ff..38dd7ec 100644 (file)
@@ -146,6 +146,7 @@ private:
         void hasVideoInPictureInPictureDidChange(WebPageProxy*, bool) final;
 
         void imageOrMediaDocumentSizeChanged(const WebCore::IntSize&) final;
+        void didShowSafeBrowsingWarning() final;
 
         UIDelegate& m_uiDelegate;
     };
@@ -222,6 +223,7 @@ private:
         bool webViewGetContextMenuFromProposedMenuForElementUserInfoCompletionHandler : 1;
 #endif
         bool webViewHasVideoInPictureInPictureDidChange : 1;
+        bool webViewDidShowSafeBrowsingWarning : 1;
     } m_delegateMethods;
 };
 
index a7a83b4..ce84a88 100644 (file)
@@ -169,6 +169,7 @@ void UIDelegate::setDelegate(id <WKUIDelegate> delegate)
 #endif
     
     m_delegateMethods.webViewHasVideoInPictureInPictureDidChange = [delegate respondsToSelector:@selector(_webView:hasVideoInPictureInPictureDidChange:)];
+    m_delegateMethods.webViewDidShowSafeBrowsingWarning = [delegate respondsToSelector:@selector(_webViewDidShowSafeBrowsingWarning:)];
 }
 
 #if ENABLE(CONTEXT_MENUS)
@@ -1217,6 +1218,18 @@ void UIDelegate::UIClient::didLosePointerLock(WebPageProxy*)
 
 #endif
     
+void UIDelegate::UIClient::didShowSafeBrowsingWarning()
+{
+    if (!m_uiDelegate.m_delegateMethods.webViewDidShowSafeBrowsingWarning)
+        return;
+
+    auto delegate = m_uiDelegate.m_delegate.get();
+    if (!delegate)
+        return;
+
+    [static_cast<id <WKUIDelegatePrivate>>(delegate) _webViewDidShowSafeBrowsingWarning:m_uiDelegate.m_webView];
+}
+
 void UIDelegate::UIClient::hasVideoInPictureInPictureDidChange(WebPageProxy*, bool hasVideoInPictureInPicture)
 {
     if (!m_uiDelegate.m_delegateMethods.webViewHasVideoInPictureInPictureDidChange)
index 8c2285e..78b6b17 100644 (file)
 constexpr CGFloat exclamationPointSize = 30;
 constexpr CGFloat boxCornerRadius = 6;
 #if HAVE(SAFE_BROWSING)
+#if PLATFORM(WATCHOS)
+constexpr CGFloat marginSize = 10;
+#else
 constexpr CGFloat marginSize = 20;
+#endif
 constexpr CGFloat maxWidth = 675;
 #endif
 
@@ -85,7 +89,11 @@ static FontType *fontOfSize(WarningTextSize size)
 #elif HAVE(SAFE_BROWSING)
     switch (size) {
     case WarningTextSize::Title:
+#if PLATFORM(WATCHOS)
+        return [UIFont preferredFontForTextStyle:UIFontTextStyleHeadline];
+#else
         return [UIFont preferredFontForTextStyle:UIFontTextStyleLargeTitle];
+#endif
     case WarningTextSize::Body:
         return [UIFont preferredFontForTextStyle:UIFontTextStyleBody];
     }
@@ -220,12 +228,12 @@ static ButtonType *makeButton(WarningItem item, WKSafeBrowsingWarning *warning,
 }
 
 #if HAVE(SAFE_BROWSING)
-static CGFloat buttonWidth(ButtonType *button)
+static CGSize buttonSize(ButtonType *button)
 {
 #if PLATFORM(MAC)
-    return button.frame.size.width;
+    return button.frame.size;
 #else
-    return button.titleLabel.intrinsicContentSize.width;
+    return button.titleLabel.intrinsicContentSize;
 #endif
 }
 #endif
@@ -301,35 +309,48 @@ static void setBackground(ViewType *view, ColorType *color)
     box.translatesAutoresizingMaskIntoConstraints = NO;
     [self addSubview:box];
 
-#if HAVE(SAFE_BROWSING)
+#if PLATFORM(WATCHOS)
+    [NSLayoutConstraint activateConstraints:@[
+        [[box.leadingAnchor anchorWithOffsetToAnchor:exclamationPoint.leadingAnchor] constraintEqualToAnchor:[exclamationPoint.trailingAnchor anchorWithOffsetToAnchor:box.trailingAnchor]],
+        [[box.leadingAnchor anchorWithOffsetToAnchor:title.leadingAnchor] constraintEqualToConstant:marginSize],
+        [[title.bottomAnchor anchorWithOffsetToAnchor:warning.topAnchor] constraintEqualToConstant:marginSize],
+        [[exclamationPoint.bottomAnchor anchorWithOffsetToAnchor:title.topAnchor] constraintEqualToConstant:marginSize],
+        [[box.topAnchor anchorWithOffsetToAnchor:exclamationPoint.topAnchor] constraintEqualToConstant:marginSize + self.frame.size.height / 2],
+        [[self.topAnchor anchorWithOffsetToAnchor:box.topAnchor] constraintEqualToAnchor:[box.bottomAnchor anchorWithOffsetToAnchor:self.bottomAnchor] multiplier:0.2],
+    ]];
+#elif HAVE(SAFE_BROWSING)
     [NSLayoutConstraint activateConstraints:@[
+        [[box.leadingAnchor anchorWithOffsetToAnchor:exclamationPoint.leadingAnchor] constraintEqualToConstant:marginSize],
+        [[box.leadingAnchor anchorWithOffsetToAnchor:title.leadingAnchor] constraintEqualToConstant:marginSize * 1.5 + exclamationPointSize],
+        [[title.topAnchor anchorWithOffsetToAnchor:exclamationPoint.topAnchor] constraintEqualToAnchor:[exclamationPoint.bottomAnchor anchorWithOffsetToAnchor:title.bottomAnchor]],
+        [[title.bottomAnchor anchorWithOffsetToAnchor:warning.topAnchor] constraintEqualToConstant:marginSize],
+        [[box.topAnchor anchorWithOffsetToAnchor:title.topAnchor] constraintEqualToConstant:marginSize],
         [[self.topAnchor anchorWithOffsetToAnchor:box.topAnchor] constraintEqualToAnchor:[box.bottomAnchor anchorWithOffsetToAnchor:self.bottomAnchor] multiplier:0.5],
+    ]];
+#endif
+
+#if HAVE(SAFE_BROWSING)
+    [NSLayoutConstraint activateConstraints:@[
         [[self.leftAnchor anchorWithOffsetToAnchor:box.leftAnchor] constraintEqualToAnchor:[box.rightAnchor anchorWithOffsetToAnchor:self.rightAnchor]],
 
         [box.widthAnchor constraintLessThanOrEqualToConstant:maxWidth],
         [box.widthAnchor constraintLessThanOrEqualToAnchor:self.widthAnchor],
 
-        [[box.leadingAnchor anchorWithOffsetToAnchor:exclamationPoint.leadingAnchor] constraintEqualToConstant:marginSize],
-        [[box.leadingAnchor anchorWithOffsetToAnchor:title.leadingAnchor] constraintEqualToConstant:marginSize * 1.5 + exclamationPointSize],
         [[box.leadingAnchor anchorWithOffsetToAnchor:warning.leadingAnchor] constraintEqualToConstant:marginSize],
 
         [[title.trailingAnchor anchorWithOffsetToAnchor:box.trailingAnchor] constraintGreaterThanOrEqualToConstant:marginSize],
         [[warning.trailingAnchor anchorWithOffsetToAnchor:box.trailingAnchor] constraintGreaterThanOrEqualToConstant:marginSize],
         [[goBack.trailingAnchor anchorWithOffsetToAnchor:box.trailingAnchor] constraintEqualToConstant:marginSize],
 
-        [[title.topAnchor anchorWithOffsetToAnchor:exclamationPoint.topAnchor] constraintEqualToAnchor:[exclamationPoint.bottomAnchor anchorWithOffsetToAnchor:title.bottomAnchor]],
-
-        [[box.topAnchor anchorWithOffsetToAnchor:title.topAnchor] constraintEqualToConstant:marginSize],
-        [[title.bottomAnchor anchorWithOffsetToAnchor:warning.topAnchor] constraintEqualToConstant:marginSize],
         [[warning.bottomAnchor anchorWithOffsetToAnchor:goBack.topAnchor] constraintEqualToConstant:marginSize],
     ]];
     
-    bool needsVerticalButtonLayout = buttonWidth(showDetails) + buttonWidth(goBack) + 3 * marginSize > self.frame.size.width;
+    bool needsVerticalButtonLayout = buttonSize(showDetails).width + buttonSize(goBack).width + 3 * marginSize > self.frame.size.width;
     if (needsVerticalButtonLayout) {
         [NSLayoutConstraint activateConstraints:@[
             [[showDetails.trailingAnchor anchorWithOffsetToAnchor:box.trailingAnchor] constraintEqualToConstant:marginSize],
             [[goBack.bottomAnchor anchorWithOffsetToAnchor:showDetails.topAnchor] constraintEqualToConstant:marginSize],
-            [[goBack.bottomAnchor anchorWithOffsetToAnchor:box.bottomAnchor] constraintEqualToConstant:marginSize * 2 + showDetails.frame.size.height],
+            [[goBack.bottomAnchor anchorWithOffsetToAnchor:box.bottomAnchor] constraintEqualToConstant:marginSize * 2 + buttonSize(showDetails).height],
         ]];
     } else {
         [NSLayoutConstraint activateConstraints:@[
@@ -338,6 +359,9 @@ static void setBackground(ViewType *view, ColorType *color)
             [[goBack.bottomAnchor anchorWithOffsetToAnchor:box.bottomAnchor] constraintEqualToConstant:marginSize],
         ]];
     }
+#if !PLATFORM(MAC)
+    [self updateContentSize];
+#endif
 #endif
 }
 
@@ -392,13 +416,20 @@ static void setBackground(ViewType *view, ColorType *color)
 #endif
     [self layoutText];
 #if !PLATFORM(MAC)
+    [self updateContentSize];
+#endif
+}
+
+#if !PLATFORM(MAC)
+- (void)updateContentSize
+{
     [self layoutIfNeeded];
     CGFloat height = 0;
     for (ViewType *subview in self.subviews)
         height += subview.frame.size.height;
     [self setContentSize: { self.frame.size.width, self.frame.size.height / 2 + height }];
-#endif
 }
+#endif
 
 - (void)layoutText
 {
index fbbc875..74495e4 100644 (file)
@@ -4323,6 +4323,7 @@ void WebPageProxy::decidePolicyForNavigationAction(WebFrameProxy& frame, WebCore
                     }
                 });
             });
+            m_uiClient->didShowSafeBrowsingWarning();
             return;
         }
         completionHandler(policyAction);
index 27adc59..b10696e 100644 (file)
@@ -1,3 +1,16 @@
+2018-12-12  Alex Christensen  <achristensen@webkit.org>
+
+        Implement safe browsing in WebKit on WatchOS
+        https://bugs.webkit.org/show_bug.cgi?id=192641
+        <rdar://problem/46376188>
+
+        Reviewed by Geoff Garen.
+
+        * TestWebKitAPI/Tests/WebKitCocoa/SafeBrowsing.mm:
+        (-[SafeBrowsingNavigationDelegate _webViewDidShowSafeBrowsingWarning:]):
+        (safeBrowsingView):
+        Add a test that the new delegate callback is called.
+
 2018-12-12  Michael Catanzaro  <mcatanzaro@igalia.com>
 
         Unreviewed manual rollout of r239100-r239102 and r239116
index 54284cb..d5f71fc 100644 (file)
 #import "TestNavigationDelegate.h"
 #import "TestWKWebView.h"
 #import <WebKit/WKNavigationDelegate.h>
+#import <WebKit/WKUIDelegatePrivate.h>
 #import <WebKit/WKWebViewPrivate.h>
 #import <wtf/RetainPtr.h>
 
 static bool committedNavigation;
+static bool warningShown;
 
-@interface SafeBrowsingNavigationDelegate : NSObject <WKNavigationDelegate>
+@interface SafeBrowsingNavigationDelegate : NSObject <WKNavigationDelegate, WKUIDelegatePrivate>
 @end
 
 @implementation SafeBrowsingNavigationDelegate
@@ -47,6 +49,11 @@ static bool committedNavigation;
     committedNavigation = true;
 }
 
+- (void)_webViewDidShowSafeBrowsingWarning:(WKWebView *)webView
+{
+    warningShown = true;
+}
+
 @end
 
 @interface TestServiceLookupResult : NSObject {
@@ -173,9 +180,12 @@ static RetainPtr<WKWebView> safeBrowsingView()
     static auto delegate = adoptNS([SafeBrowsingNavigationDelegate new]);
     auto webView = adoptNS([WKWebView new]);
     [webView setNavigationDelegate:delegate.get()];
+    [webView setUIDelegate:delegate.get()];
     [webView loadRequest:[NSURLRequest requestWithURL:resourceURL(@"simple")]];
+    EXPECT_FALSE(warningShown);
     while (![webView _safeBrowsingWarning])
         TestWebKitAPI::Util::spinRunLoop();
+    EXPECT_TRUE(warningShown);
 #if !PLATFORM(MAC)
     [[webView _safeBrowsingWarning] didMoveToWindow];
 #endif