Title: [266654] trunk
Revision
266654
Author
[email protected]
Date
2020-09-04 21:07:47 -0700 (Fri, 04 Sep 2020)

Log Message

Move PDF heads-up display to UI process on macOS
https://bugs.webkit.org/show_bug.cgi?id=215780
<rdar://problem/58715847>

Patch by Alex Christensen <[email protected]> on 2020-09-04
Reviewed by Tim Horton.

Source/WebKit:

This has many benefits including the one in the radar, testability, and moving WebKit-specific code from PDFKit to WebKit.

Now that the HUD is displayed in the UI process instead of in the web content, zooming in keeps the HUD the same size.
A 3d-transformed iframe with a PDF in it now shows the HUD in the place you can click on it, instead of in the transformed PDF.
Also, moving the mouse to the HUD within the first 3 seconds prevents it from hiding, which it does when the mouse leaves the HUD.
The rest of the behavior I think should be the same.  Most users should not notice any difference.

Functionality covered by API tests, the first tests for PDF content interaction!

* Scripts/webkit/messages.py:
* UIProcess/API/Cocoa/WKWebViewInternal.h:
* UIProcess/API/mac/WKView.mm:
(-[WKView _createPDFHUD:rect:]):
(-[WKView _pdfHUD:changedLocation:]):
(-[WKView _removePDFHUD:]):
(-[WKView _removeAllPDFHUDs]):
* UIProcess/API/mac/WKWebViewMac.mm:
(-[WKWebView mouseMoved:]):
(-[WKWebView mouseDown:]):
(-[WKWebView mouseUp:]):
(-[WKWebView _createPDFHUD:rect:]):
(-[WKWebView _pdfHUD:changedLocation:]):
(-[WKWebView _removePDFHUD:]):
(-[WKWebView _removeAllPDFHUDs]):
* UIProcess/API/mac/WKWebViewPrivateForTestingMac.h:
* UIProcess/API/mac/WKWebViewTestingMac.mm:
(-[WKWebView pdfHUDs]):
* UIProcess/Cocoa/WebViewImpl.h:
* UIProcess/Cocoa/WebViewImpl.mm:
(WebKit::WebViewImpl::createPDFHUD):
(WebKit::WebViewImpl::updatePDFHUDLocation):
(WebKit::WebViewImpl::removePDFHUD):
(WebKit::WebViewImpl::removeAllPDFHUDs):
* UIProcess/PageClient.h:
* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::didCommitLoadForFrame):
(WebKit::WebPageProxy::processDidTerminate):
* UIProcess/WebPageProxy.h:
* UIProcess/WebPageProxy.messages.in:
* UIProcess/ios/WebPageProxyIOS.mm:
(WebKit::WebPageProxy::savePDFToTemporaryFolderAndOpenWithNativeApplication): Deleted.
(WebKit::WebPageProxy::openPDFFromTemporaryFolderWithNativeApplication): Deleted.
* UIProcess/mac/PageClientImplMac.h:
* UIProcess/mac/PageClientImplMac.mm:
(WebKit::PageClientImpl::createPDFHUD):
(WebKit::PageClientImpl::updatePDFHUDLocation):
(WebKit::PageClientImpl::removePDFHUD):
(WebKit::PageClientImpl::removeAllPDFHUDs):
* UIProcess/mac/WebPageProxyMac.mm:
(WebKit::WebPageProxy::savePDFToTemporaryFolderAndOpenWithNativeApplication):
(WebKit::WebPageProxy::createPDFHUD):
(WebKit::WebPageProxy::removePDFHUD):
(WebKit::WebPageProxy::updatePDFHUDLocation):
(WebKit::WebPageProxy::pdfZoomIn):
(WebKit::WebPageProxy::pdfZoomOut):
(WebKit::WebPageProxy::pdfSaveToPDF):
(WebKit::WebPageProxy::pdfOpenWithPreview):
* WebKit.xcodeproj/project.pbxproj:
* WebProcess/Plugins/PDF/PDFLayerControllerSPI.h:
* WebProcess/Plugins/PDF/PDFPlugin.h:
* WebProcess/Plugins/PDF/PDFPlugin.mm:
(-[WKPDFLayerControllerDelegate openWithNativeApplication]):
(-[WKPDFLayerControllerDelegate saveToPDF]):
(WebKit::PDFPlugin::PDFPlugin):
(WebKit::PDFPlugin::~PDFPlugin):
(WebKit::PDFPlugin::frameForHUD const):
(WebKit::PDFPlugin::calculateSizes):
(WebKit::PDFPlugin::convertFromPDFViewToRootView const):
(WebKit::PDFPlugin::visibilityDidChange):
(WebKit::PDFPlugin::zoomIn):
(WebKit::PDFPlugin::zoomOut):
(WebKit::PDFPlugin::save):
(WebKit::PDFPlugin::openWithPreview):
* WebProcess/WebPage/WebPage.cpp:
* WebProcess/WebPage/WebPage.h:
* WebProcess/WebPage/WebPage.messages.in:
* WebProcess/WebPage/mac/WebPageMac.mm:
(WebKit::WebPage::zoomPDFIn):
(WebKit::WebPage::zoomPDFOut):
(WebKit::WebPage::savePDF):
(WebKit::WebPage::openPDFWithPreview):
(WebKit::WebPage::createPDFHUD):
(WebKit::WebPage::updatePDFHUDLocation):
(WebKit::WebPage::removePDFHUD):

Source/WTF:

* wtf/PlatformHave.h:

Tools:

* TestWebKitAPI/Tests/WebKitCocoa/WKPDFView.mm:
(pdfData):
(TEST):
(checkFrame):
* TestWebKitAPI/cocoa/TestUIDelegate.h:
* TestWebKitAPI/cocoa/TestUIDelegate.mm:
(-[TestUIDelegate _webView:saveDataToFile:suggestedFilename:mimeType:originatingURL:]):

Modified Paths

Added Paths

Diff

Modified: trunk/Source/WTF/ChangeLog (266653 => 266654)


--- trunk/Source/WTF/ChangeLog	2020-09-05 03:52:42 UTC (rev 266653)
+++ trunk/Source/WTF/ChangeLog	2020-09-05 04:07:47 UTC (rev 266654)
@@ -1,3 +1,13 @@
+2020-09-04  Alex Christensen  <[email protected]>
+
+        Move PDF heads-up display to UI process on macOS
+        https://bugs.webkit.org/show_bug.cgi?id=215780
+        <rdar://problem/58715847>
+
+        Reviewed by Tim Horton.
+
+        * wtf/PlatformHave.h:
+
 2020-09-03  Ryosuke Niwa  <[email protected]>
 
         GTK+ build fix attempt after r266573.

Modified: trunk/Source/WTF/wtf/PlatformEnableCocoa.h (266653 => 266654)


--- trunk/Source/WTF/wtf/PlatformEnableCocoa.h	2020-09-05 03:52:42 UTC (rev 266653)
+++ trunk/Source/WTF/wtf/PlatformEnableCocoa.h	2020-09-05 04:07:47 UTC (rev 266654)
@@ -228,6 +228,10 @@
 #define ENABLE_GPU_DRIVER_PREWARMING 1
 #endif
 
+#if PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 110000
+#define ENABLE_UI_PROCESS_PDF_HUD 1
+#endif
+
 #if !defined(ENABLE_INDEXED_DATABASE)
 #define ENABLE_INDEXED_DATABASE 1
 #endif

Modified: trunk/Source/WebCore/PAL/pal/spi/mac/NSImageSPI.h (266653 => 266654)


--- trunk/Source/WebCore/PAL/pal/spi/mac/NSImageSPI.h	2020-09-05 03:52:42 UTC (rev 266653)
+++ trunk/Source/WebCore/PAL/pal/spi/mac/NSImageSPI.h	2020-09-05 04:07:47 UTC (rev 266654)
@@ -36,6 +36,8 @@
 NS_ASSUME_NONNULL_BEGIN
 
 @interface NSImage ()
++ (instancetype)imageWithImageRep:(NSImageRep *)imageRep;
+- (instancetype)_imageWithConfiguration:(NSDictionary *)configuration;
 - (void)lockFocusWithRect:(NSRect)rect context:(nullable NSGraphicsContext *)context hints:(nullable NSDictionary *)hints flipped:(BOOL)flipped;
 @end
 
@@ -43,6 +45,13 @@
 + (nullable NSImage *)_imageWithSystemSymbolName:(NSString *) symbolName;
 @end
 
+WTF_EXTERN_C_BEGIN
+
+extern const NSString *NSImageAlternateCriterionFont;
+extern const NSString *NSImageAlternateCriterionSymbolScale;
+
+WTF_EXTERN_C_END
+
 NS_ASSUME_NONNULL_END
 
 #endif
@@ -56,6 +65,6 @@
 
 NS_ASSUME_NONNULL_END
 
-#endif
+#endif // HAVE(ALTERNATE_ICONS)
 
-#endif
+#endif // USE(APPLE_INTERNAL_SDK)

Modified: trunk/Source/WebKit/ChangeLog (266653 => 266654)


--- trunk/Source/WebKit/ChangeLog	2020-09-05 03:52:42 UTC (rev 266653)
+++ trunk/Source/WebKit/ChangeLog	2020-09-05 04:07:47 UTC (rev 266654)
@@ -1,3 +1,96 @@
+2020-09-04  Alex Christensen  <[email protected]>
+
+        Move PDF heads-up display to UI process on macOS
+        https://bugs.webkit.org/show_bug.cgi?id=215780
+        <rdar://problem/58715847>
+
+        Reviewed by Tim Horton.
+
+        This has many benefits including the one in the radar, testability, and moving WebKit-specific code from PDFKit to WebKit.
+
+        Now that the HUD is displayed in the UI process instead of in the web content, zooming in keeps the HUD the same size.
+        A 3d-transformed iframe with a PDF in it now shows the HUD in the place you can click on it, instead of in the transformed PDF.
+        Also, moving the mouse to the HUD within the first 3 seconds prevents it from hiding, which it does when the mouse leaves the HUD.
+        The rest of the behavior I think should be the same.  Most users should not notice any difference.
+
+        Functionality covered by API tests, the first tests for PDF content interaction!
+
+        * Scripts/webkit/messages.py:
+        * UIProcess/API/Cocoa/WKWebViewInternal.h:
+        * UIProcess/API/mac/WKView.mm:
+        (-[WKView _createPDFHUD:rect:]):
+        (-[WKView _pdfHUD:changedLocation:]):
+        (-[WKView _removePDFHUD:]):
+        (-[WKView _removeAllPDFHUDs]):
+        * UIProcess/API/mac/WKWebViewMac.mm:
+        (-[WKWebView mouseMoved:]):
+        (-[WKWebView mouseDown:]):
+        (-[WKWebView mouseUp:]):
+        (-[WKWebView _createPDFHUD:rect:]):
+        (-[WKWebView _pdfHUD:changedLocation:]):
+        (-[WKWebView _removePDFHUD:]):
+        (-[WKWebView _removeAllPDFHUDs]):
+        * UIProcess/API/mac/WKWebViewPrivateForTestingMac.h:
+        * UIProcess/API/mac/WKWebViewTestingMac.mm:
+        (-[WKWebView pdfHUDs]):
+        * UIProcess/Cocoa/WebViewImpl.h:
+        * UIProcess/Cocoa/WebViewImpl.mm:
+        (WebKit::WebViewImpl::createPDFHUD):
+        (WebKit::WebViewImpl::updatePDFHUDLocation):
+        (WebKit::WebViewImpl::removePDFHUD):
+        (WebKit::WebViewImpl::removeAllPDFHUDs):
+        * UIProcess/PageClient.h:
+        * UIProcess/WebPageProxy.cpp:
+        (WebKit::WebPageProxy::didCommitLoadForFrame):
+        (WebKit::WebPageProxy::processDidTerminate):
+        * UIProcess/WebPageProxy.h:
+        * UIProcess/WebPageProxy.messages.in:
+        * UIProcess/ios/WebPageProxyIOS.mm:
+        (WebKit::WebPageProxy::savePDFToTemporaryFolderAndOpenWithNativeApplication): Deleted.
+        (WebKit::WebPageProxy::openPDFFromTemporaryFolderWithNativeApplication): Deleted.
+        * UIProcess/mac/PageClientImplMac.h:
+        * UIProcess/mac/PageClientImplMac.mm:
+        (WebKit::PageClientImpl::createPDFHUD):
+        (WebKit::PageClientImpl::updatePDFHUDLocation):
+        (WebKit::PageClientImpl::removePDFHUD):
+        (WebKit::PageClientImpl::removeAllPDFHUDs):
+        * UIProcess/mac/WebPageProxyMac.mm:
+        (WebKit::WebPageProxy::savePDFToTemporaryFolderAndOpenWithNativeApplication):
+        (WebKit::WebPageProxy::createPDFHUD):
+        (WebKit::WebPageProxy::removePDFHUD):
+        (WebKit::WebPageProxy::updatePDFHUDLocation):
+        (WebKit::WebPageProxy::pdfZoomIn):
+        (WebKit::WebPageProxy::pdfZoomOut):
+        (WebKit::WebPageProxy::pdfSaveToPDF):
+        (WebKit::WebPageProxy::pdfOpenWithPreview):
+        * WebKit.xcodeproj/project.pbxproj:
+        * WebProcess/Plugins/PDF/PDFLayerControllerSPI.h:
+        * WebProcess/Plugins/PDF/PDFPlugin.h:
+        * WebProcess/Plugins/PDF/PDFPlugin.mm:
+        (-[WKPDFLayerControllerDelegate openWithNativeApplication]):
+        (-[WKPDFLayerControllerDelegate saveToPDF]):
+        (WebKit::PDFPlugin::PDFPlugin):
+        (WebKit::PDFPlugin::~PDFPlugin):
+        (WebKit::PDFPlugin::frameForHUD const):
+        (WebKit::PDFPlugin::calculateSizes):
+        (WebKit::PDFPlugin::convertFromPDFViewToRootView const):
+        (WebKit::PDFPlugin::visibilityDidChange):
+        (WebKit::PDFPlugin::zoomIn):
+        (WebKit::PDFPlugin::zoomOut):
+        (WebKit::PDFPlugin::save):
+        (WebKit::PDFPlugin::openWithPreview):
+        * WebProcess/WebPage/WebPage.cpp:
+        * WebProcess/WebPage/WebPage.h:
+        * WebProcess/WebPage/WebPage.messages.in:
+        * WebProcess/WebPage/mac/WebPageMac.mm:
+        (WebKit::WebPage::zoomPDFIn):
+        (WebKit::WebPage::zoomPDFOut):
+        (WebKit::WebPage::savePDF):
+        (WebKit::WebPage::openPDFWithPreview):
+        (WebKit::WebPage::createPDFHUD):
+        (WebKit::WebPage::updatePDFHUDLocation):
+        (WebKit::WebPage::removePDFHUD):
+
 2020-09-04  Chris Dumez  <[email protected]>
 
         handleXPCEndpointMessages does not check XPC object is an xpc_endpoint_t

