[iOS] Use PDFKit SPI for taking snapshots when the hosting app is not entitled for...
authoraestes@apple.com <aestes@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 11 Jun 2019 00:45:50 +0000 (00:45 +0000)
committeraestes@apple.com <aestes@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 11 Jun 2019 00:45:50 +0000 (00:45 +0000)
https://bugs.webkit.org/show_bug.cgi?id=198731
<rdar://problem/46215174>

Reviewed by Tim Horton.

Source/WebKit:

PDFHostViewController renders PDF contents in a view service, and apps are unable to
snapshot views rendered out-of-process without an entitlement.

When an app is missing this entitlement and calls WKWebView's
takeSnapshotWithConfiguration: API when a PDF is displayed, fall back to calling
PDFHostViewController's snapshotting SPI.

Testing is blocked by <https://webkit.org/b/175204>.

* Platform/spi/ios/PDFKitSPI.h:
* UIProcess/API/Cocoa/WKWebView.mm:
(-[WKWebView _snapshotRect:intoImageOfWidth:completionHandler:]):
* UIProcess/Cocoa/WKWebViewContentProvider.h:
* UIProcess/ios/WKPDFView.mm:
(+[WKPDFView web_requiresCustomSnapshotting]):
(-[WKPDFView web_snapshotRectInContentViewCoordinates:snapshotWidth:completionHandler:]):
* UIProcess/ios/WKSystemPreviewView.mm:
(+[WKSystemPreviewView web_requiresCustomSnapshotting]):

Source/WTF:

* wtf/FeatureDefines.h:

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

Source/WTF/ChangeLog
Source/WTF/wtf/FeatureDefines.h
Source/WebKit/ChangeLog
Source/WebKit/Platform/spi/ios/PDFKitSPI.h
Source/WebKit/UIProcess/API/Cocoa/WKWebView.mm
Source/WebKit/UIProcess/Cocoa/WKWebViewContentProvider.h
Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm
Source/WebKit/UIProcess/ios/WKPDFView.mm
Source/WebKit/UIProcess/ios/WKSystemPreviewView.mm

index 29d2394..24c8021 100644 (file)
@@ -1,3 +1,13 @@
+2019-06-10  Andy Estes  <aestes@apple.com>
+
+        [iOS] Use PDFKit SPI for taking snapshots when the hosting app is not entitled for global capture
+        https://bugs.webkit.org/show_bug.cgi?id=198731
+        <rdar://problem/46215174>
+
+        Reviewed by Tim Horton.
+
+        * wtf/FeatureDefines.h:
+
 2019-06-10  Sam Weinig  <weinig@apple.com>
 
         Remove Dashboard support
index 1fd946b..5168146 100644 (file)
@@ -172,11 +172,17 @@ the public iOS SDK. See <https://webkit.org/b/179167>. */
 #endif
 
 #if !defined(ENABLE_WKPDFVIEW)
-#if PLATFORM(IOS_FAMILY) && !PLATFORM(WATCHOS) && !PLATFORM(APPLETV) && !PLATFORM(IOSMAC) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 120000
+#if !PLATFORM(WATCHOS) && !PLATFORM(APPLETV) && !PLATFORM(IOSMAC) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 120000
 #define ENABLE_WKPDFVIEW 1
 #endif
 #endif
 
+#if !defined(HAVE_PDFHOSTVIEWCONTROLLER_SNAPSHOTTING)
+#if !PLATFORM(WATCHOS) && !PLATFORM(APPLETV) && !PLATFORM(IOSMAC) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 130000
+#define HAVE_PDFHOSTVIEWCONTROLLER_SNAPSHOTTING 1
+#endif
+#endif
+
 #if !defined(HAVE_VISIBILITY_PROPAGATION_VIEW)
 #if __IPHONE_OS_VERSION_MIN_REQUIRED >= 130000
 #define HAVE_VISIBILITY_PROPAGATION_VIEW 1
