Provide a prototype for AR QuickLook to trigger processing in the originating page
authordino@apple.com <dino@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 13 Sep 2019 21:43:18 +0000 (21:43 +0000)
committerdino@apple.com <dino@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 13 Sep 2019 21:43:18 +0000 (21:43 +0000)
https://bugs.webkit.org/show_bug.cgi?id=201371
<rdar://54904781>

Reviewed by Simon Fraser.

Source/WebCore:

* dom/Document.cpp:
(WebCore::Document::dispatchSystemPreviewActionEvent): Create and dispatch a MessageEvent.
* dom/Document.h:

* html/HTMLAnchorElement.cpp: Send along the page and frame identifiers for this
object to ensure that any reply goes to the correct place.
(WebCore::HTMLAnchorElement::handleClick):

* loader/FrameLoadRequest.h: Use the new SystemPreviewInfo type.
(WebCore::FrameLoadRequest::isSystemPreview const):
(WebCore::FrameLoadRequest::systemPreviewInfo const):
(WebCore::FrameLoadRequest::systemPreviewRect const): Deleted.
* loader/FrameLoader.cpp:
(WebCore::FrameLoader::loadURL):

* loader/FrameLoaderTypes.h: Provide encoders for the type.
(WebCore::SystemPreviewInfo::encode const):
(WebCore::SystemPreviewInfo::decode):

* platform/network/ResourceRequestBase.cpp: Use the new type.
(WebCore::ResourceRequestBase::isSystemPreview const):
(WebCore::ResourceRequestBase::systemPreviewInfo const):
(WebCore::ResourceRequestBase::setSystemPreviewInfo):
(WebCore::ResourceRequestBase::setSystemPreview): Deleted.
(WebCore::ResourceRequestBase::systemPreviewRect const): Deleted.
(WebCore::ResourceRequestBase::setSystemPreviewRect): Deleted.
* platform/network/ResourceRequestBase.h:

* testing/Internals.cpp: Expose the frame and page identifiers to testing.
(WebCore::Internals::frameIdentifier const):
(WebCore::Internals::pageIdentifier const):
* testing/Internals.h:
* testing/Internals.idl:

Source/WebKit:

Provide a way for a Web page to know if an action in the AR scene
was performed, if and only if the system AR library calls a delegate with
particular parameters. Post a message to the originating frame so
the page can detect the action.

* Scripts/webkit/messages.py: Include the right header for SystemPreviewInfo.

* Shared/WebCoreArgumentCoders.cpp: Use SystemPreviewInfo.
(IPC::ArgumentCoder<ResourceRequest>::encode):
(IPC::ArgumentCoder<ResourceRequest>::decode):

* UIProcess/API/Cocoa/WKWebView.mm:
(-[WKWebView _triggerSystemPreviewActionOnFrame:page:]): New helper/test function
to trigger the system preview action.
* UIProcess/API/Cocoa/WKWebViewPrivate.h:

* UIProcess/Cocoa/DownloadClient.mm: Use new type.
(WebKit::DownloadClient::didStart):

* UIProcess/Cocoa/SystemPreviewControllerCocoa.mm: Implement the delegate so that
we can detect an action. When it happens, tell the WebPageProxy to send a message.

* UIProcess/Downloads/DownloadProxy.h: Use SystemPreviewInfo type.
(WebKit::DownloadProxy::systemPreviewDownloadInfo const):
(WebKit::DownloadProxy::systemPreviewDownloadRect const): Deleted.

* UIProcess/SystemPreviewController.h:
(WebKit::SystemPreviewController::previewInfo const):

* UIProcess/WebPageProxy.cpp: Send it over to the Web Process.
(WebKit::WebPageProxy::systemPreviewActionTriggered const):
* UIProcess/WebPageProxy.h:

* WebProcess/WebPage/WebPage.cpp: Check the destination still exists, and then talk
to the Document.
(WebKit::WebPage::systemPreviewActionTriggered):
* WebProcess/WebPage/WebPage.h:
* WebProcess/WebPage/WebPage.messages.in:

Tools:

* TestWebKitAPI/Tools/TestWebKitAPI/Tests/WebKitCocoa/SystemPreview.mm:
* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
* TestWebKitAPI/Tests/WebKitCocoa/system-preview-trigger.html: Added.

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

31 files changed:
Source/WebCore/ChangeLog
Source/WebCore/dom/Document.cpp
Source/WebCore/dom/Document.h
Source/WebCore/html/HTMLAnchorElement.cpp
Source/WebCore/loader/FrameLoadRequest.h
Source/WebCore/loader/FrameLoader.cpp
Source/WebCore/loader/FrameLoaderTypes.h
Source/WebCore/platform/network/ResourceRequestBase.cpp
Source/WebCore/platform/network/ResourceRequestBase.h
Source/WebCore/rendering/RenderImage.cpp
Source/WebCore/testing/Internals.cpp
Source/WebCore/testing/Internals.h
Source/WebCore/testing/Internals.idl
Source/WebKit/ChangeLog
Source/WebKit/Scripts/webkit/messages.py
Source/WebKit/Shared/WebCoreArgumentCoders.cpp
Source/WebKit/UIProcess/API/Cocoa/WKWebView.mm
Source/WebKit/UIProcess/API/Cocoa/WKWebViewPrivate.h
Source/WebKit/UIProcess/Cocoa/DownloadClient.mm
Source/WebKit/UIProcess/Cocoa/SystemPreviewControllerCocoa.mm
Source/WebKit/UIProcess/Downloads/DownloadProxy.h
Source/WebKit/UIProcess/SystemPreviewController.h
Source/WebKit/UIProcess/WebPageProxy.cpp
Source/WebKit/UIProcess/WebPageProxy.h
Source/WebKit/WebProcess/WebPage/WebPage.cpp
Source/WebKit/WebProcess/WebPage/WebPage.h
Source/WebKit/WebProcess/WebPage/WebPage.messages.in
Tools/ChangeLog
Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj
Tools/TestWebKitAPI/Tests/WebKitCocoa/SystemPreview.mm [new file with mode: 0644]
Tools/TestWebKitAPI/Tests/WebKitCocoa/system-preview-trigger.html [new file with mode: 0644]