Modified: trunk/Source/WebKit/Scripts/webkit/messages.py (266653 => 266654)


--- trunk/Source/WebKit/Scripts/webkit/messages.py	2020-09-05 03:52:42 UTC (rev 266653)
+++ trunk/Source/WebKit/Scripts/webkit/messages.py	2020-09-05 04:07:47 UTC (rev 266654)
@@ -244,6 +244,7 @@
         'WebKit::MDNSRegisterIdentifier',
         'WebKit::MediaPlayerPrivateRemoteIdentifier',
         'WebKit::MediaRecorderIdentifier',
+        'WebKit::PDFPluginIdentifier',
         'WebKit::PlaybackSessionContextIdentifier',
         'WebKit::PluginProcessType',
         'WebKit::RemoteAudioDestinationIdentifier',

Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebViewInternal.h (266653 => 266654)


--- trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebViewInternal.h	2020-09-05 03:52:42 UTC (rev 266653)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebViewInternal.h	2020-09-05 04:07:47 UTC (rev 266654)
@@ -23,11 +23,11 @@
  * THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#import "WKWebViewPrivate.h"
-
+#import "PDFPluginIdentifier.h"
 #import "SameDocumentNavigationType.h"
 #import "WKShareSheet.h"
 #import "WKWebViewConfiguration.h"
+#import "WKWebViewPrivate.h"
 #import "_WKAttachmentInternal.h"
 #import "_WKWebViewPrintFormatterInternal.h"
 #import <wtf/CompletionHandler.h>
@@ -133,7 +133,7 @@
     // Only used with UI-side compositing.
     RetainPtr<WKScrollView> _scrollView;
     RetainPtr<WKContentView> _contentView;
-#endif
+#endif // PLATFORM(MAC)
 
 #if PLATFORM(IOS_FAMILY)
     RetainPtr<WKScrollView> _scrollView;

Modified: trunk/Source/WebKit/UIProcess/API/mac/WKWebViewPrivateForTestingMac.h (266653 => 266654)


--- trunk/Source/WebKit/UIProcess/API/mac/WKWebViewPrivateForTestingMac.h	2020-09-05 03:52:42 UTC (rev 266653)
+++ trunk/Source/WebKit/UIProcess/API/mac/WKWebViewPrivateForTestingMac.h	2020-09-05 04:07:47 UTC (rev 266654)
@@ -50,6 +50,7 @@
 
 - (void)_setHeaderBannerHeight:(int)height;
 - (void)_setFooterBannerHeight:(int)height;
+- (NSSet<NSView *> *)_pdfHUDs;
 
 @end
 

Modified: trunk/Source/WebKit/UIProcess/API/mac/WKWebViewTestingMac.mm (266653 => 266654)


--- trunk/Source/WebKit/UIProcess/API/mac/WKWebViewTestingMac.mm	2020-09-05 03:52:42 UTC (rev 266653)
+++ trunk/Source/WebKit/UIProcess/API/mac/WKWebViewTestingMac.mm	2020-09-05 04:07:47 UTC (rev 266654)
@@ -103,6 +103,15 @@
     _page->setFooterBannerHeightForTesting(height);
 }
 
+- (NSSet<NSView *> *)_pdfHUDs
+{
+#if ENABLE(UI_PROCESS_PDF_HUD)
+    return _impl->pdfHUDs();
+#else
+    return nil;
+#endif
+}
+
 - (NSMenu *)_activeMenu
 {
     // FIXME: Only the DOM paste access menu is supported for now. In the future, it could be

Modified: trunk/Source/WebKit/UIProcess/Cocoa/WebViewImpl.h (266653 => 266654)


--- trunk/Source/WebKit/UIProcess/Cocoa/WebViewImpl.h	2020-09-05 03:52:42 UTC (rev 266653)
+++ trunk/Source/WebKit/UIProcess/Cocoa/WebViewImpl.h	2020-09-05 04:07:47 UTC (rev 266654)
@@ -27,6 +27,7 @@
 
 #if PLATFORM(MAC)
 
+#include "PDFPluginIdentifier.h"
 #include "PluginComplexTextInputState.h"
 #include "ShareableBitmap.h"
 #include "WKLayoutMode.h"
@@ -76,6 +77,10 @@
 OBJC_CLASS WebPlaybackControlsManager;
 #endif // HAVE(TOUCH_BAR)
 
+#if ENABLE(UI_PROCESS_PDF_HUD)
+OBJC_CLASS WKPDFHUDView;
+#endif
+
 namespace API {
 class HitTestResult;
 class Object;
@@ -190,6 +195,14 @@
     void viewWillStartLiveResize();
     void viewDidEndLiveResize();
 
+#if ENABLE(UI_PROCESS_PDF_HUD)
+    void createPDFHUD(PDFPluginIdentifier, const WebCore::IntRect&);
+    void updatePDFHUDLocation(PDFPluginIdentifier, const WebCore::IntRect&);
+    void removePDFHUD(PDFPluginIdentifier);
+    void removeAllPDFHUDs();
+    NSSet *pdfHUDs();
+#endif
+
     void renewGState();
     void setFrameSize(CGSize);
     void disableFrameSizeUpdates();
@@ -729,7 +742,11 @@
 #if ENABLE(FULLSCREEN_API)
     RetainPtr<WKFullScreenWindowController> m_fullScreenWindowController;
 #endif
-    
+
+#if ENABLE(UI_PROCESS_PDF_HUD)
+    HashMap<WebKit::PDFPluginIdentifier, RetainPtr<WKPDFHUDView>> _pdfHUDViews;
+#endif
+
     RetainPtr<WKShareSheet> _shareSheet;
 
     RetainPtr<WKWindowVisibilityObserver> m_windowVisibilityObserver;

Modified: trunk/Source/WebKit/UIProcess/Cocoa/WebViewImpl.mm (266653 => 266654)


--- trunk/Source/WebKit/UIProcess/Cocoa/WebViewImpl.mm	2020-09-05 03:52:42 UTC (rev 266653)
+++ trunk/Source/WebKit/UIProcess/Cocoa/WebViewImpl.mm	2020-09-05 04:07:47 UTC (rev 266654)
@@ -62,6 +62,7 @@
 #import "WKErrorInternal.h"
 #import "WKFullScreenWindowController.h"
 #import "WKImmediateActionController.h"
+#import "WKPDFHUDView.h"
 #import "WKPrintingView.h"
 #import "WKSafeBrowsingWarning.h"
 #import "WKShareSheet.h"
@@ -1718,6 +1719,45 @@
     [m_layoutStrategy didEndLiveResize];
 }
 
+#if ENABLE(UI_PROCESS_PDF_HUD)
+
+void WebViewImpl::createPDFHUD(PDFPluginIdentifier identifier, const WebCore::IntRect& rect)
+{
+    removePDFHUD(identifier);
+    auto hud = adoptNS([[WKPDFHUDView alloc] initWithFrame:rect pluginIdentifier:identifier page:m_page.get()]);
+    [m_view addSubview:hud.get()];
+    _pdfHUDViews.add(identifier, WTFMove(hud));
+}
+
+void WebViewImpl::updatePDFHUDLocation(PDFPluginIdentifier identifier, const WebCore::IntRect& rect)
+{
+    if (auto hud = _pdfHUDViews.get(identifier))
+        [hud setFrame:rect];
+}
+
+void WebViewImpl::removePDFHUD(PDFPluginIdentifier identifier)
+{
+    if (auto hud = _pdfHUDViews.take(identifier))
+        [hud removeFromSuperview];
+}
+
+void WebViewImpl::removeAllPDFHUDs()
+{
+    for (auto& hud : _pdfHUDViews.values())
+        [hud removeFromSuperview];
+    _pdfHUDViews.clear();
+}
+
+NSSet *WebViewImpl::pdfHUDs()
+{
+    NSMutableSet<NSView *> *set = [NSMutableSet setWithCapacity:_pdfHUDViews.size()];
+    for (auto& hud : _pdfHUDViews.values())
+        [set addObject:hud.get()];
+    return set;
+}
+
+#endif // ENABLE(UI_PROCESS_PDF_HUD)
+
 void WebViewImpl::renewGState()
 {
     if (m_textIndicatorWindow)
@@ -2149,6 +2189,10 @@
         return;
 
     m_page->setIntrinsicDeviceScaleFactor(newBackingScaleFactor);
+#if ENABLE(UI_PROCESS_PDF_HUD)
+    for (auto& hud : _pdfHUDViews.values())
+        [hud setDeviceScaleFactor:newBackingScaleFactor];
+#endif
 }
 
 void WebViewImpl::windowDidChangeScreen()
@@ -5391,6 +5435,11 @@
     if (m_ignoresNonWheelEvents)
         return;
 
+#if ENABLE(UI_PROCESS_PDF_HUD)
+    for (auto& hud : _pdfHUDViews.values())
+        [hud mouseMoved:event];
+#endif
+
     // When a view is first responder, it gets mouse moved events even when the mouse is outside its visible rect.
     if (m_view.getAutoreleased() == [m_view window].firstResponder && !NSPointInRect([m_view convertPoint:[event locationInWindow] fromView:nil], [m_view visibleRect]))
         return;
@@ -5439,6 +5488,11 @@
     if (m_ignoresNonWheelEvents)
         return;
 
+#if ENABLE(UI_PROCESS_PDF_HUD)
+    for (auto& hud : _pdfHUDViews.values())
+        [hud mouseDown:event];
+#endif
+
     setLastMouseDownEvent(event);
     setIgnoresMouseDraggedEvents(false);
 
@@ -5450,6 +5504,11 @@
     if (m_ignoresNonWheelEvents)
         return;
 
+#if ENABLE(UI_PROCESS_PDF_HUD)
+    for (auto& hud : _pdfHUDViews.values())
+        [hud mouseUp:event];
+#endif
+
     setLastMouseDownEvent(nil);
     mouseUpInternal(event);
 }