index f6b7f04..490570a 100644 (file)
@@ -1,3 +1,30 @@
+2019-06-10  Andy Estes  <aestes@apple.com>
+
+        [iOS] Use PDFKit SPI for taking snapshots when the hosting app is not entitled for global capture
+        https://bugs.webkit.org/show_bug.cgi?id=198731
+        <rdar://problem/46215174>
+
+        Reviewed by Tim Horton.
+
+        PDFHostViewController renders PDF contents in a view service, and apps are unable to
+        snapshot views rendered out-of-process without an entitlement.
+
+        When an app is missing this entitlement and calls WKWebView's
+        takeSnapshotWithConfiguration: API when a PDF is displayed, fall back to calling
+        PDFHostViewController's snapshotting SPI.
+
+        Testing is blocked by <https://webkit.org/b/175204>.
+
+        * Platform/spi/ios/PDFKitSPI.h:
+        * UIProcess/API/Cocoa/WKWebView.mm:
+        (-[WKWebView _snapshotRect:intoImageOfWidth:completionHandler:]):
+        * UIProcess/Cocoa/WKWebViewContentProvider.h:
+        * UIProcess/ios/WKPDFView.mm:
+        (+[WKPDFView web_requiresCustomSnapshotting]):
+        (-[WKPDFView web_snapshotRectInContentViewCoordinates:snapshotWidth:completionHandler:]):
+        * UIProcess/ios/WKSystemPreviewView.mm:
+        (+[WKSystemPreviewView web_requiresCustomSnapshotting]):
+
 2019-06-10  Sam Weinig  <weinig@apple.com>
 
         Remove Dashboard support
index 93b0105..fac6378 100644 (file)
 - (void) beginPDFViewRotation;
 - (void) endPDFViewRotation;
 
+#if HAVE(PDFHOSTVIEWCONTROLLER_SNAPSHOTTING)
+- (void) snapshotViewRect: (CGRect) rect snapshotWidth: (NSNumber*) width afterScreenUpdates: (BOOL) afterScreenUpdates withResult: (void (^)(UIImage* image)) completion;
+#endif
+
 @end
 
 #endif
index 20558c9..a1beb77 100644 (file)
@@ -6198,6 +6198,11 @@ static inline WebKit::FindOptions toFindOptions(_WKFindOptions wkFindOptions)
     CGFloat imageHeight = imageScale * snapshotRectInContentCoordinates.size.height;
     CGSize imageSize = CGSizeMake(imageWidth, imageHeight);
 