index bcae1fd..6753d59 100644 (file)
@@ -1,3 +1,45 @@
+2019-09-11  Dean Jackson  <dino@apple.com>
+
+        Provide a prototype for AR QuickLook to trigger processing in the originating page
+        https://bugs.webkit.org/show_bug.cgi?id=201371
+        <rdar://54904781>
+
+        Reviewed by Simon Fraser.
+
+        * dom/Document.cpp:
+        (WebCore::Document::dispatchSystemPreviewActionEvent): Create and dispatch a MessageEvent.
+        * dom/Document.h:
+
+        * html/HTMLAnchorElement.cpp: Send along the page and frame identifiers for this
+        object to ensure that any reply goes to the correct place.
+        (WebCore::HTMLAnchorElement::handleClick):
+
+        * loader/FrameLoadRequest.h: Use the new SystemPreviewInfo type.
+        (WebCore::FrameLoadRequest::isSystemPreview const):
+        (WebCore::FrameLoadRequest::systemPreviewInfo const):
+        (WebCore::FrameLoadRequest::systemPreviewRect const): Deleted.
+        * loader/FrameLoader.cpp:
+        (WebCore::FrameLoader::loadURL):
+
+        * loader/FrameLoaderTypes.h: Provide encoders for the type.
+        (WebCore::SystemPreviewInfo::encode const):
+        (WebCore::SystemPreviewInfo::decode):
+
+        * platform/network/ResourceRequestBase.cpp: Use the new type.
+        (WebCore::ResourceRequestBase::isSystemPreview const):
+        (WebCore::ResourceRequestBase::systemPreviewInfo const):
+        (WebCore::ResourceRequestBase::setSystemPreviewInfo):
+        (WebCore::ResourceRequestBase::setSystemPreview): Deleted.
+        (WebCore::ResourceRequestBase::systemPreviewRect const): Deleted.
+        (WebCore::ResourceRequestBase::setSystemPreviewRect): Deleted.
+        * platform/network/ResourceRequestBase.h:
+
+        * testing/Internals.cpp: Expose the frame and page identifiers to testing.
+        (WebCore::Internals::frameIdentifier const):
+        (WebCore::Internals::pageIdentifier const):
+        * testing/Internals.h:
+        * testing/Internals.idl:
+
 2019-09-13  Chris Dumez  <cdumez@apple.com>
 
         Crash under WebCore::firstPositionInNode()
index 1377b02..f7c8e85 100644 (file)
@@ -8288,4 +8288,14 @@ MessagePortChannelProvider& Document::messagePortChannelProvider()
     return MessagePortChannelProvider::singleton();
 }
 
+#if USE(SYSTEM_PREVIEW)
+void Document::dispatchSystemPreviewActionEvent(const String& message)
+{
+    auto event = MessageEvent::create(message, origin());
+    UserGestureIndicator gestureIndicator(ProcessingUserGesture, this);
+    dispatchWindowEvent(event, domWindow());
+}
+#endif
+
+
 } // namespace WebCore
index 4dbf302..0c91259 100644 (file)
@@ -635,7 +635,7 @@ public:
     WEBCORE_EXPORT AXObjectCache* axObjectCache() const;
     void clearAXObjectCache();
 
-    Optional<PageIdentifier> pageID() const;
+    WEBCORE_EXPORT Optional<PageIdentifier> pageID() const;
     // to get visually ordered hebrew and arabic pages right
     void setVisuallyOrdered();
     bool visuallyOrdered() const { return m_visuallyOrdered; }
@@ -1532,6 +1532,10 @@ public:
 
     MessagePortChannelProvider& messagePortChannelProvider();
 
+#if USE(SYSTEM_PREVIEW)
+    WEBCORE_EXPORT void dispatchSystemPreviewActionEvent(const String& message);
+#endif
+
 protected:
     enum ConstructionFlags { Synthesized = 1, NonRenderedPlaceholder = 1 << 1 };
     Document(PAL::SessionID, Frame*, const URL&, unsigned = DefaultDocumentClass, unsigned constructionFlags = 0);
index d32c738..535e0dc 100644 (file)
@@ -482,11 +482,13 @@ void HTMLAnchorElement::handleClick(Event& event)
 
     SystemPreviewInfo systemPreviewInfo;
 #if USE(SYSTEM_PREVIEW)
-    systemPreviewInfo.isSystemPreview = isSystemPreviewLink() && RuntimeEnabledFeatures::sharedFeatures().systemPreviewEnabled();
+    systemPreviewInfo.isPreview = isSystemPreviewLink() && RuntimeEnabledFeatures::sharedFeatures().systemPreviewEnabled();
 