Copied: trunk/Source/WebKit/UIProcess/PDF/WKPDFHUDView.h (from rev 266653, trunk/Tools/TestWebKitAPI/cocoa/TestUIDelegate.h) (0 => 266654)


--- trunk/Source/WebKit/UIProcess/PDF/WKPDFHUDView.h	                        (rev 0)
+++ trunk/Source/WebKit/UIProcess/PDF/WKPDFHUDView.h	2020-09-05 04:07:47 UTC (rev 266654)
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+#if ENABLE(UI_PROCESS_PDF_HUD)
+
+#import "PDFPluginIdentifier.h"
+
+namespace WebKit {
+class WebPageProxy;
+}
+
+@interface WKPDFHUDView : NSView
+
+- (instancetype)initWithFrame:(NSRect)frame pluginIdentifier:(WebKit::PDFPluginIdentifier)pluginIdentifier page:(WebKit::WebPageProxy&)page;
+- (void)setFrame:(NSRect)frame;
+- (void)mouseMoved:(NSEvent *)event;
+- (void)mouseDown:(NSEvent *)event;
+- (void)mouseUp:(NSEvent *)event;
+- (void)setDeviceScaleFactor:(CGFloat)deviceScaleFactor;
+
+@end
+
+#endif // ENABLE(UI_PROCESS_PDF_HUD)

Added: trunk/Source/WebKit/UIProcess/PDF/WKPDFHUDView.mm (0 => 266654)