+    if ([[_customContentView class] web_requiresCustomSnapshotting]) {
+        [_customContentView web_snapshotRectInContentViewCoordinates:snapshotRectInContentCoordinates snapshotWidth:imageWidth completionHandler:completionHandler];
+        return;
+    }
+
 #if HAVE(CORE_ANIMATION_RENDER_SERVER) && HAVE(IOSURFACE)
     // If we are parented and thus won't incur a significant penalty from paging in tiles, snapshot the view hierarchy directly.
     if (NSString *displayName = self.window.screen.displayConfiguration.name) {
@@ -6216,6 +6221,7 @@ static inline WebKit::FindOptions toFindOptions(_WKFindOptions wkFindOptions)
 #endif
 
     if (_customContentView) {
+        ASSERT(![[_customContentView class] web_requiresCustomSnapshotting]);
         UIGraphicsBeginImageContextWithOptions(imageSize, YES, 1);
 
         UIView *customContentView = _customContentView.get();
index 0a3b1c9..8d8a942 100644 (file)
@@ -52,6 +52,7 @@ struct UIEdgeInsets;
 - (void)web_findString:(NSString *)string options:(_WKFindOptions)options maxCount:(NSUInteger)maxCount;
 - (void)web_hideFindUI;
 @property (nonatomic, readonly) UIView *web_contentView;
+@property (nonatomic, readonly, class) BOOL web_requiresCustomSnapshotting;
 
 @optional
 - (void)web_scrollViewDidScroll:(UIScrollView *)scrollView;
@@ -60,6 +61,7 @@ struct UIEdgeInsets;
 - (void)web_scrollViewDidZoom:(UIScrollView *)scrollView;
 - (void)web_beginAnimatedResizeWithUpdates:(void (^)(void))updateBlock;
 - (BOOL)web_handleKeyEvent:(UIEvent *)event;
+- (void)web_snapshotRectInContentViewCoordinates:(CGRect)contentViewCoordinates snapshotWidth:(CGFloat)snapshotWidth completionHandler:(void (^)(CGImageRef))completionHandler;
 @property (nonatomic, readonly) NSData *web_dataRepresentation;
 @property (nonatomic, readonly) NSString *web_suggestedFilename;
 @property (nonatomic, readonly) BOOL web_isBackground;
index ca87bf3..25d40f7 100644 (file)
@@ -7565,9 +7565,11 @@ static NSString *previewIdentifierForElementAction(_WKElementAction *action)
         if ([uiDelegate respondsToSelector:@selector(webView:previewingViewControllerForElement:defaultActions:)]) {
             auto previewActions = adoptNS([[NSMutableArray alloc] init]);
             for (_WKElementAction *elementAction in actions.get()) {
+                ALLOW_DEPRECATED_DECLARATIONS_BEGIN
                 WKPreviewAction *previewAction = [WKPreviewAction actionWithIdentifier:previewIdentifierForElementAction(elementAction) title:[elementAction title] style:UIPreviewActionStyleDefault handler:^(UIPreviewAction *, UIViewController *) {
                     [elementAction runActionWithElementInfo:elementInfo.get()];
                 }];
+                ALLOW_DEPRECATED_DECLARATIONS_END
                 [previewActions addObject:previewAction];
             }
             ALLOW_DEPRECATED_DECLARATIONS_BEGIN
index 6c500fd..025701d 100644 (file)
@@ -45,6 +45,7 @@
 #import <wtf/MainThread.h>
 #import <wtf/RetainPtr.h>
 #import <wtf/WeakObjCPtr.h>
+#import <wtf/cocoa/Entitlements.h>
 #import <wtf/cocoa/NSURLExtras.h>
 
 @interface WKPDFView () <PDFHostViewControllerDelegate, WKActionSheetAssistantDelegate>
@@ -357,6 +358,16 @@ static NSStringCompareOptions stringCompareOptions(_WKFindOptions findOptions)
     return self._contentView;
 }
 
++ (BOOL)web_requiresCustomSnapshotting
+{
+#if HAVE(PDFHOSTVIEWCONTROLLER_SNAPSHOTTING)
+    static bool hasGlobalCaptureEntitlement = WTF::processHasEntitlement("com.apple.QuartzCore.global-capture");
+    return !hasGlobalCaptureEntitlement;
+#else
+    return false;
+#endif
+}
+
 - (void)web_scrollViewDidScroll:(UIScrollView *)scrollView
 {
     [_hostViewController updatePDFViewLayout];
@@ -384,6 +395,16 @@ static NSStringCompareOptions stringCompareOptions(_WKFindOptions findOptions)
     [_hostViewController endPDFViewRotation];
 }
 
+- (void)web_snapshotRectInContentViewCoordinates:(CGRect)rectInContentViewCoordinates snapshotWidth:(CGFloat)snapshotWidth completionHandler:(void (^)(CGImageRef))completionHandler
+{
+#if HAVE(PDFHOSTVIEWCONTROLLER_SNAPSHOTTING)
+    CGRect rectInHostViewCoordinates = [self._contentView convertRect:rectInContentViewCoordinates toView:[_hostViewController view]];
+    [_hostViewController snapshotViewRect:rectInHostViewCoordinates snapshotWidth:@(snapshotWidth) afterScreenUpdates:NO withResult:^(UIImage *image) {
+        completionHandler(image.CGImage);
+    }];
+#endif
+}
+
 - (NSData *)web_dataRepresentation
 {
     return _data.get();
index ba2e6da..14f04b9 100644 (file)
@@ -144,6 +144,11 @@ static NSString *getUTIForSystemPreviewMIMEType(const String& mimeType)
     return self;
 }
 
++ (BOOL)web_requiresCustomSnapshotting
+{
+    return false;
+}
+
 - (void)web_setMinimumSize:(CGSize)size
 {
 }