-    if (systemPreviewInfo.isSystemPreview) {
+    if (systemPreviewInfo.isPreview) {
+        systemPreviewInfo.globalFrameID.frameID = document().frame()->loader().client().frameID().valueOr(FrameIdentifier { });
+        systemPreviewInfo.globalFrameID.pageID = document().frame()->loader().client().pageID().valueOr(PageIdentifier { });
         if (auto* child = firstElementChild())
-            systemPreviewInfo.systemPreviewRect = child->boundsInRootViewSpace();
+            systemPreviewInfo.previewRect = child->boundsInRootViewSpace();
     }
 #endif
 
index 1d81fe4..79a4ba2 100644 (file)
@@ -91,8 +91,8 @@ public:
 
     InitiatedByMainFrame initiatedByMainFrame() const { return m_initiatedByMainFrame; }
 
-    bool isSystemPreview() const { return m_systemPreviewInfo.isSystemPreview; }
-    const IntRect& systemPreviewRect() const { return m_systemPreviewInfo.systemPreviewRect; }
+    bool isSystemPreview() const { return m_systemPreviewInfo.isPreview; }
+    const SystemPreviewInfo& systemPreviewInfo() const { return m_systemPreviewInfo; }
 
     void setIsRequestFromClientOrUserInput() { m_isRequestFromClientOrUserInput = true; }
     bool isRequestFromClientOrUserInput() const { return m_isRequestFromClientOrUserInput; }
index 07f5cea..0402962 100644 (file)
@@ -1414,9 +1414,8 @@ void FrameLoader::loadURL(FrameLoadRequest&& frameLoadRequest, const String& ref
     bool isRedirect = m_quickRedirectComing;
 #if USE(SYSTEM_PREVIEW)
     bool isSystemPreview = frameLoadRequest.isSystemPreview();
-    request.setSystemPreview(isSystemPreview);
     if (isSystemPreview)
-        request.setSystemPreviewRect(frameLoadRequest.systemPreviewRect());
+        request.setSystemPreviewInfo(frameLoadRequest.systemPreviewInfo());
 #endif
     loadWithNavigationAction(request, WTFMove(action), lockHistory, newLoadType, WTFMove(formState), allowNavigationToInvalidURL, frameLoadRequest.downloadAttribute(), [this, isRedirect, sameURL, newLoadType, protectedFrame = makeRef(m_frame), completionHandler = completionHandlerCaller.release()] () mutable {
         if (isRedirect) {
index 3ba1632..5406984 100644 (file)
@@ -28,6 +28,7 @@
 
 #pragma once
 
+#include "GlobalFrameIdentifier.h"
 #include "IntRect.h"
 #include "ProcessIdentifier.h"
 
@@ -185,10 +186,41 @@ enum class AllowNavigationToInvalidURL : bool { No, Yes };
 enum class HasInsecureContent : bool { No, Yes };
 
 struct SystemPreviewInfo {
-    IntRect systemPreviewRect;
-    bool isSystemPreview { false };
+    GlobalFrameIdentifier globalFrameID;
+    IntRect previewRect;
+    bool isPreview { false };
+
+    template<class Encoder> void encode(Encoder&) const;
+    template<class Decoder> static Optional<SystemPreviewInfo> decode(Decoder&);
 };
 
+template<class Encoder>
+void SystemPreviewInfo::encode(Encoder& encoder) const
+{
+    encoder << globalFrameID << previewRect << isPreview;
+}
+
+template<class Decoder>
+Optional<SystemPreviewInfo> SystemPreviewInfo::decode(Decoder& decoder)
+{
+    Optional<GlobalFrameIdentifier> globalFrameID;
+    decoder >> globalFrameID;
+    if (!globalFrameID)
+        return WTF::nullopt;
+
+    Optional<IntRect> previewRect;
+    decoder >> previewRect;
+    if (!previewRect)
+        return WTF::nullopt;
+
+    Optional<bool> isPreview;
+    decoder >> isPreview;
+    if (!isPreview)
+        return WTF::nullopt;
+
+    return { { WTFMove(*globalFrameID), WTFMove(*previewRect), WTFMove(*isPreview) } };
+}
+
 enum class LoadCompletionType : uint8_t {
     Finish,
     Cancel
index 619f084..60fc945 100644 (file)
@@ -603,22 +603,17 @@ void ResourceRequestBase::setHTTPHeaderFields(HTTPHeaderMap headerFields)
 #if USE(SYSTEM_PREVIEW)
 bool ResourceRequestBase::isSystemPreview() const
 {
-    return m_isSystemPreview;
+    return m_systemPreviewInfo.hasValue();
 }
 
-void ResourceRequestBase::setSystemPreview(bool s)
+SystemPreviewInfo ResourceRequestBase::systemPreviewInfo() const
 {
-    m_isSystemPreview = s;
+    return m_systemPreviewInfo.valueOr(SystemPreviewInfo { });
 }
 
-const IntRect& ResourceRequestBase::systemPreviewRect() const
+void ResourceRequestBase::setSystemPreviewInfo(const SystemPreviewInfo& info)
 {
-    return m_systemPreviewRect;
-}
-
-void ResourceRequestBase::setSystemPreviewRect(const IntRect& rect)
-{
-    m_systemPreviewRect = rect;
+    m_systemPreviewInfo = info;
 }
 #endif
 
index 8c04af8..e12f554 100644 (file)
@@ -29,6 +29,7 @@
 #define ResourceRequestBase_h
 
 #include "FormData.h"
+#include "FrameLoaderTypes.h"
 #include "HTTPHeaderMap.h"
 #include "IntRect.h"
 #include "ResourceLoadPriority.h"
@@ -181,10 +182,9 @@ public:
 
 #if USE(SYSTEM_PREVIEW)
     WEBCORE_EXPORT bool isSystemPreview() const;
-    WEBCORE_EXPORT void setSystemPreview(bool);
 
-    WEBCORE_EXPORT const IntRect& systemPreviewRect() const;
-    WEBCORE_EXPORT void setSystemPreviewRect(const IntRect&);
+    WEBCORE_EXPORT SystemPreviewInfo systemPreviewInfo() const;
+    WEBCORE_EXPORT void setSystemPreviewInfo(const SystemPreviewInfo&);
 #endif
 
 #if !PLATFORM(COCOA)
@@ -248,8 +248,7 @@ protected:
     bool m_hiddenFromInspector { false };
     bool m_isTopSite { false };
 #if USE(SYSTEM_PREVIEW)
-    bool m_isSystemPreview { false };
-    IntRect m_systemPreviewRect;
+    Optional<SystemPreviewInfo> m_systemPreviewInfo;
 #endif
 
 private:
index 26aaa03..652dabe 100644 (file)
@@ -641,8 +641,12 @@ ImageDrawResult RenderImage::paintIntoRect(PaintInfo& paintInfo, const FloatRect
         imageResource().cachedImage()->addClientWaitingForAsyncDecoding(*this);
 
 #if USE(SYSTEM_PREVIEW)
-    if (imageElement && imageElement->isSystemPreviewImage() && drawResult == ImageDrawResult::DidDraw && RuntimeEnabledFeatures::sharedFeatures().systemPreviewEnabled())
+    WTFLogAlways("dino> checking for system preview image");
+    if (imageElement && imageElement->isSystemPreviewImage() && drawResult == ImageDrawResult::DidDraw && RuntimeEnabledFeatures::sharedFeatures().systemPreviewEnabled()) {
+        WTFLogAlways("dino> found system preview image");
+
         theme().paintSystemPreviewBadge(*img, paintInfo, rect);
+    }
 #endif
 
     return drawResult;
index f792be8..aa7c140 100644 (file)
@@ -78,6 +78,7 @@
 #include "FormController.h"
 #include "Frame.h"
 #include "FrameLoader.h"
+#include "FrameLoaderClient.h"
 #include "FrameView.h"
 #include "FullscreenManager.h"
 #include "GCObservation.h"
@@ -2483,6 +2484,18 @@ bool Internals::isDocumentAlive(uint64_t documentIdentifier) const
     return Document::allDocumentsMap().contains(makeObjectIdentifier<DocumentIdentifierType>(documentIdentifier));
 }
 
+uint64_t Internals::frameIdentifier(const Document& document) const
+{
+    if (auto* page = document.page())
+        return page->mainFrame().loader().client().frameID().valueOr(FrameIdentifier { }).toUInt64();
+    return 0;
+}
+
+uint64_t Internals::pageIdentifier(const Document& document) const
+{
+    return document.pageID().valueOr(PageIdentifier { }).toUInt64();
+}
+
 bool Internals::isAnyWorkletGlobalScopeAlive() const
 {
 #if ENABLE(CSS_PAINTING_API)
index 2fb98b9..c3d9c38 100644 (file)
@@ -408,6 +408,9 @@ public:
     uint64_t documentIdentifier(const Document&) const;
     bool isDocumentAlive(uint64_t documentIdentifier) const;
 
+    uint64_t frameIdentifier(const Document&) const;
+    uint64_t pageIdentifier(const Document&) const;
+
     bool isAnyWorkletGlobalScopeAlive() const;
 
     String serviceWorkerClientIdentifier(const Document&) const;
index b80b8a6..7df7480 100644 (file)
@@ -717,6 +717,9 @@ enum CompositingPolicy {
     unsigned long long documentIdentifier(Document document);
     boolean isDocumentAlive(unsigned long long documentIdentifier);
 
+    unsigned long long frameIdentifier(Document document);
+    unsigned long long pageIdentifier(Document document);
+
     boolean isAnyWorkletGlobalScopeAlive();
 
     DOMString serviceWorkerClientIdentifier(Document document);
index 9e435c5..47be7d8 100644 (file)
@@ -1,3 +1,50 @@
+2019-09-11  Dean Jackson  <dino@apple.com>
+
+        Provide a prototype for AR QuickLook to trigger processing in the originating page
+        https://bugs.webkit.org/show_bug.cgi?id=201371
+        <rdar://54904781>
+
+        Reviewed by Simon Fraser.
+
+        Provide a way for a Web page to know if an action in the AR scene
+        was performed, if and only if the system AR library calls a delegate with
+        particular parameters. Post a message to the originating frame so
+        the page can detect the action.
+
+        * Scripts/webkit/messages.py: Include the right header for SystemPreviewInfo.
+
+        * Shared/WebCoreArgumentCoders.cpp: Use SystemPreviewInfo.
+        (IPC::ArgumentCoder<ResourceRequest>::encode):
+        (IPC::ArgumentCoder<ResourceRequest>::decode):
+
+        * UIProcess/API/Cocoa/WKWebView.mm:
+        (-[WKWebView _triggerSystemPreviewActionOnFrame:page:]): New helper/test function
+        to trigger the system preview action.
+        * UIProcess/API/Cocoa/WKWebViewPrivate.h:
+
+        * UIProcess/Cocoa/DownloadClient.mm: Use new type.
+        (WebKit::DownloadClient::didStart):
+
+        * UIProcess/Cocoa/SystemPreviewControllerCocoa.mm: Implement the delegate so that
+        we can detect an action. When it happens, tell the WebPageProxy to send a message.
+
+        * UIProcess/Downloads/DownloadProxy.h: Use SystemPreviewInfo type.
+        (WebKit::DownloadProxy::systemPreviewDownloadInfo const):
+        (WebKit::DownloadProxy::systemPreviewDownloadRect const): Deleted.
+
+        * UIProcess/SystemPreviewController.h:
+        (WebKit::SystemPreviewController::previewInfo const):
+
+        * UIProcess/WebPageProxy.cpp: Send it over to the Web Process.
+        (WebKit::WebPageProxy::systemPreviewActionTriggered const):
+        * UIProcess/WebPageProxy.h:
+
+        * WebProcess/WebPage/WebPage.cpp: Check the destination still exists, and then talk
+        to the Document.
+        (WebKit::WebPage::systemPreviewActionTriggered):
+        * WebProcess/WebPage/WebPage.h:
+        * WebProcess/WebPage/WebPage.messages.in:
+
 2019-09-13  Youenn Fablet  <youenn@apple.com>
 
         Partition processes running service workers by session ID
index 56acb65..ec40d43 100644 (file)
@@ -467,6 +467,7 @@ def headers_for_type(type):
         'WebCore::StorageAccessPromptWasShown': ['<WebCore/DocumentStorageAccess.h>'],
         'WebCore::StorageAccessWasGranted': ['<WebCore/DocumentStorageAccess.h>'],
         'WebCore::SupportedPluginIdentifier': ['<WebCore/PluginData.h>'],
+        'WebCore::SystemPreviewInfo': ['<WebCore/FrameLoaderTypes.h>'],
         'WebCore::TextCheckingRequestData': ['<WebCore/TextChecking.h>'],
         'WebCore::TextCheckingResult': ['<WebCore/TextCheckerClient.h>'],
         'WebCore::TextCheckingType': ['<WebCore/TextChecking.h>'],
index 974b52b..2735617 100644 (file)
@@ -1224,7 +1224,7 @@ void ArgumentCoder<ResourceRequest>::encode(Encoder& encoder, const ResourceRequ
 #if USE(SYSTEM_PREVIEW)
     if (resourceRequest.isSystemPreview()) {
         encoder << true;
-        encoder << resourceRequest.systemPreviewRect();
+        encoder << resourceRequest.systemPreviewInfo();
     } else
         encoder << false;
 #endif
@@ -1254,13 +1254,12 @@ bool ArgumentCoder<ResourceRequest>::decode(Decoder& decoder, ResourceRequest& r
     bool isSystemPreview;
     if (!decoder.decode(isSystemPreview))
         return false;
-    resourceRequest.setSystemPreview(isSystemPreview);
 
     if (isSystemPreview) {
-        IntRect systemPreviewRect;
-        if (!decoder.decode(systemPreviewRect))
+        SystemPreviewInfo systemPreviewInfo;
+        if (!decoder.decode(systemPreviewInfo))
             return false;
-        resourceRequest.setSystemPreviewRect(systemPreviewRect);
+        resourceRequest.setSystemPreviewInfo(systemPreviewInfo);
     }
 #endif
 
index 7dca9eb..5fcf83d 100644 (file)
@@ -7468,8 +7468,20 @@ static WebCore::UserInterfaceLayoutDirection toUserInterfaceLayoutDirection(UISe
     WebKit::UserMediaProcessManager::singleton().denyNextUserMediaRequest();
 #endif
 }
-@end
 
+#if PLATFORM(IOS_FAMILY)
+- (void)_triggerSystemPreviewActionOnFrame:(uint64_t)frameID page:(uint64_t)pageID
+{
+#if USE(SYSTEM_PREVIEW)
+    if (_page) {
+        if (auto* previewController = _page->systemPreviewController())
+            previewController->triggerSystemPreviewActionWithTargetForTesting(frameID, pageID);
+    }
+#endif
+}
+#endif
+
+@end
 
 #if ENABLE(FULLSCREEN_API) && PLATFORM(IOS_FAMILY)
 
index 2c6b5cb..cd205d0 100644 (file)
@@ -506,6 +506,8 @@ typedef NS_OPTIONS(NSUInteger, _WKRectEdge) {
 - (void)_accessibilityClearSelection WK_API_AVAILABLE(ios(11.3));
 - (UIView *)_fullScreenPlaceholderView WK_API_AVAILABLE(ios(12.0));
 
+- (void)_triggerSystemPreviewActionOnFrame:(uint64_t)frameID page:(uint64_t)pageID WK_API_AVAILABLE(ios(13.0));
+
 @property (nonatomic, readonly) BOOL _contentViewIsFirstResponder WK_API_AVAILABLE(ios(12.2));
 #else
 - (void)_dismissContentRelativeChildWindows WK_API_AVAILABLE(macos(10.13.4));
index 36ede72..b30d7c6 100644 (file)
@@ -71,7 +71,7 @@ void DownloadClient::didStart(WebProcessPool&, DownloadProxy& downloadProxy)
     if (downloadProxy.isSystemPreviewDownload()) {
         if (auto* webPage = downloadProxy.originatingPage()) {
             // FIXME: Update the MIME-type once it is known in the ResourceResponse.
-            webPage->systemPreviewController()->start(URL(URL(), webPage->currentURL()), "application/octet-stream"_s, downloadProxy.systemPreviewDownloadRect());
+            webPage->systemPreviewController()->start(URL(URL(), webPage->currentURL()), "application/octet-stream"_s, downloadProxy.systemPreviewDownloadInfo());
         }
         takeActivityToken(downloadProxy);
         return;
index 8e01cc5..74ef4c7 100644 (file)
@@ -45,9 +45,13 @@ SOFT_LINK_PRIVATE_FRAMEWORK(ARKit);
 SOFT_LINK_CLASS(ARKit, ARQuickLookPreviewItem);
 SOFT_LINK_PRIVATE_FRAMEWORK(AssetViewer);
 SOFT_LINK_CLASS(AssetViewer, ARQuickLookWebKitItem);
-#endif
 
+@protocol ARQuickLookWebKitItemDelegate;
+
+@interface _WKPreviewControllerDataSource : NSObject <QLPreviewControllerDataSource, ARQuickLookWebKitItemDelegate> {
+#else
 @interface _WKPreviewControllerDataSource : NSObject <QLPreviewControllerDataSource> {
+#endif
     RetainPtr<NSItemProvider> _itemProvider;
 #if HAVE(ARKIT_QUICK_LOOK_PREVIEW_ITEM)
     RetainPtr<ARQuickLookWebKitItem> _item;
@@ -56,6 +60,7 @@ SOFT_LINK_CLASS(AssetViewer, ARQuickLookWebKitItem);
 #endif
     URL _originatingPageURL;
     URL _downloadedURL;
+    WebKit::SystemPreviewController* _previewController;
 };
 
 @property (strong) NSItemProviderCompletionHandler completionHandler;
@@ -65,11 +70,12 @@ SOFT_LINK_CLASS(AssetViewer, ARQuickLookWebKitItem);
 
 @implementation _WKPreviewControllerDataSource
 
-- (instancetype)initWithMIMEType:(NSString*)mimeType originatingPageURL:(URL)url
+- (instancetype)initWithSystemPreviewController:(WebKit::SystemPreviewController*)previewController MIMEType:(NSString*)mimeType originatingPageURL:(URL)url
 {
     if (!(self = [super init]))
         return nil;
 
+    _previewController = previewController;
     _originatingPageURL = url;
     _mimeType = [mimeType copy];
 
@@ -103,6 +109,7 @@ SOFT_LINK_CLASS(AssetViewer, ARQuickLookWebKitItem);
     previewItem.canonicalWebPageURL = _originatingPageURL;
 
     _item = [allocARQuickLookWebKitItemInstance() initWithPreviewItemProvider:_itemProvider.get() contentType:contentType previewTitle:@"Preview" fileSize:@(0) previewItem:previewItem];
+    [_item setDelegate:self];
 #else
     _item = adoptNS([PAL::allocQLItemInstance() initWithPreviewItemProvider:_itemProvider.get() contentType:contentType previewTitle:@"Preview" fileSize:@(0)]);
 #endif
@@ -142,6 +149,17 @@ SOFT_LINK_CLASS(AssetViewer, ARQuickLookWebKitItem);
         self.completionHandler(nil, error);
 }
 
+#if HAVE(ARKIT_QUICK_LOOK_PREVIEW_ITEM)
+- (void)previewItem:(ARQuickLookWebKitItem *)previewItem didReceiveMessage:(NSDictionary *)message
+{
+    if (!_previewController)
+        return;
+
+    if ([[message[@"callToAction"] stringValue] isEqualToString:@"buttonTapped"])
+        _previewController->triggerSystemPreviewAction();
+}
+#endif
+
 @end
 
 @interface _WKPreviewControllerDelegate : NSObject <QLPreviewControllerDelegate> {
@@ -152,13 +170,12 @@ SOFT_LINK_CLASS(AssetViewer, ARQuickLookWebKitItem);
 
 @implementation _WKPreviewControllerDelegate
 
-- (id)initWithSystemPreviewController:(WebKit::SystemPreviewController*)previewController fromRect:(WebCore::IntRect)rect
+- (id)initWithSystemPreviewController:(WebKit::SystemPreviewController*)previewController
 {
     if (!(self = [super init]))
         return nil;
 
     _previewController = previewController;
-    _linkRect = rect;
     return self;
 }
 
@@ -185,16 +202,15 @@ SOFT_LINK_CLASS(AssetViewer, ARQuickLookWebKitItem);
 
     *view = presentingViewController.view;
 
-    if (_linkRect.isEmpty()) {
-        CGRect frame;
-        frame.size.width = presentingViewController.view.frame.size.width / 2.0;
-        frame.size.height = presentingViewController.view.frame.size.height / 2.0;
-        frame.origin.x = (presentingViewController.view.frame.size.width - frame.size.width) / 2.0;
-        frame.origin.y = (presentingViewController.view.frame.size.height - frame.size.height) / 2.0;
-        return frame;
-    }
+    if (!_previewController->previewInfo().previewRect.isEmpty())
+        return _previewController->page().syncRootViewToScreen(_previewController->previewInfo().previewRect);
 
-    return _previewController->page().syncRootViewToScreen(_linkRect);
+    CGRect frame;
+    frame.size.width = (*view).frame.size.width / 2.0;
+    frame.size.height = (*view).frame.size.height / 2.0;
+    frame.origin.x = ((*view).frame.size.width - frame.size.width) / 2.0;
+    frame.origin.y = ((*view).frame.size.height - frame.size.height) / 2.0;
+    return frame;
 }
 
 - (UIImage *)previewController:(QLPreviewController *)controller transitionImageForPreviewItem:(id <QLPreviewItem>)item contentRect:(CGRect *)contentRect
@@ -218,7 +234,7 @@ SOFT_LINK_CLASS(AssetViewer, ARQuickLookWebKitItem);
 
 namespace WebKit {
 
-void SystemPreviewController::start(URL originatingPageURL, const String& mimeType, const WebCore::IntRect& fromRect)
+void SystemPreviewController::start(URL originatingPageURL, const String& mimeType, const WebCore::SystemPreviewInfo& systemPreviewInfo)
 {
     ASSERT(!m_qlPreviewController);
     if (m_qlPreviewController)
@@ -229,12 +245,14 @@ void SystemPreviewController::start(URL originatingPageURL, const String& mimeTy
     if (!presentingViewController)
         return;
 
+    m_systemPreviewInfo = systemPreviewInfo;
+
     m_qlPreviewController = adoptNS([PAL::allocQLPreviewControllerInstance() init]);
 
-    m_qlPreviewControllerDelegate = adoptNS([[_WKPreviewControllerDelegate alloc] initWithSystemPreviewController:this fromRect:fromRect]);
+    m_qlPreviewControllerDelegate = adoptNS([[_WKPreviewControllerDelegate alloc] initWithSystemPreviewController:this]);
     [m_qlPreviewController setDelegate:m_qlPreviewControllerDelegate.get()];
 
-    m_qlPreviewControllerDataSource = adoptNS([[_WKPreviewControllerDataSource alloc] initWithMIMEType:mimeType originatingPageURL:originatingPageURL]);
+    m_qlPreviewControllerDataSource = adoptNS([[_WKPreviewControllerDataSource alloc] initWithSystemPreviewController:this MIMEType:mimeType originatingPageURL:originatingPageURL]);
     [m_qlPreviewController setDataSource:m_qlPreviewControllerDataSource.get()];
 
     [presentingViewController presentViewController:m_qlPreviewController.get() animated:YES completion:nullptr];
@@ -268,6 +286,18 @@ void SystemPreviewController::fail(const WebCore::ResourceError& error)
         [m_qlPreviewControllerDataSource failWithError:error.nsError()];
 }
 
+void SystemPreviewController::triggerSystemPreviewAction()
+{
+    page().systemPreviewActionTriggered(m_systemPreviewInfo, "_apple_ar_quicklook_button_tapped");
+}
+
+void SystemPreviewController::triggerSystemPreviewActionWithTargetForTesting(uint64_t frameID, uint64_t pageID)
+{
+    m_systemPreviewInfo.globalFrameID.frameID = makeObjectIdentifier<WebCore::FrameIdentifierType>(frameID);
+    m_systemPreviewInfo.globalFrameID.pageID = makeObjectIdentifier<WebCore::PageIdentifierType>(pageID);
+    triggerSystemPreviewAction();
+}
+
 }
 
 #endif
index f240499..aa1f377 100644 (file)
@@ -91,7 +91,7 @@ public:
 
 #if USE(SYSTEM_PREVIEW)
     bool isSystemPreviewDownload() const { return request().isSystemPreview(); }
-    const WebCore::IntRect& systemPreviewDownloadRect() const { return request().systemPreviewRect(); }
+    WebCore::SystemPreviewInfo systemPreviewDownloadInfo() const { return request().systemPreviewInfo(); }
 #endif
 
 #if PLATFORM(COCOA)
index 2b90e1b..1aa4017 100644 (file)
@@ -27,6 +27,7 @@
 
 #if USE(SYSTEM_PREVIEW)
 
+#include <WebCore/FrameLoaderTypes.h>
 #include <WebCore/IntRect.h>
 #include <WebCore/ResourceError.h>
 #include <wtf/RetainPtr.h>
@@ -49,16 +50,22 @@ public:
 
     bool canPreview(const String& mimeType) const;
 
-    void start(URL originatingPageURL, const String& mimeType, const WebCore::IntRect&);
+    void start(URL originatingPageURL, const String& mimeType, const WebCore::SystemPreviewInfo&);
     void updateProgress(float);
     void finish(URL);
     void cancel();
     void fail(const WebCore::ResourceError&);
 
     WebPageProxy& page() { return m_webPageProxy; }
+    const WebCore::SystemPreviewInfo& previewInfo() const { return m_systemPreviewInfo; }
+
+    void triggerSystemPreviewAction();
+
+    void triggerSystemPreviewActionWithTargetForTesting(uint64_t frameID, uint64_t pageID);
 
 private:
     WebPageProxy& m_webPageProxy;
+    WebCore::SystemPreviewInfo m_systemPreviewInfo;
 #if USE(QUICK_LOOK)
     RetainPtr<QLPreviewController> m_qlPreviewController;
     RetainPtr<_WKPreviewControllerDelegate> m_qlPreviewControllerDelegate;
index c3c5a64..2e4398f 100644 (file)
@@ -9172,6 +9172,13 @@ void WebPageProxy::removeDataDetectedLinks(CompletionHandler<void(const DataDete
 
 #endif
 
+#if USE(SYSTEM_PREVIEW)
+void WebPageProxy::systemPreviewActionTriggered(const WebCore::SystemPreviewInfo& previewInfo, const String& message) const
+{
+    m_process->send(Messages::WebPage::SystemPreviewActionTriggered(previewInfo, message), m_webPageID);
+}
+#endif
+
 void WebPageProxy::dumpAdClickAttribution(CompletionHandler<void(const String&)>&& completionHandler)
 {
     if (auto* networkProcess = m_process->processPool().networkProcess()) {
index 3ab7b2b..fd99fc3 100644 (file)
@@ -484,6 +484,7 @@ public:
 
 #if USE(SYSTEM_PREVIEW)
     SystemPreviewController* systemPreviewController() { return m_systemPreviewController.get(); }
+    void systemPreviewActionTriggered(const WebCore::SystemPreviewInfo&, const String&) const;
 #endif
 
 #if ENABLE(CONTEXT_MENUS)
index 2a63a25..1cdc0b6 100644 (file)
@@ -6612,6 +6612,25 @@ void WebPage::simulateDeviceOrientationChange(double alpha, double beta, double
 #endif
 }
 
+#if USE(SYSTEM_PREVIEW)
+void WebPage::systemPreviewActionTriggered(WebCore::SystemPreviewInfo previewInfo, const String& message)
+{
+    WebFrame* frame = WebProcess::singleton().webFrame(previewInfo.globalFrameID.frameID);
+    if (!frame)
+        return;
+
+    auto* document = frame->coreFrame()->document();
+    if (!document)
+        return;
+
+    auto pageID = document->pageID();
+    if (!pageID || previewInfo.globalFrameID.pageID != pageID.value())
+        return;
+
+    document->dispatchSystemPreviewActionEvent(message);
+}
+#endif
+
 #if ENABLE(SPEECH_SYNTHESIS)
 void WebPage::speakingErrorOccurred()
 {
index 92a2423..4428f3a 100644 (file)
@@ -1589,6 +1589,10 @@ private:
 
     void simulateDeviceOrientationChange(double alpha, double beta, double gamma);
 
+#if USE(SYSTEM_PREVIEW)
+    void systemPreviewActionTriggered(WebCore::SystemPreviewInfo, const String& message);
+#endif
+
 #if ENABLE(SPEECH_SYNTHESIS)
     void speakingErrorOccurred();
     void boundaryEventOccurred(bool wordBoundary, unsigned charIndex);
index 9d4f93e..c6da6e2 100644 (file)
@@ -574,4 +574,9 @@ GenerateSyntheticEditingCommand(enum:uint8_t WebKit::SyntheticEditingCommandType
 #if ENABLE(RESOURCE_LOAD_STATISTICS)
     WasLoadedWithDataTransferFromPrevalentResource()
 #endif
+
+#if USE(SYSTEM_PREVIEW)
+    SystemPreviewActionTriggered(struct WebCore::SystemPreviewInfo previewInfo, String message)
+#endif
+
 }
index cc76387..1a1666c 100644 (file)
@@ -1,3 +1,15 @@
+2019-09-11  Dean Jackson  <dino@apple.com>
+
+        Provide a prototype for AR QuickLook to trigger processing in the originating page
+        https://bugs.webkit.org/show_bug.cgi?id=201371
+        <rdar://54904781>
+
+        Reviewed by Simon Fraser.
+
+        * TestWebKitAPI/Tools/TestWebKitAPI/Tests/WebKitCocoa/SystemPreview.mm:
+        * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
+        * TestWebKitAPI/Tests/WebKitCocoa/system-preview-trigger.html: Added.
+
 2019-09-13  Youenn Fablet  <youenn@apple.com>
 
         Partition processes running service workers by session ID
index 1912135..f6d018d 100644 (file)
                2EFF06D71D8AF34A0004BB30 /* WKWebViewCandidateTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2EFF06D61D8AF34A0004BB30 /* WKWebViewCandidateTests.mm */; };
                313C3A0221E567C300DBA86E /* SystemPreviewBlobNaming.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 313C3A0121E5677A00DBA86E /* SystemPreviewBlobNaming.html */; };
                315118101DB1AE4000176304 /* ExtendedColor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3151180F1DB1ADD500176304 /* ExtendedColor.cpp */; };
+               31B76E4323298E2C007FED2C /* SystemPreview.mm in Sources */ = {isa = PBXBuildFile; fileRef = 31B76E4223298E2B007FED2C /* SystemPreview.mm */; };
+               31B76E4523299BDC007FED2C /* system-preview-trigger.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 31B76E4423299BA3007FED2C /* system-preview-trigger.html */; };
                33BE5AF9137B5AAE00705813 /* MouseMoveAfterCrash_Bundle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 33BE5AF8137B5AAE00705813 /* MouseMoveAfterCrash_Bundle.cpp */; };
                33DC8912141955FE00747EF7 /* simple-iframe.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 33DC890E1419539300747EF7 /* simple-iframe.html */; };
                33DC89141419579F00747EF7 /* LoadCanceledNoServerRedirectCallback_Bundle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 33DC89131419579F00747EF7 /* LoadCanceledNoServerRedirectCallback_Bundle.cpp */; };
                                9BD6D3A31F7B218300BD4962 /* sunset-in-cupertino-200px.png in Copy Resources */,
                                9BD6D3A41F7B218300BD4962 /* sunset-in-cupertino-400px.gif in Copy Resources */,
                                9BD6D3A51F7B218300BD4962 /* sunset-in-cupertino-600px.jpg in Copy Resources */,
+                               31B76E4523299BDC007FED2C /* system-preview-trigger.html in Copy Resources */,
                                313C3A0221E567C300DBA86E /* SystemPreviewBlobNaming.html in Copy Resources */,
                                CD59F53519E9110D00CF1835 /* test-mse.mp4 in Copy Resources */,
                                C95984F71E36BCEF002C0D45 /* test-without-audio-track.mp4 in Copy Resources */,
                2EFF06D61D8AF34A0004BB30 /* WKWebViewCandidateTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WKWebViewCandidateTests.mm; sourceTree = "<group>"; };
                313C3A0121E5677A00DBA86E /* SystemPreviewBlobNaming.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = SystemPreviewBlobNaming.html; sourceTree = "<group>"; };
                3151180F1DB1ADD500176304 /* ExtendedColor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ExtendedColor.cpp; sourceTree = "<group>"; };
+               31B76E4223298E2B007FED2C /* SystemPreview.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = SystemPreview.mm; sourceTree = "<group>"; };
+               31B76E4423299BA3007FED2C /* system-preview-trigger.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; path = "system-preview-trigger.html"; sourceTree = "<group>"; };
                333B9CE11277F23100FEFCE3 /* PreventEmptyUserAgent.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PreventEmptyUserAgent.cpp; sourceTree = "<group>"; };
                33BE5AF4137B5A6C00705813 /* MouseMoveAfterCrash.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MouseMoveAfterCrash.cpp; sourceTree = "<group>"; };
                33BE5AF8137B5AAE00705813 /* MouseMoveAfterCrash_Bundle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MouseMoveAfterCrash_Bundle.cpp; sourceTree = "<group>"; };
                                414AD6852285D1B000777F2D /* StorageQuota.mm */,
                                515BE1701D428BD100DD7C68 /* StoreBlobThenDelete.mm */,
                                1C734B5220788C4800F430EA /* SystemColors.mm */,
+                               31B76E4223298E2B007FED2C /* SystemPreview.mm */,
                                2D70059521EDA0C6003463CB /* TabOutOfWebView.mm */,
                                5774AA6721FBBF7800AF2A1B /* TestSOAuthorization.mm */,
                                F4CD74C720FDB49600DE3794 /* TestURLSchemeHandler.h */,
                                9BD6D3A01F7B202000BD4962 /* sunset-in-cupertino-200px.png */,
                                9BD6D39F1F7B202000BD4962 /* sunset-in-cupertino-400px.gif */,
                                9BD6D39E1F7B201E00BD4962 /* sunset-in-cupertino-600px.jpg */,
+                               31B76E4423299BA3007FED2C /* system-preview-trigger.html */,
                                313C3A0121E5677A00DBA86E /* SystemPreviewBlobNaming.html */,
                                2E9896141D8F092B00739892 /* text-and-password-inputs.html */,
                                F4CD74C520FDACF500DE3794 /* text-with-async-script.html */,
                                4433A396208044140091ED57 /* SynchronousTimeoutTests.mm in Sources */,
                                7CCE7EA81A411A1900447C4C /* SyntheticBackingScaleFactorWindow.m in Sources */,
                                1C734B5320788C4800F430EA /* SystemColors.mm in Sources */,
+                               31B76E4323298E2C007FED2C /* SystemPreview.mm in Sources */,
                                2D70059621EDA0C6003463CB /* TabOutOfWebView.mm in Sources */,
                                7CCE7F161A411AE600447C4C /* TerminateTwice.cpp in Sources */,
                                7CCE7EA91A411A1D00447C4C /* TestBrowsingContextLoadDelegate.mm in Sources */,
diff --git a/Tools/TestWebKitAPI/Tests/WebKitCocoa/SystemPreview.mm b/Tools/TestWebKitAPI/Tests/WebKitCocoa/SystemPreview.mm
new file mode 100644 (file)
index 0000000..d306889
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2019 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "config.h"
+
+#if PLATFORM(IOS) && USE(SYSTEM_PREVIEW)
+
+#import "TestWKWebView.h"
+#import "Utilities.h"
+#import "WKWebViewConfigurationExtras.h"
+#import <WebKit/WKViewPrivate.h>
+#import <WebKit/WKWebViewPrivate.h>
+#import <WebKit/WebKit.h>
+
+static bool isLoaded;
+static bool isTriggered;
+static uint64_t frameID;
+static uint64_t pageID;
+
+@interface TestSystemPreviewTriggeredHandler : NSObject <WKScriptMessageHandler>
+@end
+
+@implementation TestSystemPreviewTriggeredHandler
+
+- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message
+{
+    if ([message.body[@"message"] isEqualToString:@"loaded"]) {
+        frameID = [message.body[@"frameID"] unsignedIntValue];
+        pageID = [message.body[@"pageID"] unsignedIntValue];
+        isLoaded = true;
+    } else if ([message.body[@"message"] isEqualToString:@"triggered"]) {
+        EXPECT_TRUE([message.body[@"action"] isEqualToString:@"_apple_ar_quicklook_button_tapped"]);
+        isTriggered = true;
+    }
+}
+
+@end
+
+namespace TestWebKitAPI {
+
+TEST(WebKit, SystemPreviewTriggered)
+{
+    auto messageHandler = adoptNS([[TestSystemPreviewTriggeredHandler alloc] init]);
+
+    WKWebViewConfiguration *configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"WebProcessPlugInWithInternals"];
+    [configuration.userContentController addScriptMessageHandler:messageHandler.get() name:@"testSystemPreview"];
+
+    auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectZero configuration:configuration]);
+    [webView loadRequest:[NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@"system-preview-trigger" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]]];
+    Util::run(&isLoaded);
+
+    [webView _triggerSystemPreviewActionOnFrame:frameID page:pageID];
+    Util::run(&isTriggered);
+}
+
+}
+
+#endif // PLATFORM(IOS) && USE(SYSTEM_PREVIEW)
diff --git a/Tools/TestWebKitAPI/Tests/WebKitCocoa/system-preview-trigger.html b/Tools/TestWebKitAPI/Tests/WebKitCocoa/system-preview-trigger.html
new file mode 100644 (file)
index 0000000..b6c5bc7
--- /dev/null
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<body>
+<script>
+window.addEventListener("message", function (event) {
+    window.webkit.messageHandlers.testSystemPreview.postMessage({ message: "triggered", action: event.data });
+});
+
+window.addEventListener("load", function () {
+    let pageID = internals.pageIdentifier(document);
+    let frameID = internals.frameIdentifier(document);
+    let msg = { message: "loaded", pageID, frameID };
+    window.webkit.messageHandlers.testSystemPreview.postMessage(msg);
+});
+
+</script>
+