--- trunk/Source/WebKit/UIProcess/PDF/WKPDFHUDView.mm	                        (rev 0)
+++ trunk/Source/WebKit/UIProcess/PDF/WKPDFHUDView.mm	2020-09-05 04:07:47 UTC (rev 266654)
@@ -0,0 +1,352 @@
+/*
+ * Copyright (C) 2020 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"
+#import "WKPDFHUDView.h"
+
+#if ENABLE(UI_PROCESS_PDF_HUD)
+
+#import "WebPageProxy.h"
+#import <QuartzCore/CATransaction.h>
+#import <pal/spi/cocoa/QuartzCoreSPI.h>
+#import <pal/spi/mac/NSImageSPI.h>
+#import <wtf/WeakObjCPtr.h>
+
+//  The HUD items should have the following spacing:
+//  -------------------------------------------------
+// |      12        12      10     12        12      |
+// |     ----      ----     |     ----      ----     |
+// | 10 |icon| 10 |icon| 10 | 10 |icon| 10 |icon| 10 |
+// |     ----      ----     |     ----      ----     |
+// |      12        12      10     12        12      |
+//  -------------------------------------------------
+//  where the 12 point vertical spacing is anchored to the smallest icon image,
+//  and all subsequent icons with be centered vertically with the smallest icon.
+
+static const CGFloat layerVerticalOffset = 40;
+static const CGFloat layerCornerRadius = 12;
+static const CGFloat layerGrayComponent = 0;
+static const CGFloat layerAlpha = 0.75;
+static const CGFloat layerImageScale = 1.5;
+static const CGFloat layerSeperatorControllerSize = 1.5;
+static const CGFloat layerControllerHorizontalMargin = 10.0;
+static const CGFloat layerImageVerticalMargin = 12.0;
+static const CGFloat layerSeperatorVerticalMargin = 10.0;
+static const CGFloat controlLayerNormalAlpha = 0.75;
+static const CGFloat controlLayerDownAlpha = 0.45;
+
+static NSString * const PDFHUDZoomInControl = @"plus.magnifyingglass";
+static NSString * const PDFHUDZoomOutControl = @"minus.magnifyingglass";
+static NSString * const PDFHUDLaunchPreviewControl = @"preview";
+static NSString * const PDFHUDSavePDFControl = @"arrow.down.circle";
+static NSString * const PDFHUDSeperatorControl = @"PDFHUDSeperatorControl";
+
+static const CGFloat layerFadeInTimeInterval = 0.25;
+static const CGFloat layerFadeOutTimeInterval = 0.5;
+static const CGFloat initialHideTimeInterval = 3.0;
+
+static NSArray<NSString *> *controlArray()
+{
+    return @[
+        PDFHUDZoomOutControl,
+        PDFHUDZoomInControl,
+        PDFHUDSeperatorControl,
+        PDFHUDLaunchPreviewControl,
+        PDFHUDSavePDFControl
+    ];
+}
+
+@implementation WKPDFHUDView {
+@private
+    WeakPtr<WebKit::WebPageProxy> _page;
+    RetainPtr<NSString> _activeControl;
+    WebKit::PDFPluginIdentifier _pluginIdentifier;
+    CGFloat _deviceScaleFactor;
+    RetainPtr<CALayer> _layer;
+    RetainPtr<CALayer> _activeLayer;
+    CGSize _frameSize;
+    RetainPtr<NSMutableDictionary<NSString *, NSImage *>> _cachedIcons;
+    BOOL _visible;
+    BOOL _mouseMovedToHUD;
+    BOOL _initialHideTimerFired;
+}
+
+- (instancetype)initWithFrame:(NSRect)frame pluginIdentifier:(WebKit::PDFPluginIdentifier)pluginIdentifier page:(WebKit::WebPageProxy&)page
+{
+    if (!(self = [super initWithFrame:frame]))
+        return nil;
+    
+    self.wantsLayer = YES;
+    _cachedIcons = adoptNS([[NSMutableDictionary alloc] init]);
+    _pluginIdentifier = pluginIdentifier;
+    _page = makeWeakPtr(page);
+    _deviceScaleFactor = page.deviceScaleFactor();
+    _visible = YES;
+    [self _setupLayer:self.layer];
+    [self setFrame:frame];
+
+    WeakObjCPtr<WKPDFHUDView> weakSelf = self;
+    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(initialHideTimeInterval * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
+        [weakSelf _hideTimerFired];
+    });
+    return self;
+}
+
+- (void)dealloc
+{
+    [_layer removeFromSuperlayer];
+    [super dealloc];
+}
+
+- (void)setFrame:(NSRect)rect
+{
+    [super setFrame:rect];
+    _frameSize = rect.size;
+
+    [CATransaction begin];
+    [CATransaction setDisableActions:YES];
+    CGRect layerBounds = [_layer bounds];
+    [_layer setFrame:CGRectMake(rect.size.width / 2.0 - layerBounds.size.width / 2.0, layerVerticalOffset, layerBounds.size.width, layerBounds.size.height)];
+    [CATransaction commit];
+}
+
+- (void)setDeviceScaleFactor:(CGFloat)deviceScaleFactor
+{
+    if (_deviceScaleFactor == deviceScaleFactor)
+        return;
+    
+    _deviceScaleFactor = deviceScaleFactor;
+    
+    [self _redrawLayer];
+}
+
+- (void)_hideTimerFired
+{
+    _initialHideTimerFired = YES;
+    if (!_mouseMovedToHUD)
+        [self _setVisible:false];
+}
+
+- (void)_setVisible:(bool)isVisible
+{
+    if (_visible == isVisible)
+        return;
+    _visible = isVisible;
+    [CATransaction begin];
+    [CATransaction setAnimationDuration:isVisible ? layerFadeInTimeInterval : layerFadeOutTimeInterval];
+    [self _setLayerOpacity:isVisible ? layerAlpha : 0.0];
+    [CATransaction commit];
+}
+
+- (void)mouseMoved:(NSEvent *)event
+{
+    if (CGRectContainsPoint([self convertRect:CGRectInset([_layer frame], -16.0, -16.0) toView:nil], NSPointToCGPoint(event.locationInWindow))) {
+        [self _setVisible:true];
+        _mouseMovedToHUD = YES;
+    } else if (_initialHideTimerFired)
+        [self _setVisible:false];
+}
+
+- (void)mouseDown:(NSEvent *)event
+{
+    _activeControl = [self _controlForEvent:event];
+    if ([_activeControl isEqualToString:PDFHUDSeperatorControl])
+        _activeControl = nil;
+    if (_activeControl) {
+        // Update rendering to highlight it..
+        _activeLayer = [self _layerForEvent:event];
+        
+        // Update layer image; do not animate
+        [CATransaction begin];
+        [CATransaction setDisableActions:YES];
+        
+        [_activeLayer setOpacity:controlLayerDownAlpha];
+        
+        [CATransaction commit];
+    }
+}
+
+- (void)mouseUp:(NSEvent *)event
+{
+    if (!_activeControl)
+        return;
+    
+    NSString* mouseUpControl = [self _controlForEvent:event];
+    if ([_activeControl isEqualToString:mouseUpControl])
+        [self _performActionForControl:_activeControl.get()];
+    
+    [CATransaction begin];
+    [CATransaction setDisableActions:YES];
+    [_activeLayer setOpacity:controlLayerNormalAlpha];
+    [CATransaction commit];
+
+    _activeLayer = nil;
+    _activeControl = nil;
+}
+
+- (Optional<NSUInteger>)_controlIndexForEvent:(NSEvent *)event
+{
+    CGPoint initialPoint = NSPointToCGPoint(event.locationInWindow);
+    initialPoint.x -= [_layer frame].origin.x;
+    initialPoint.y -= [_layer frame].origin.y;
+    for (NSUInteger index = 0; index < [_layer sublayers].count; index++) {
+        CALayer *subLayer = [_layer sublayers][index];
+        NSRect windowSpaceRect = [self convertRect:subLayer.frame toView:nil];
+        if (CGRectContainsPoint(windowSpaceRect, initialPoint))
+            return index;
+    }
+    return WTF::nullopt;
+}
+
+- (NSString *)_controlForEvent:(NSEvent *)event
+{
+    if (auto index = [self _controlIndexForEvent:event])
+        return controlArray()[*index];
+    return nil;
+}
+
+- (CALayer *)_layerForEvent:(NSEvent *)event
+{
+    if (auto index = [self _controlIndexForEvent:event])
+        return [_layer sublayers][*index];
+    return nil;
+}
+
+- (void)_performActionForControl:(NSString *)control
+{
+    if (!_visible)
+        return;
+    auto* page = _page.get();
+    if (!page)
+        return;
+    if ([control isEqualToString:PDFHUDZoomInControl])
+        page->pdfZoomIn(_pluginIdentifier);
+    else if ([control isEqualToString:PDFHUDZoomOutControl])
+        page->pdfZoomOut(_pluginIdentifier);
+    else if ([control isEqualToString:PDFHUDSavePDFControl])
+        page->pdfSaveToPDF(_pluginIdentifier);
+    else if ([control isEqualToString:PDFHUDLaunchPreviewControl])
+        page->pdfOpenWithPreview(_pluginIdentifier);
+}
+
+- (void)_loadIconImages
+{
+    for (NSString *controlName in controlArray())
+        [self _getImageForControlName:controlName];
+}
+
+- (void)_setupLayer:(CALayer *)parentLayer
+{
+    _layer = adoptNS([[CALayer alloc] init]);
+    [_layer setCornerRadius:layerCornerRadius];
+    
+    [_layer setBackgroundColor:WebCore::cachedCGColor({ WebCore::SRGBA<float>(layerGrayComponent, layerGrayComponent, layerGrayComponent) })];
+    [self _setLayerOpacity:layerAlpha];
+    
+    [self _loadIconImages];
+    CGFloat minIconImageHeight = std::numeric_limits<CGFloat>::max();
+    for (NSImage *image in [_cachedIcons allValues])
+        minIconImageHeight = std::min(minIconImageHeight, (image.size.height / _deviceScaleFactor));
+    
+    CGFloat dx = layerControllerHorizontalMargin;
+    for (NSString *controlName in controlArray()) {
+        auto controlLayer = adoptNS([[CALayer alloc] init]);
+        CGFloat dy = 0.0;
+        CGFloat controllerWidth = 0.0;
+        CGFloat controllerHeight = 0.0;
+
+        if ([controlName isEqualToString:PDFHUDSeperatorControl]) {
+            dy = layerSeperatorVerticalMargin;
+            controllerWidth = layerSeperatorControllerSize;
+            controllerHeight = minIconImageHeight + (2.0 * layerImageVerticalMargin) - (2.0 * layerSeperatorVerticalMargin);
+            
+            [controlLayer setBackgroundColor:[[NSColor lightGrayColor] CGColor]];
+        } else {
+            NSImage *controlImage = [self _getImageForControlName:controlName];
+            [controlLayer setContents:controlImage];
+            [controlLayer setOpacity:controlLayerNormalAlpha];
+
+            dy = layerImageVerticalMargin;
+            controllerWidth = [controlImage size].width / _deviceScaleFactor;
+            controllerHeight = [controlImage size].height / _deviceScaleFactor;
+            
+            dy -= (controllerHeight - minIconImageHeight) / 2.0;
+            
+            [controlLayer setFilters:@[[CAFilter filterWithType:kCAFilterColorInvert]]];
+        }
+        
+        [controlLayer setFrame:CGRectMake(dx, dy, controllerWidth, controllerHeight)];
+        [_layer addSublayer:controlLayer.get()];
+        
+        dx += controllerWidth + layerControllerHorizontalMargin;
+    }
+    
+    [_layer setFrame:CGRectMake(0, layerVerticalOffset, dx, minIconImageHeight + 2.0 * layerImageVerticalMargin)];
+    [parentLayer addSublayer:_layer.get()];
+}
+
+- (void)_redrawLayer
+{
+    [_cachedIcons removeAllObjects];
+    CALayer *parentLayer = [_layer superlayer];
+    [_layer removeFromSuperlayer];
+    [self _setupLayer:parentLayer];
+    [self setFrameSize:_frameSize];
+}
+
+- (NSImage *)_getImageForControlName:(NSString *)control
+{
+    NSImage *iconImage = _cachedIcons.get()[control];
+    if (iconImage)
+        return iconImage;
+
+    iconImage = [NSImage _imageWithSystemSymbolName:control];
+    if (!iconImage)
+        return nil;
+
+    // This was introduced in rdar://problem/59118412
+    iconImage = [iconImage _imageWithConfiguration:@{
+        NSImageAlternateCriterionFont:[NSFont preferredFontForTextStyle:NSFontTextStyleTitle2 options:@{ }],
+        NSImageAlternateCriterionSymbolScale:@(NSImageSymbolScaleLarge)
+    }];
+        
+    NSRect iconImageRect = NSMakeRect(0, 0, [iconImage size].width * layerImageScale * _deviceScaleFactor, [iconImage size].height * layerImageScale * _deviceScaleFactor);
+    NSImageRep *iconImageRep = [iconImage bestRepresentationForRect:iconImageRect context:nil hints:nil];
+    iconImage = [NSImage imageWithImageRep:iconImageRep];
+    
+    _cachedIcons.get()[control] = iconImage;
+    return iconImage;
+}
+
+- (void)_setLayerOpacity:(CGFloat)alpha
+{
+    [_layer setOpacity:alpha];
+    for (CALayer *subLayer in [_layer sublayers])
+        [subLayer setOpacity:alpha];
+}
+
+@end
+
+#endif // ENABLE(UI_PROCESS_PDF_HUD)

Modified: trunk/Source/WebKit/UIProcess/PageClient.h (266653 => 266654)


--- trunk/Source/WebKit/UIProcess/PageClient.h	2020-09-05 03:52:42 UTC (rev 266653)
+++ trunk/Source/WebKit/UIProcess/PageClient.h	2020-09-05 04:07:47 UTC (rev 266654)
@@ -26,6 +26,7 @@
 #pragma once
 
 #include "LayerTreeContext.h"
+#include "PDFPluginIdentifier.h"
 #include "SameDocumentNavigationType.h"
 #include "ShareableBitmap.h"
 #include "WebColorPicker.h"
@@ -241,6 +242,13 @@
     virtual void didFailProvisionalLoadForMainFrame() { };
     virtual void didCommitLoadForMainFrame(const String& mimeType, bool useCustomContentProvider) = 0;
 
+#if ENABLE(UI_PROCESS_PDF_HUD)
+    virtual void createPDFHUD(PDFPluginIdentifier, const WebCore::IntRect&) = 0;
+    virtual void updatePDFHUDLocation(PDFPluginIdentifier, const WebCore::IntRect&) = 0;
+    virtual void removePDFHUD(PDFPluginIdentifier) = 0;
+    virtual void removeAllPDFHUDs() = 0;
+#endif
+    
     virtual void handleDownloadRequest(DownloadProxy&) = 0;
 
     virtual bool handleRunOpenPanel(WebPageProxy*, WebFrameProxy*, const FrameInfoData&, API::OpenPanelParameters*, WebOpenPanelResultListenerProxy*) { return false; }

Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.cpp (266653 => 266654)


--- trunk/Source/WebKit/UIProcess/WebPageProxy.cpp	2020-09-05 03:52:42 UTC (rev 266653)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.cpp	2020-09-05 04:07:47 UTC (rev 266654)
@@ -4765,15 +4765,14 @@
             m_pluginScaleFactor = 1;
             m_mainFramePluginHandlesPageScaleGesture = false;
         }
-    }
-
 #if ENABLE(POINTER_LOCK)
-    if (frame->isMainFrame())
         requestPointerUnlock();
 #endif
-
-    if (frame->isMainFrame())
         pageClient().setMouseEventPolicy(mouseEventPolicy);
+#if ENABLE(UI_PROCESS_PDF_HUD)
+        pageClient().removeAllPDFHUDs();
+#endif
+    }
 
     m_pageLoadState.commitChanges();
     if (m_loaderClient)
@@ -7446,6 +7445,9 @@
 
     resetStateAfterProcessExited(reason);
     stopAllURLSchemeTasks(m_process.ptr());
+#if ENABLE(UI_PROCESS_PDF_HUD)
+    pageClient().removeAllPDFHUDs();
+#endif
 
     // For bringup of process swapping, NavigationSwap termination will not go out to clients.
     // If it does *during* process swapping, and the client triggers a reload, that causes bizarre WebKit re-entry.

Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.h (266653 => 266654)


--- trunk/Source/WebKit/UIProcess/WebPageProxy.h	2020-09-05 03:52:42 UTC (rev 266653)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.h	2020-09-05 04:07:47 UTC (rev 266654)
@@ -40,6 +40,7 @@
 #include "LayerTreeContext.h"
 #include "MessageSender.h"
 #include "NotificationPermissionRequestManagerProxy.h"
+#include "PDFPluginIdentifier.h"
 #include "PageLoadState.h"
 #include "PluginProcessAttributes.h"
 #include "PolicyDecision.h"
@@ -1317,10 +1318,12 @@
 
     void saveDataToFileInDownloadsFolder(String&& suggestedFilename, String&& mimeType, URL&& originatingURL, API::Data&);
     void savePDFToFileInDownloadsFolder(String&& suggestedFilename, URL&& originatingURL, const IPC::DataReference&);
-#if PLATFORM(COCOA)
+#if ENABLE(PDFKIT_PLUGIN)
     void savePDFToTemporaryFolderAndOpenWithNativeApplication(const String& suggestedFilename, FrameInfoData&&, const IPC::DataReference&, const String& pdfUUID);
+#if !ENABLE(UI_PROCESS_PDF_HUD)
     void openPDFFromTemporaryFolderWithNativeApplication(FrameInfoData&&, const String& pdfUUID);
 #endif
+#endif
 
 #if ENABLE(PDFKIT_PLUGIN)
     void showPDFContextMenu(const WebKit::PDFContextMenu&, CompletionHandler<void(Optional<int32_t>&&)>&&);
@@ -1808,6 +1811,16 @@
     bool canUseCredentialStorage() { return m_canUseCredentialStorage; }
     void setCanUseCredentialStorage(bool);
 
+#if ENABLE(UI_PROCESS_PDF_HUD)
+    void createPDFHUD(PDFPluginIdentifier, const WebCore::IntRect&);
+    void updatePDFHUDLocation(PDFPluginIdentifier, const WebCore::IntRect&);
+    void removePDFHUD(PDFPluginIdentifier);
+    void pdfZoomIn(PDFPluginIdentifier);
+    void pdfZoomOut(PDFPluginIdentifier);
+    void pdfSaveToPDF(PDFPluginIdentifier);
+    void pdfOpenWithPreview(PDFPluginIdentifier);
+#endif
+
 private:
     WebPageProxy(PageClient&, WebProcessProxy&, Ref<API::PageConfiguration>&&);
     void platformInitialize();

Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.messages.in (266653 => 266654)


--- trunk/Source/WebKit/UIProcess/WebPageProxy.messages.in	2020-09-05 03:52:42 UTC (rev 266653)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.messages.in	2020-09-05 04:07:47 UTC (rev 266654)
@@ -433,9 +433,8 @@
     SaveRecentSearches(String name, Vector<WebCore::RecentSearch> searchItems)
     LoadRecentSearches(String name) -> (Vector<WebCore::RecentSearch> result) Synchronous
 
+#if ENABLE(PDFKIT_PLUGIN) && !ENABLE(UI_PROCESS_PDF_HUD)
     SavePDFToFileInDownloadsFolder(String suggestedFilename, URL originatingURL, IPC::DataReference data)
-
-#if PLATFORM(COCOA)
     SavePDFToTemporaryFolderAndOpenWithNativeApplication(String suggestedFilename, struct WebKit::FrameInfoData sourceFrameInfo, IPC::DataReference data, String pdfUUID)
     OpenPDFFromTemporaryFolderWithNativeApplication(struct WebKit::FrameInfoData sourceFrameInfo, String pdfUUID)
 #endif
@@ -566,6 +565,12 @@
     SpeechSynthesisResume() -> () Async
 #endif
 
+#if ENABLE(UI_PROCESS_PDF_HUD)
+    CreatePDFHUD(WebKit::PDFPluginIdentifier identifier, WebCore::IntRect boundingBox)
+    UpdatePDFHUDLocation(WebKit::PDFPluginIdentifier identifier, WebCore::IntRect boundingBox)
+    RemovePDFHUD(WebKit::PDFPluginIdentifier identifier)
+#endif
+
     ConfigureLoggingChannel(String channelName, enum:uint8_t WTFLogChannelState state, enum:uint8_t WTFLogLevel level)
 
 #if PLATFORM(GTK)

Modified: trunk/Source/WebKit/UIProcess/ios/WebPageProxyIOS.mm (266653 => 266654)


--- trunk/Source/WebKit/UIProcess/ios/WebPageProxyIOS.mm	2020-09-05 03:52:42 UTC (rev 266653)
+++ trunk/Source/WebKit/UIProcess/ios/WebPageProxyIOS.mm	2020-09-05 04:07:47 UTC (rev 266654)
@@ -1088,16 +1088,6 @@
     pageClient().didPerformDictionaryLookup(dictionaryPopupInfo);
 }
 
-void WebPageProxy::savePDFToTemporaryFolderAndOpenWithNativeApplication(const String&, FrameInfoData&&, const IPC::DataReference&, const String&)
-{
-    notImplemented();
-}
-
-void WebPageProxy::openPDFFromTemporaryFolderWithNativeApplication(FrameInfoData&&, const String&)
-{
-    notImplemented();
-}
-
 void WebPageProxy::setRemoteLayerTreeRootNode(RemoteLayerTreeNode* rootNode)
 {
     pageClient().setRemoteLayerTreeRootNode(rootNode);

Modified: trunk/Source/WebKit/UIProcess/mac/PageClientImplMac.h (266653 => 266654)


--- trunk/Source/WebKit/UIProcess/mac/PageClientImplMac.h	2020-09-05 03:52:42 UTC (rev 266653)
+++ trunk/Source/WebKit/UIProcess/mac/PageClientImplMac.h	2020-09-05 04:07:47 UTC (rev 266654)
@@ -190,6 +190,13 @@
 
     void registerInsertionUndoGrouping() override;
 
+#if ENABLE(UI_PROCESS_PDF_HUD)
+    void createPDFHUD(PDFPluginIdentifier, const WebCore::IntRect&) override;
+    void updatePDFHUDLocation(PDFPluginIdentifier, const WebCore::IntRect&) override;
+    void removePDFHUD(PDFPluginIdentifier) override;
+    void removeAllPDFHUDs() override;
+#endif
+
     // Auxiliary Client Creation
 #if ENABLE(FULLSCREEN_API)
     WebFullScreenManagerProxyClient& fullScreenManagerProxyClient() override;

Modified: trunk/Source/WebKit/UIProcess/mac/PageClientImplMac.mm (266653 => 266654)


--- trunk/Source/WebKit/UIProcess/mac/PageClientImplMac.mm	2020-09-05 03:52:42 UTC (rev 266653)
+++ trunk/Source/WebKit/UIProcess/mac/PageClientImplMac.mm	2020-09-05 04:07:47 UTC (rev 266654)
@@ -349,6 +349,30 @@
     registerInsertionUndoGroupingWithUndoManager([m_view undoManager]);
 }
 
+#if ENABLE(UI_PROCESS_PDF_HUD)
+
+void PageClientImpl::createPDFHUD(PDFPluginIdentifier identifier, const WebCore::IntRect& rect)
+{
+    m_impl->createPDFHUD(identifier, rect);
+}
+
+void PageClientImpl::updatePDFHUDLocation(PDFPluginIdentifier identifier, const WebCore::IntRect& rect)
+{
+    m_impl->updatePDFHUDLocation(identifier, rect);
+}
+
+void PageClientImpl::removePDFHUD(PDFPluginIdentifier identifier)
+{
+    m_impl->removePDFHUD(identifier);
+}
+
+void PageClientImpl::removeAllPDFHUDs()
+{
+    m_impl->removeAllPDFHUDs();
+}
+
+#endif // ENABLE(UI_PROCESS_PDF_HUD)
+
 void PageClientImpl::clearAllEditCommands()
 {
     m_impl->clearAllEditCommands();

Modified: trunk/Source/WebKit/UIProcess/mac/WebPageProxyMac.mm (266653 => 266654)


--- trunk/Source/WebKit/UIProcess/mac/WebPageProxyMac.mm	2020-09-05 03:52:42 UTC (rev 266653)
+++ trunk/Source/WebKit/UIProcess/mac/WebPageProxyMac.mm	2020-09-05 04:07:47 UTC (rev 266654)
@@ -480,8 +480,6 @@
 
 void WebPageProxy::savePDFToTemporaryFolderAndOpenWithNativeApplication(const String& suggestedFilename, FrameInfoData&& frameInfo, const IPC::DataReference& data, const String& pdfUUID)
 {
-    MESSAGE_CHECK(TemporaryPDFFileMap::isValidKey(pdfUUID));
-
     if (data.isEmpty()) {
         WTFLogAlways("Cannot save empty PDF file to the temporary directory.");
         return;
@@ -509,7 +507,8 @@
     auto originatingURLString = frameInfo.request.url().string();
     FileSystem::setMetadataURL(nsPath.get(), originatingURLString);
 
-    m_temporaryPDFFiles.add(pdfUUID, nsPath.get());
+    if (TemporaryPDFFileMap::isValidKey(pdfUUID))
+        m_temporaryPDFFiles.add(pdfUUID, nsPath.get());
 
     auto pdfFileURL = URL::fileURLWithFileSystemPath(String(nsPath.get()));
     m_uiClient->confirmPDFOpening(*this, pdfFileURL, WTFMove(frameInfo), [pdfFileURL] (bool allowed) {
@@ -519,6 +518,7 @@
     });
 }
 
+#if ENABLE(PDFKIT_PLUGIN) && !ENABLE(UI_PROCESS_PDF_HUD)
 void WebPageProxy::openPDFFromTemporaryFolderWithNativeApplication(FrameInfoData&& frameInfo, const String& pdfUUID)
 {
     MESSAGE_CHECK(TemporaryPDFFileMap::isValidKey(pdfUUID));
@@ -535,6 +535,7 @@
         [[NSWorkspace sharedWorkspace] openURL:pdfFileURL];
     });
 }
+#endif
 
 #if ENABLE(PDFKIT_PLUGIN)
 void WebPageProxy::showPDFContextMenu(const WebKit::PDFContextMenu& contextMenu, CompletionHandler<void(Optional<int32_t>&&)>&& completionHandler)
@@ -678,6 +679,49 @@
     return [pageClient().platformWindow() contentView];
 }
 
+#if ENABLE(UI_PROCESS_PDF_HUD)
+
+void WebPageProxy::createPDFHUD(PDFPluginIdentifier identifier, const WebCore::IntRect& rect)
+{
+    pageClient().createPDFHUD(identifier, rect);
+}
+
+void WebPageProxy::removePDFHUD(PDFPluginIdentifier identifier)
+{
+    pageClient().removePDFHUD(identifier);
+}
+
+void WebPageProxy::updatePDFHUDLocation(PDFPluginIdentifier identifier, const WebCore::IntRect& rect)
+{
+    pageClient().updatePDFHUDLocation(identifier, rect);
+}
+
+void WebPageProxy::pdfZoomIn(PDFPluginIdentifier identifier)
+{
+    send(Messages::WebPage::ZoomPDFIn(identifier));
+}
+
+void WebPageProxy::pdfZoomOut(PDFPluginIdentifier identifier)
+{
+    send(Messages::WebPage::ZoomPDFOut(identifier));
+}
+
+void WebPageProxy::pdfSaveToPDF(PDFPluginIdentifier identifier)
+{
+    sendWithAsyncReply(Messages::WebPage::SavePDF(identifier), [this, protectedThis = makeRef(*this)] (String&& suggestedFilename, URL&& originatingURL, const IPC::DataReference& dataReference) {
+        savePDFToFileInDownloadsFolder(WTFMove(suggestedFilename), WTFMove(originatingURL), dataReference);
+    });
+}
+
+void WebPageProxy::pdfOpenWithPreview(PDFPluginIdentifier identifier)
+{
+    sendWithAsyncReply(Messages::WebPage::OpenPDFWithPreview(identifier), [this, protectedThis = makeRef(*this)] (String&& suggestedFilename, FrameInfoData&& frameInfo, const IPC::DataReference& data, const String& pdfUUID) {
+        savePDFToTemporaryFolderAndOpenWithNativeApplication(WTFMove(suggestedFilename), WTFMove(frameInfo), data, pdfUUID);
+    });
+}
+
+#endif // ENABLE(UI_PROCESS_PDF_HUD)
+
 } // namespace WebKit
 
 #endif // PLATFORM(MAC)

Modified: trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj (266653 => 266654)


--- trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj	2020-09-05 03:52:42 UTC (rev 266653)
+++ trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj	2020-09-05 04:07:47 UTC (rev 266654)
@@ -1786,6 +1786,7 @@
 		D3B9484911FF4B6500032B39 /* WebSearchPopupMenu.h in Headers */ = {isa = PBXBuildFile; fileRef = D3B9484511FF4B6500032B39 /* WebSearchPopupMenu.h */; };
 		DF462E0F23F22F5500EFF35F /* WKHTTPCookieStorePrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = DF462E0E23F22F5300EFF35F /* WKHTTPCookieStorePrivate.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		DF462E1223F338BE00EFF35F /* WKContentWorldPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = DF462E1123F338AD00EFF35F /* WKContentWorldPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		DF84CEE4249AA24D009096F6 /* WKPDFHUDView.mm in Sources */ = {isa = PBXBuildFile; fileRef = DF84CEE2249AA21F009096F6 /* WKPDFHUDView.mm */; };
 		E105FE5418D7B9DE008F57A8 /* EditingRange.h in Headers */ = {isa = PBXBuildFile; fileRef = E105FE5318D7B9DE008F57A8 /* EditingRange.h */; };
 		E11D35AE16B63D1B006D23D7 /* com.apple.WebProcess.sb in Resources */ = {isa = PBXBuildFile; fileRef = E1967E37150AB5E200C73169 /* com.apple.WebProcess.sb */; };
 		E14A954A16E016A40068DE82 /* NetworkProcessPlatformStrategies.h in Headers */ = {isa = PBXBuildFile; fileRef = E14A954816E016A40068DE82 /* NetworkProcessPlatformStrategies.h */; };
@@ -5264,6 +5265,9 @@
 		DF462E1123F338AD00EFF35F /* WKContentWorldPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKContentWorldPrivate.h; sourceTree = "<group>"; };
 		DF58C6311371AC5800F9A37C /* NativeWebWheelEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NativeWebWheelEvent.h; sourceTree = "<group>"; };
 		DF58C6351371ACA000F9A37C /* NativeWebWheelEventMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = NativeWebWheelEventMac.mm; sourceTree = "<group>"; };
+		DF74275C24F4955000F8ABE9 /* PDFPluginIdentifier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PDFPluginIdentifier.h; sourceTree = "<group>"; };
+		DF84CEE2249AA21F009096F6 /* WKPDFHUDView.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = WKPDFHUDView.mm; path = PDF/WKPDFHUDView.mm; sourceTree = "<group>"; };
+		DF84CEE3249AA21F009096F6 /* WKPDFHUDView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WKPDFHUDView.h; path = PDF/WKPDFHUDView.h; sourceTree = "<group>"; };
 		E105FE5318D7B9DE008F57A8 /* EditingRange.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EditingRange.h; sourceTree = "<group>"; };
 		E115C715190F8A2500ECC516 /* com.apple.WebKit.Storage.sb */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = com.apple.WebKit.Storage.sb; path = DerivedSources/WebKit2/com.apple.WebKit.Storage.sb; sourceTree = BUILT_PRODUCTS_DIR; };
 		E133FD891423DD7F00FC7BFB /* WebKit.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; name = WebKit.icns; path = Resources/WebKit.icns; sourceTree = "<group>"; };
@@ -5885,6 +5889,7 @@
 			children = (
 				1A6FB90811E66FB100DB1371 /* Netscape */,
 				E199875B142BF9CF00BB2DE7 /* PDF */,
+				DF74275C24F4955000F8ABE9 /* PDFPluginIdentifier.h */,
 				1A6FB7D011E651E200DB1371 /* Plugin.cpp */,
 				1A6FB7D111E651E200DB1371 /* Plugin.h */,
 				1AA56F2811E92BC80061B882 /* PluginController.h */,
@@ -8938,6 +8943,7 @@
 				CD4570D82444CA1700A3DCEB /* Media */,
 				510CC7E716138E7200D03ED3 /* Network */,
 				31A2EC401489973700810D71 /* Notifications */,
+				DF84CEE1249AA200009096F6 /* PDF */,
 				1AEFCC0511D01F34008219D3 /* Plugins */,
 				2D1551A91F5A9B420006E3FE /* RemoteLayerTree */,
 				1AAF089E192681AC00B6390C /* UserContent */,
@@ -10425,6 +10431,15 @@
 			path = ios;
 			sourceTree = "<group>";
 		};
+		DF84CEE1249AA200009096F6 /* PDF */ = {
+			isa = PBXGroup;
+			children = (
+				DF84CEE3249AA21F009096F6 /* WKPDFHUDView.h */,
+				DF84CEE2249AA21F009096F6 /* WKPDFHUDView.mm */,
+			);
+			name = PDF;
+			sourceTree = "<group>";
+		};
 		E170876D16D6CA7200F99226 /* FileAPI */ = {
 			isa = PBXGroup;
 			children = (
@@ -13112,6 +13127,7 @@
 				637281A321ADC744009E0DE6 /* WKDownloadProgress.mm in Sources */,
 				5CE9120D2293C219005BEC78 /* WKMain.mm in Sources */,
 				4657D88A22664A2F005DE823 /* WKOrientationAccessAlert.mm in Sources */,
+				DF84CEE4249AA24D009096F6 /* WKPDFHUDView.mm in Sources */,
 				5CA26D83217AD1B800F97A35 /* WKSafeBrowsingWarning.mm in Sources */,
 				1DB01944211CF005009FB3E8 /* WKShareSheet.mm in Sources */,
 				7A78FF332241919B0096483E /* WKStorageAccessAlert.mm in Sources */,

Modified: trunk/Source/WebKit/WebProcess/Plugins/PDF/PDFLayerControllerSPI.h (266653 => 266654)


--- trunk/Source/WebKit/WebProcess/Plugins/PDF/PDFLayerControllerSPI.h	2020-09-05 03:52:42 UTC (rev 266653)
+++ trunk/Source/WebKit/WebProcess/Plugins/PDF/PDFLayerControllerSPI.h	2020-09-05 04:07:47 UTC (rev 266654)
@@ -87,6 +87,12 @@
 
 - (void)snapshotInContext:(CGContextRef)context;
 
+#if ENABLE(UI_PROCESS_PDF_HUD)
+- (void)setDisplaysPDFHUDController:(BOOL)displaysController;
+- (void)zoomIn:(id)atPoint;
+- (void)zoomOut:(id)atPoint;
+#endif
+
 - (void)magnifyWithMagnification:(CGFloat)magnification atPoint:(CGPoint)point immediately:(BOOL)immediately;
 
 - (CGPoint)scrollPosition;

Modified: trunk/Source/WebKit/WebProcess/Plugins/PDF/PDFPlugin.h (266653 => 266654)


--- trunk/Source/WebKit/WebProcess/Plugins/PDF/PDFPlugin.h	2020-09-05 03:52:42 UTC (rev 266653)
+++ trunk/Source/WebKit/WebProcess/Plugins/PDF/PDFPlugin.h	2020-09-05 04:07:47 UTC (rev 266654)
@@ -28,6 +28,7 @@
 #if ENABLE(PDFKIT_PLUGIN)
 
 #include "PDFKitImports.h"
+#include "PDFPluginIdentifier.h"
 #include "Plugin.h"
 #include "WebEvent.h"
 #include "WebHitTestResultData.h"
@@ -50,6 +51,7 @@
 OBJC_CLASS NSArray;
 OBJC_CLASS NSAttributedString;
 OBJC_CLASS NSData;
+OBJC_CLASS NSEvent;
 OBJC_CLASS NSString;
 OBJC_CLASS PDFAnnotation;
 OBJC_CLASS PDFLayerController;
@@ -77,8 +79,9 @@
 class PDFPluginPasswordField;
 class PluginView;
 class WebFrame;
+struct FrameInfoData;
 
-class PDFPlugin final : public Plugin, private WebCore::ScrollableArea
+class PDFPlugin final : public Plugin, public WebCore::ScrollableArea
 #if HAVE(INCREMENTAL_PDF_APIS)
     , private WebCore::NetscapePlugInStreamLoaderClient
 #endif
@@ -103,9 +106,19 @@
     void notifySelectionChanged(PDFSelection *);
     void notifyCursorChanged(uint64_t /* PDFLayerControllerCursorType */);
 
+#if ENABLE(UI_PROCESS_PDF_HUD)
+    void zoomIn();
+    void zoomOut();
+    void save(CompletionHandler<void(const String&, const URL&, const IPC::DataReference&)>&&);
+    void openWithPreview(CompletionHandler<void(const String&, FrameInfoData&&, const IPC::DataReference&, const String&)>&&);
+    PDFPluginIdentifier identifier() const { return m_identifier; }
+#endif
+
     void clickedLink(NSURL *);
+#if !ENABLE(UI_PROCESS_PDF_HUD)
     void saveToPDF();
     void openWithNativeApplication();
+#endif
     void writeItemsToPasteboard(NSString *pasteboardName, NSArray *items, NSArray *types);
     void showDefinitionForAttributedString(NSAttributedString *, CGPoint);
     void performWebSearch(NSString *);
@@ -118,7 +131,10 @@
 
     WebCore::FloatRect convertFromPDFViewToScreen(const WebCore::FloatRect&) const;
     WebCore::IntPoint convertFromRootViewToPDFView(const WebCore::IntPoint&) const;
+    WebCore::IntPoint convertFromPDFViewToRootView(const WebCore::IntPoint&) const;
+    WebCore::IntRect convertFromPDFViewToRootView(const WebCore::IntRect&) const;
     WebCore::IntRect boundsOnScreen() const;
+    WebCore::IntRect frameForHUD() const;
 
     bool showContextMenuAtPoint(const WebCore::IntPoint&);
 
@@ -159,7 +175,7 @@
     bool wantsWheelEvents() final { return true; }
     void geometryDidChange(const WebCore::IntSize& pluginSize, const WebCore::IntRect& clipRect, const WebCore::AffineTransform& pluginToRootViewTransform) final;
     void contentsScaleFactorChanged(float) final;
-    void visibilityDidChange(bool) final { }
+    void visibilityDidChange(bool) final;
     void frameDidFinishLoading(uint64_t requestID) final;
     void frameDidFail(uint64_t requestID, bool wasCancelled) final;
     void didEvaluateJavaScript(uint64_t requestID, const String& result) final;
@@ -263,7 +279,6 @@
     NSEvent *nsEventForWebMouseEvent(const WebMouseEvent&);
     WebCore::IntPoint convertFromPluginToPDFView(const WebCore::IntPoint&) const;
     WebCore::IntPoint convertFromRootViewToPlugin(const WebCore::IntPoint&) const;
-    WebCore::IntPoint convertFromPDFViewToRootView(const WebCore::IntPoint&) const;
     
     bool supportsForms();
     bool isFullFramePlugin() const;
@@ -403,6 +418,9 @@
 #endif
 
 #endif // HAVE(INCREMENTAL_PDF_APIS)
+#if ENABLE(UI_PROCESS_PDF_HUD)
+    PDFPluginIdentifier m_identifier;
+#endif
 };
 
 } // namespace WebKit

Modified: trunk/Source/WebKit/WebProcess/Plugins/PDF/PDFPlugin.mm (266653 => 266654)


--- trunk/Source/WebKit/WebProcess/Plugins/PDF/PDFPlugin.mm	2020-09-05 03:52:42 UTC (rev 266653)
+++ trunk/Source/WebKit/WebProcess/Plugins/PDF/PDFPlugin.mm	2020-09-05 04:07:47 UTC (rev 266654)
@@ -433,12 +433,16 @@
 
 - (void)openWithNativeApplication
 {
+#if !ENABLE(UI_PROCESS_PDF_HUD)
     _pdfPlugin->openWithNativeApplication();
+#endif
 }
 
 - (void)saveToPDF
 {
+#if !ENABLE(UI_PROCESS_PDF_HUD)
     _pdfPlugin->saveToPDF();
+#endif
 }
 
 - (void)pdfLayerController:(PDFLayerController *)pdfLayerController clickedLinkWithURL:(NSURL *)url
@@ -600,7 +604,13 @@
 #if HAVE(INCREMENTAL_PDF_APIS)
     , m_incrementalPDFLoadingEnabled(WebCore::RuntimeEnabledFeatures::sharedFeatures().incrementalPDFLoadingEnabled())
 #endif
+#if ENABLE(UI_PROCESS_PDF_HUD)
+    , m_identifier(PDFPluginIdentifier::generate())
+#endif
 {
+#if ENABLE(UI_PROCESS_PDF_HUD)
+    [m_pdfLayerController setDisplaysPDFHUDController:NO];
+#endif
     m_pdfLayerController.get().delegate = m_pdfLayerControllerDelegate.get();
     m_pdfLayerController.get().parentLayer = m_contentLayer.get();
 
@@ -640,6 +650,10 @@
 
 PDFPlugin::~PDFPlugin()
 {
+#if ENABLE(UI_PROCESS_PDF_HUD)
+    if (auto* page = m_frame.page())
+        page->removePDFHUD(*this);
+#endif
 }
 
 #if HAVE(INCREMENTAL_PDF_APIS)
@@ -1780,6 +1794,11 @@
     updatePageAndDeviceScaleFactors();
 }
 
+IntRect PDFPlugin::frameForHUD() const
+{
+    return convertFromPDFViewToRootView(IntRect(IntPoint(), size()));
+}
+
 void PDFPlugin::calculateSizes()
 {
     if ([m_pdfDocument isLocked]) {
@@ -1790,6 +1809,10 @@
 
     m_firstPageHeight = [m_pdfDocument pageCount] ? static_cast<unsigned>(CGCeiling([[m_pdfDocument pageAtIndex:0] boundsForBox:kPDFDisplayBoxCropBox].size.height)) : 0;
     setPDFDocumentSize(IntSize([m_pdfLayerController contentSizeRespectingZoom]));
+
+#if ENABLE(UI_PROCESS_PDF_HUD)
+    m_frame.page()->updatePDFHUDLocation(*this, frameForHUD());
+#endif
 }
 
 bool PDFPlugin::initialize(const Parameters& parameters)
@@ -1924,7 +1947,13 @@
     IntPoint pointInPluginCoordinates(point.x(), size().height() - point.y());
     return m_rootViewToPluginTransform.inverse().valueOr(AffineTransform()).mapPoint(pointInPluginCoordinates);
 }
-    
+
+IntRect PDFPlugin::convertFromPDFViewToRootView(const IntRect& rect) const
+{
+    IntRect rectInPluginCoordinates(rect.x(), rect.y(), rect.width(), rect.height());
+    return m_rootViewToPluginTransform.inverse().valueOr(AffineTransform()).mapRect(rectInPluginCoordinates);
+}
+
 IntPoint PDFPlugin::convertFromRootViewToPDFView(const IntPoint& point) const
 {
     IntPoint pointInPluginCoordinates = m_rootViewToPluginTransform.mapPoint(point);
@@ -1955,6 +1984,18 @@
     return frameView->contentsToScreen(enclosingIntRect(rectInRootViewCoordinates));
 }
 
+void PDFPlugin::visibilityDidChange(bool visible)
+{
+#if ENABLE(UI_PROCESS_PDF_HUD)
+    if (visible)
+        m_frame.page()->createPDFHUD(*this, frameForHUD());
+    else
+        m_frame.page()->removePDFHUD(*this);
+#else
+    UNUSED_PARAM(visible);
+#endif
+}
+
 void PDFPlugin::geometryDidChange(const IntSize& pluginSize, const IntRect&, const AffineTransform& pluginToRootViewTransform)
 {
     if (size() == pluginSize && pluginView()->pageScaleFactor() == [m_pdfLayerController contentScaleFactor])
@@ -2400,6 +2441,31 @@
     return true;
 }
 
+#if ENABLE(UI_PROCESS_PDF_HUD)
+
+void PDFPlugin::zoomIn()
+{
+    [m_pdfLayerController zoomIn:nil];
+}
+
+void PDFPlugin::zoomOut()
+{
+    [m_pdfLayerController zoomOut:nil];
+}
+
+void PDFPlugin::save(CompletionHandler<void(const String&, const URL&, const IPC::DataReference&)>&& completionHandler)
+{
+    NSData *data = ""
+    completionHandler(m_suggestedFilename, m_frame.url(), IPC:: DataReference(static_cast<const uint8_t*>(data.bytes), data.length));
+}
+
+void PDFPlugin::openWithPreview(CompletionHandler<void(const String&, FrameInfoData&&, const IPC::DataReference&, const String&)>&& completionHandler)
+{
+    NSData *data = ""
+    completionHandler(m_suggestedFilename, m_frame.info(), IPC:: DataReference { static_cast<const uint8_t*>(data.bytes), data.length }, createCanonicalUUIDString());
+}
+
+#else // ENABLE(UI_PROCESS_PDF_HUD)
     
 void PDFPlugin::saveToPDF()
 {
@@ -2432,6 +2498,8 @@
     m_frame.page()->send(Messages::WebPageProxy::OpenPDFFromTemporaryFolderWithNativeApplication(m_frame.info(), m_temporaryPDFUUID));
 }
 
+#endif // ENABLE(UI_PROCESS_PDF_HUD)
+
 void PDFPlugin::writeItemsToPasteboard(NSString *pasteboardName, NSArray *items, NSArray *types)
 {
     auto pasteboardTypes = makeVector<String>(types);

Copied: trunk/Source/WebKit/WebProcess/Plugins/PDFPluginIdentifier.h (from rev 266653, trunk/Tools/TestWebKitAPI/cocoa/TestUIDelegate.h) (0 => 266654)


--- trunk/Source/WebKit/WebProcess/Plugins/PDFPluginIdentifier.h	                        (rev 0)
+++ trunk/Source/WebKit/WebProcess/Plugins/PDFPluginIdentifier.h	2020-09-05 04:07:47 UTC (rev 266654)
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+#pragma once
+
+#include <wtf/ObjectIdentifier.h>
+
+namespace WebKit {
+
+#if ENABLE(UI_PROCESS_PDF_HUD)
+enum PDFPluginIdentifierType { };
+using PDFPluginIdentifier = ObjectIdentifier<PDFPluginIdentifierType>;
+#endif
+
+}

Modified: trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp (266653 => 266654)


--- trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp	2020-09-05 03:52:42 UTC (rev 266653)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp	2020-09-05 04:07:47 UTC (rev 266654)
@@ -5120,12 +5120,12 @@
 }
 #endif
 
+#if ENABLE(PDFKIT_PLUGIN) && !ENABLE(UI_PROCESS_PDF_HUD)
 void WebPage::savePDFToFileInDownloadsFolder(const String& suggestedFilename, const URL& originatingURL, const uint8_t* data, unsigned long size)
 {
     send(Messages::WebPageProxy::SavePDFToFileInDownloadsFolder(suggestedFilename, originatingURL, IPC::DataReference(data, size)));
 }
 
-#if PLATFORM(COCOA)
 void WebPage::savePDFToTemporaryFolderAndOpenWithNativeApplication(const String& suggestedFilename, FrameInfoData&& frameInfo, const uint8_t* data, unsigned long size, const String& pdfUUID)
 {
     send(Messages::WebPageProxy::SavePDFToTemporaryFolderAndOpenWithNativeApplication(suggestedFilename, frameInfo, IPC::DataReference(data, size), pdfUUID));

Modified: trunk/Source/WebKit/WebProcess/WebPage/WebPage.h (266653 => 266654)


--- trunk/Source/WebKit/WebProcess/WebPage/WebPage.h	2020-09-05 03:52:42 UTC (rev 266653)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebPage.h	2020-09-05 04:07:47 UTC (rev 266654)
@@ -45,6 +45,7 @@
 #include "MessageReceiver.h"
 #include "MessageSender.h"
 #include "OptionalCallbackID.h"
+#include "PDFPluginIdentifier.h"
 #include "Plugin.h"
 #include "PolicyDecision.h"
 #include "SandboxExtension.h"
@@ -345,6 +346,16 @@
 
     void centerSelectionInVisibleArea();
 
+#if ENABLE(UI_PROCESS_PDF_HUD)
+    void createPDFHUD(PDFPlugin&, const WebCore::IntRect&);
+    void updatePDFHUDLocation(PDFPlugin&, const WebCore::IntRect&);
+    void removePDFHUD(PDFPlugin&);
+    void zoomPDFIn(PDFPluginIdentifier);
+    void zoomPDFOut(PDFPluginIdentifier);
+    void savePDF(PDFPluginIdentifier, CompletionHandler<void(const String&, const URL&, const IPC::DataReference&)>&&);
+    void openPDFWithPreview(PDFPluginIdentifier, CompletionHandler<void(const String&, FrameInfoData&&, const IPC::DataReference&, const String&)>&&);
+#endif
+
 #if PLATFORM(COCOA)
     void willCommitLayerTree(RemoteLayerTreeTransaction&);
     void didFlushLayerTreeAtTime(MonotonicTime);
@@ -1073,9 +1084,8 @@
     NSDictionary *dataDetectionContext() const { return m_dataDetectionContext.get(); }
 #endif
 
+#if ENABLE(PDFKIT_PLUGIN) && !ENABLE(UI_PROCESS_PDF_HUD)
     void savePDFToFileInDownloadsFolder(const String& suggestedFilename, const URL& originatingURL, const uint8_t* data, unsigned long size);
-
-#if PLATFORM(COCOA)
     void savePDFToTemporaryFolderAndOpenWithNativeApplication(const String& suggestedFilename, FrameInfoData&&, const uint8_t* data, unsigned long size, const String& pdfUUID);
 #endif
 
@@ -1790,6 +1800,10 @@
 
     WebCore::Color m_underlayColor;
 
+#if ENABLE(UI_PROCESS_PDF_HUD)
+    HashMap<PDFPluginIdentifier, WeakPtr<PDFPlugin>> m_pdfPlugInsWithHUD;
+#endif
+
     bool m_isInRedo { false };
     bool m_isClosed { false };
     bool m_tabToLinks { false };

Modified: trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in (266653 => 266654)


--- trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in	2020-09-05 03:52:42 UTC (rev 266653)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in	2020-09-05 04:07:47 UTC (rev 266654)
@@ -575,6 +575,13 @@
 
     SetDefersLoading(bool defersLoading)
 
+#if ENABLE(UI_PROCESS_PDF_HUD)
+    ZoomPDFIn(WebKit::PDFPluginIdentifier identifier)
+    ZoomPDFOut(WebKit::PDFPluginIdentifier identifier)
+    SavePDF(WebKit::PDFPluginIdentifier identifier) -> (String filename, URL url, IPC::DataReference data) Async
+    OpenPDFWithPreview(WebKit::PDFPluginIdentifier identifier) -> (String filename, struct WebKit::FrameInfoData frameInfo, IPC::DataReference data, String uuid) Async
+#endif
+
     UpdateCurrentModifierState(OptionSet<WebCore::PlatformEvent::Modifier> modifiers)
     SimulateDeviceOrientationChange(double alpha, double beta, double gamma)
 

Modified: trunk/Source/WebKit/WebProcess/WebPage/mac/WebPageMac.mm (266653 => 266654)


--- trunk/Source/WebKit/WebProcess/WebPage/mac/WebPageMac.mm	2020-09-05 03:52:42 UTC (rev 266653)
+++ trunk/Source/WebKit/WebProcess/WebPage/mac/WebPageMac.mm	2020-09-05 04:07:47 UTC (rev 266654)
@@ -33,6 +33,7 @@
 #import "EditingRange.h"
 #import "EditorState.h"
 #import "FontInfo.h"
+#import "FrameInfoData.h"
 #import "InjectedBundleHitTestResult.h"
 #import "PDFKitImports.h"
 #import "PDFPlugin.h"
@@ -1051,8 +1052,63 @@
     [NSApp _setAccentColor:color.isValid() ? WebCore::nsColor(color) : nil];
 }
 
-#endif
+#endif // HAVE(APP_ACCENT_COLORS)
 
+#if ENABLE(UI_PROCESS_PDF_HUD)
+
+void WebPage::zoomPDFIn(PDFPluginIdentifier identifier)
+{
+    auto pdfPlugin = m_pdfPlugInsWithHUD.get(identifier);
+    if (!pdfPlugin)
+        return;
+    pdfPlugin->zoomIn();
+}
+
+void WebPage::zoomPDFOut(PDFPluginIdentifier identifier)
+{
+    auto pdfPlugin = m_pdfPlugInsWithHUD.get(identifier);
+    if (!pdfPlugin)
+        return;
+    pdfPlugin->zoomOut();
+}
+
+void WebPage::savePDF(PDFPluginIdentifier identifier, CompletionHandler<void(const String&, const URL&, const IPC::DataReference&)>&& completionHandler)
+{
+    auto pdfPlugin = m_pdfPlugInsWithHUD.get(identifier);
+    if (!pdfPlugin)
+        return completionHandler({ }, { }, { });
+    pdfPlugin->save(WTFMove(completionHandler));
+}
+
+void WebPage::openPDFWithPreview(PDFPluginIdentifier identifier, CompletionHandler<void(const String&, FrameInfoData&&, const IPC::DataReference&, const String&)>&& completionHandler)
+{
+    auto pdfPlugin = m_pdfPlugInsWithHUD.get(identifier);
+    if (!pdfPlugin)
+        return completionHandler({ }, { }, { }, { });
+    pdfPlugin->openWithPreview(WTFMove(completionHandler));
+}
+
+void WebPage::createPDFHUD(PDFPlugin& plugin, const IntRect& boundingBox)
+{
+    auto addResult = m_pdfPlugInsWithHUD.add(plugin.identifier(), makeWeakPtr(plugin));
+    if (addResult.isNewEntry)
+        send(Messages::WebPageProxy::CreatePDFHUD(plugin.identifier(), boundingBox));
+}
+
+void WebPage::updatePDFHUDLocation(PDFPlugin& plugin, const IntRect& boundingBox)
+{
+    if (m_pdfPlugInsWithHUD.contains(plugin.identifier()))
+        send(Messages::WebPageProxy::UpdatePDFHUDLocation(plugin.identifier(), boundingBox));
+}
+
+void WebPage::removePDFHUD(PDFPlugin& plugin)
+{
+    if (m_pdfPlugInsWithHUD.remove(plugin.identifier()))
+        send(Messages::WebPageProxy::RemovePDFHUD(plugin.identifier()));
+}
+
+#endif // ENABLE(UI_PROCESS_PDF_HUD)
+
 } // namespace WebKit
 
 #endif // PLATFORM(MAC)

Modified: trunk/Tools/ChangeLog (266653 => 266654)


--- trunk/Tools/ChangeLog	2020-09-05 03:52:42 UTC (rev 266653)
+++ trunk/Tools/ChangeLog	2020-09-05 04:07:47 UTC (rev 266654)
@@ -1,3 +1,19 @@
+2020-09-04  Alex Christensen  <[email protected]>
+
+        Move PDF heads-up display to UI process on macOS
+        https://bugs.webkit.org/show_bug.cgi?id=215780
+        <rdar://problem/58715847>
+
+        Reviewed by Tim Horton.
+
+        * TestWebKitAPI/Tests/WebKitCocoa/WKPDFView.mm:
+        (pdfData):
+        (TEST):
+        (checkFrame):
+        * TestWebKitAPI/cocoa/TestUIDelegate.h:
+        * TestWebKitAPI/cocoa/TestUIDelegate.mm:
+        (-[TestUIDelegate _webView:saveDataToFile:suggestedFilename:mimeType:originatingURL:]):
+
 2020-09-04  Jonathan Bedard  <[email protected]>
 
         [webkitcorepy] Add mock Response object

Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/WKPDFView.mm (266653 => 266654)


--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/WKPDFView.mm	2020-09-05 03:52:42 UTC (rev 266653)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/WKPDFView.mm	2020-09-05 04:07:47 UTC (rev 266654)
@@ -30,12 +30,27 @@
 #import "PlatformUtilities.h"
 #import "Test.h"
 #import "TestNavigationDelegate.h"
+#import "TestUIDelegate.h"
+#import "TestURLSchemeHandler.h"
+#import "TestWKWebView.h"
 #import <WebKit/WKWebView.h>
 #import <WebKit/WKWebViewConfigurationPrivate.h>
+#import <WebKit/WKWebViewPrivateForTesting.h>
 #import <wtf/RetainPtr.h>
 
-#if HAVE(PDFKIT) && PLATFORM(IOS)
+#if PLATFORM(MAC)
+#import <Carbon/Carbon.h>
+#endif
 
+#if PLATFORM(IOS) || ENABLE(UI_PROCESS_PDF_HUD)
+static NSData *pdfData()
+{
+    return [NSData dataWithContentsOfURL:[[NSBundle mainBundle] URLForResource:@"test" withExtension:@"pdf" subdirectory:@"TestWebKitAPI.resources"]];
+}
+#endif
+
+#if PLATFORM(IOS)
+
 @interface PDFHostViewController : UIViewController
 + (void)createHostView:(void(^)(id hostViewController))callback forExtensionIdentifier:(NSString *)extensionIdentifier;
 @end
@@ -101,7 +116,7 @@
     RetainPtr<WKWebView> webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
 
     // Load a PDF, so we install a WKPDFView.
-    [webView loadData:[NSData dataWithContentsOfURL:[[NSBundle mainBundle] URLForResource:@"test" withExtension:@"pdf" subdirectory:@"TestWebKitAPI.resources"]] MIMEType:@"application/pdf" characterEncodingName:@"" baseURL:[NSURL URLWithString:@"https://www.apple.com/0"]];
+    [webView loadData:pdfData() MIMEType:@"application/pdf" characterEncodingName:@"" baseURL:[NSURL URLWithString:@"https://www.apple.com/0"]];
     [webView _test_waitForDidFinishNavigation];
 
     // Go into the background and parent the WKWebView.
@@ -132,3 +147,208 @@
 }
 
 #endif
+
+#if ENABLE(UI_PROCESS_PDF_HUD)
+
+static void checkFrame(NSRect frame, CGFloat x, CGFloat y, CGFloat width, CGFloat height)
+{
+    EXPECT_EQ(frame.origin.x, x);
+    EXPECT_EQ(frame.origin.y, y);
+    EXPECT_EQ(frame.size.width, width);
+    EXPECT_EQ(frame.size.height, height);
+}
+
+TEST(PDFHUD, MainResourcePDF)
+{
+    TestWKWebView *webView = [[[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:[[WKWebViewConfiguration new] autorelease]] autorelease];
+    [webView loadData:pdfData() MIMEType:@"application/pdf" characterEncodingName:@"" baseURL:[NSURL URLWithString:@"https://www.apple.com/testPath"]];
+    EXPECT_EQ(webView._pdfHUDs.count, 0u);
+    [webView _test_waitForDidFinishNavigation];
+    EXPECT_EQ(webView._pdfHUDs.count, 1u);
+    checkFrame(webView._pdfHUDs.anyObject.frame, 0, 0, 800, 600);
+    
+    TestUIDelegate *delegate = [[TestUIDelegate new] autorelease];
+    webView.UIDelegate = delegate;
+    __block bool saveRequestReceived = false;
+    delegate.saveDataToFile = ^(WKWebView *webViewFromDelegate, NSData *data, NSString *suggestedFilename, NSString *mimeType, NSURL *originatingURL) {
+        EXPECT_EQ(webView, webViewFromDelegate);
+        EXPECT_TRUE([data isEqualToData:pdfData()]);
+        EXPECT_WK_STREQ(suggestedFilename, "testPath.pdf");
+        EXPECT_WK_STREQ(mimeType, "application/pdf");
+        saveRequestReceived = true;
+    };
+    [[webView _pdfHUDs].anyObject performSelector:NSSelectorFromString(@"_performActionForControl:") withObject:@"arrow.down.circle"];
+    TestWebKitAPI::Util::run(&saveRequestReceived);
+
+    EXPECT_EQ(webView._pdfHUDs.count, 1u);
+    [webView _killWebContentProcess];
+    while (webView._pdfHUDs.count)
+        TestWebKitAPI::Util::spinRunLoop();
+}
+
+TEST(PDFHUD, MoveIFrame)
+{
+    TestURLSchemeHandler *handler = [[TestURLSchemeHandler new] autorelease];
+    handler.startURLSchemeTaskHandler = ^(WKWebView *, id<WKURLSchemeTask> task) {
+        if ([task.request.URL.path isEqualToString:@"/main.html"]) {
+            NSURLResponse *response = [[[NSURLResponse alloc] initWithURL:task.request.URL MIMEType:@"text/html" expectedContentLength:0 textEncodingName:nil] autorelease];
+            const char* html = "<br/><iframe src='' id='pdfframe'></iframe>";
+            [task didReceiveResponse:response];
+            [task didReceiveData:[NSData dataWithBytes:html length:strlen(html)]];
+            [task didFinish];
+        } else {
+            EXPECT_WK_STREQ(task.request.URL.path, "/test.pdf");
+            NSData *data = ""
+            NSURLResponse *response = [[[NSURLResponse alloc] initWithURL:task.request.URL MIMEType:@"application/pdf" expectedContentLength:data.length textEncodingName:nil] autorelease];
+            [task didReceiveResponse:response];
+            [task didReceiveData:data];
+            [task didFinish];
+        }
+    };
+
+    WKWebViewConfiguration *configuration = [[WKWebViewConfiguration new] autorelease];
+    [configuration setURLSchemeHandler:handler forURLScheme:@"test"];
+    TestWKWebView *webView = [[[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration] autorelease];
+    [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"test:///main.html"]]];
+    EXPECT_EQ(webView._pdfHUDs.count, 0u);
+    [webView _test_waitForDidFinishNavigation];
+    EXPECT_EQ(webView._pdfHUDs.count, 1u);
+    checkFrame(webView._pdfHUDs.anyObject.frame, 10, 28, 300, 150);
+
+    [webView evaluateJavaScript:@"pdfframe.width=400" completionHandler:nil];
+    while (webView._pdfHUDs.anyObject.frame.size.width != 400)
+        TestWebKitAPI::Util::spinRunLoop();
+    checkFrame(webView._pdfHUDs.anyObject.frame, 10, 28, 400, 150);
+
+    [webView evaluateJavaScript:@"var frameReference = pdfframe; document.body.removeChild(pdfframe)" completionHandler:nil];
+    while (webView._pdfHUDs.count)
+        TestWebKitAPI::Util::spinRunLoop();
+    [webView evaluateJavaScript:@"document.body.appendChild(frameReference)" completionHandler:nil];
+    while (!webView._pdfHUDs.count)
+        TestWebKitAPI::Util::spinRunLoop();
+    EXPECT_EQ(webView._pdfHUDs.count, 1u);
+    checkFrame(webView._pdfHUDs.anyObject.frame, 0, 0, 0, 0);
+    while (webView._pdfHUDs.anyObject.frame.size.width != 400)
+        TestWebKitAPI::Util::spinRunLoop();
+    EXPECT_EQ(webView._pdfHUDs.count, 1u);
+    checkFrame(webView._pdfHUDs.anyObject.frame, 10, 28, 400, 150);
+
+    webView.pageZoom = 1.4;
+    while (webView._pdfHUDs.anyObject.frame.size.width != 560)
+        TestWebKitAPI::Util::spinRunLoop();
+    EXPECT_EQ(webView._pdfHUDs.count, 1u);
+    checkFrame(webView._pdfHUDs.anyObject.frame, 14, 40, 560, 210);
+}
+
+TEST(PDFHUD, NestedIFrames)
+{
+    TestURLSchemeHandler *handler = [[TestURLSchemeHandler new] autorelease];
+    handler.startURLSchemeTaskHandler = ^(WKWebView *, id<WKURLSchemeTask> task) {
+        NSURLResponse *htmlResponse = [[[NSURLResponse alloc] initWithURL:task.request.URL MIMEType:@"text/html" expectedContentLength:0 textEncodingName:nil] autorelease];
+        if ([task.request.URL.path isEqualToString:@"/main.html"]) {
+            const char* html = "<iframe src='' id='parentframe'></iframe>";
+            [task didReceiveResponse:htmlResponse];
+            [task didReceiveData:[NSData dataWithBytes:html length:strlen(html)]];
+            [task didFinish];
+        } else if ([task.request.URL.path isEqualToString:@"/frame.html"]) {
+            const char* html = "<iframe src=''></iframe>";
+            [task didReceiveResponse:htmlResponse];
+            [task didReceiveData:[NSData dataWithBytes:html length:strlen(html)]];
+            [task didFinish];
+        } else {
+            EXPECT_WK_STREQ(task.request.URL.path, "/test.pdf");
+            NSData *data = ""
+            NSURLResponse *response = [[[NSURLResponse alloc] initWithURL:task.request.URL MIMEType:@"application/pdf" expectedContentLength:data.length textEncodingName:nil] autorelease];
+            [task didReceiveResponse:response];
+            [task didReceiveData:data];
+            [task didFinish];
+        }
+    };
+
+    WKWebViewConfiguration *configuration = [[WKWebViewConfiguration new] autorelease];
+    [configuration setURLSchemeHandler:handler forURLScheme:@"test"];
+    TestWKWebView *webView = [[[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration] autorelease];
+    [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"test:///main.html"]]];
+    EXPECT_EQ(webView._pdfHUDs.count, 0u);
+    [webView _test_waitForDidFinishNavigation];
+    EXPECT_EQ(webView._pdfHUDs.count, 1u);
+    checkFrame(webView._pdfHUDs.anyObject.frame, 20, 20, 300, 150);
+    
+    [webView evaluateJavaScript:@"document.body.removeChild(parentframe)" completionHandler:nil];
+    while (webView._pdfHUDs.count)
+        TestWebKitAPI::Util::spinRunLoop();
+}
+
+TEST(PDFHUD, IFrame3DTransform)
+{
+    TestURLSchemeHandler *handler = [[TestURLSchemeHandler new] autorelease];
+    handler.startURLSchemeTaskHandler = ^(WKWebView *, id<WKURLSchemeTask> task) {
+        NSURLResponse *htmlResponse = [[[NSURLResponse alloc] initWithURL:task.request.URL MIMEType:@"text/html" expectedContentLength:0 textEncodingName:nil] autorelease];
+        if ([task.request.URL.path isEqualToString:@"/main.html"]) {
+            const char* html = "<iframe src='' height=500 width=500 style='transform:rotateY(235deg);'></iframe>";
+            [task didReceiveResponse:htmlResponse];
+            [task didReceiveData:[NSData dataWithBytes:html length:strlen(html)]];
+            [task didFinish];
+        } else {
+            EXPECT_WK_STREQ(task.request.URL.path, "/test.pdf");
+            NSData *data = ""
+            NSURLResponse *response = [[[NSURLResponse alloc] initWithURL:task.request.URL MIMEType:@"application/pdf" expectedContentLength:data.length textEncodingName:nil] autorelease];
+            [task didReceiveResponse:response];
+            [task didReceiveData:data];
+            [task didFinish];
+        }
+    };
+
+    WKWebViewConfiguration *configuration = [[WKWebViewConfiguration new] autorelease];
+    [configuration setURLSchemeHandler:handler forURLScheme:@"test"];
+    TestWKWebView *webView = [[[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration] autorelease];
+    [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"test:///main.html"]]];
+    EXPECT_EQ(webView._pdfHUDs.count, 0u);
+    [webView _test_waitForDidFinishNavigation];
+    EXPECT_EQ(webView._pdfHUDs.count, 1u);
+    checkFrame(webView._pdfHUDs.anyObject.frame, 403, 10, 500, 500);
+}
+
+TEST(PDFHUD, MultipleIFrames)
+{
+    TestURLSchemeHandler *handler = [[TestURLSchemeHandler new] autorelease];
+    handler.startURLSchemeTaskHandler = ^(WKWebView *, id<WKURLSchemeTask> task) {
+        NSURLResponse *htmlResponse = [[[NSURLResponse alloc] initWithURL:task.request.URL MIMEType:@"text/html" expectedContentLength:0 textEncodingName:nil] autorelease];
+        if ([task.request.URL.path isEqualToString:@"/main.html"]) {
+            const char* html = "<iframe src='' height=100 width=150></iframe><iframe src='' height=123 width=134></iframe>";
+            [task didReceiveResponse:htmlResponse];
+            [task didReceiveData:[NSData dataWithBytes:html length:strlen(html)]];
+            [task didFinish];
+        } else {
+            EXPECT_WK_STREQ(task.request.URL.path, "/test.pdf");
+            NSData *data = ""
+            NSURLResponse *response = [[[NSURLResponse alloc] initWithURL:task.request.URL MIMEType:@"application/pdf" expectedContentLength:data.length textEncodingName:nil] autorelease];
+            [task didReceiveResponse:response];
+            [task didReceiveData:data];
+            [task didFinish];
+        }
+    };
+
+    WKWebViewConfiguration *configuration = [[WKWebViewConfiguration new] autorelease];
+    [configuration setURLSchemeHandler:handler forURLScheme:@"test"];
+    TestWKWebView *webView = [[[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration] autorelease];
+    [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"test:///main.html"]]];
+    EXPECT_EQ(webView._pdfHUDs.count, 0u);
+    [webView _test_waitForDidFinishNavigation];
+    EXPECT_EQ(webView._pdfHUDs.count, 2u);
+    bool hadLeftFrame = false;
+    bool hadRightFrame = false;
+    for (NSView *hud in webView._pdfHUDs) {
+        if (hud.frame.origin.x == 10) {
+            checkFrame(hud.frame, 10, 33, 150, 100);
+            hadLeftFrame = true;
+        } else {
+            checkFrame(hud.frame, 164, 10, 134, 123);
+            hadRightFrame = true;
+        }
+    }
+    EXPECT_TRUE(hadLeftFrame);
+    EXPECT_TRUE(hadRightFrame);
+}
+
+#endif

Modified: trunk/Tools/TestWebKitAPI/cocoa/TestUIDelegate.h (266653 => 266654)


--- trunk/Tools/TestWebKitAPI/cocoa/TestUIDelegate.h	2020-09-05 03:52:42 UTC (rev 266653)
+++ trunk/Tools/TestWebKitAPI/cocoa/TestUIDelegate.h	2020-09-05 04:07:47 UTC (rev 266654)
@@ -31,6 +31,7 @@
 #if PLATFORM(MAC)
 @property (nonatomic, copy) void (^getContextMenuFromProposedMenu)(NSMenu *, _WKContextMenuElementInfo *, id <NSSecureCoding>, void (^)(NSMenu *));
 #endif
+@property (nonatomic, copy) void (^saveDataToFile)(WKWebView *, NSData *, NSString *, NSString *, NSURL *);
 
 - (NSString *)waitForAlert;
 

Modified: trunk/Tools/TestWebKitAPI/cocoa/TestUIDelegate.mm (266653 => 266654)


--- trunk/Tools/TestWebKitAPI/cocoa/TestUIDelegate.mm	2020-09-05 03:52:42 UTC (rev 266653)
+++ trunk/Tools/TestWebKitAPI/cocoa/TestUIDelegate.mm	2020-09-05 04:07:47 UTC (rev 266654)
@@ -50,6 +50,12 @@
 }
 #endif // PLATFORM(MAC)
 
+- (void)_webView:(WKWebView *)webView saveDataToFile:(NSData *)data suggestedFilename:(NSString *)suggestedFilename mimeType:(NSString *)mimeType originatingURL:(NSURL *)url
+{
+    if (_saveDataToFile)
+        _saveDataToFile(webView, data, suggestedFilename, mimeType, url);
+}
+
 - (NSString *)waitForAlert
 {
     EXPECT_FALSE(self.runJavaScriptAlertPanelWithMessage);
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to