<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[278394] trunk/Source/WebKit</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/278394">278394</a></dd>
<dt>Author</dt> <dd>wenson_hsieh@apple.com</dd>
<dt>Date</dt> <dd>2021-06-02 21:59:05 -0700 (Wed, 02 Jun 2021)</dd>
</dl>

<h3>Log Message</h3>
<pre>[iOS] Show data detector context menu on long press inside image overlays
https://bugs.webkit.org/show_bug.cgi?id=226559
<rdar://problem/78789078>

Reviewed by Tim Horton.

Add additional support for data detectors that appear inside image overlays on iOS.

* Shared/ImageExtractionUpdateResult.h: Added.

Turn the `bool` propagated back to the UI process when calling `updateWithImageExtractionResult` into a separate
three-state enum instead; see changes below for more details.

* Shared/ios/InteractionInformationAtPosition.h:
* Shared/ios/InteractionInformationAtPosition.mm:
(WebKit::InteractionInformationAtPosition::encode const):
(WebKit::InteractionInformationAtPosition::decode):

Make some minor adjustments to `InteractionInformationAtPosition`:

-   Add `dataDetectorBounds`, which determines the bounds in root view coordinates of the data detector result
    corresponding to the hit-tested element.

-   Encode and decode `dataDetectorResults`, even if `isDataDetectorLink` is `false`. Unless the data detector
    is inside an image overlay, this (effectively) has no impact, since `dataDetectorResults` was previously
    only set if `isDataDetectorLink` was true.

* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::updateWithImageExtractionResult):
* UIProcess/WebPageProxy.h:
* UIProcess/ios/WKContentViewInteraction.mm:
(-[WKContentView dataDetectionContextForPositionInformation:]):

Let `dataDetectorResults` take precedence over regular `bounds` when returning the context for the data
detector menu configuration.

(-[WKContentView positionInformationHasImageOverlayDataDetector]):

Add a helper method that returns `YES` in the case where the currently cached position information object
contains a text data detection result inside an image overlay.

(-[WKContentView _createTargetedContextMenuHintPreviewIfPossible]):

Use `dataDetectorBounds` instead of `bounds` when creating a fallback targeted preview for a data detection
result in an image overlay.

(-[WKContentView continueContextMenuInteraction:]):
(-[WKContentView continueContextMenuInteractionWithDataDetectors:]):

Adjust these codepaths so that we'll continue through to the data detector case instead of bailing early in the
case where both `isImageOverlayText` is set, and `dataDetectionResults` exist.

* WebKit.xcodeproj/project.pbxproj:
* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::findDataDetectionResultElementInImageOverlay):

Add a static helper to locate a data detector element underneath the given point, inside the given element's
image overlay in the user agent shadow root. Note that we check each of the element's bounds instead of using
a hit-test because we normally just hit-test to the text containers instead of the data detector containers.

(WebKit::WebPage::updateWithImageExtractionResult):
* WebProcess/WebPage/WebPage.h:
* WebProcess/WebPage/WebPage.messages.in:
* WebProcess/WebPage/ios/WebPageIOS.mm:
(WebKit::dataDetectorLinkPositionInformation):
(WebKit::dataDetectorImageOverlayPositionInformation):

Add a static helper function to populate the given `InteractionInformationAtPosition`, if it's over a data
detection result inside an image overlay.

(WebKit::elementPositionInformation): Call the above helper function.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebKitChangeLog">trunk/Source/WebKit/ChangeLog</a></li>
<li><a href="#trunkSourceWebKitSharediosInteractionInformationAtPositionh">trunk/Source/WebKit/Shared/ios/InteractionInformationAtPosition.h</a></li>
<li><a href="#trunkSourceWebKitSharediosInteractionInformationAtPositionmm">trunk/Source/WebKit/Shared/ios/InteractionInformationAtPosition.mm</a></li>
<li><a href="#trunkSourceWebKitUIProcessWebPageProxycpp">trunk/Source/WebKit/UIProcess/WebPageProxy.cpp</a></li>
<li><a href="#trunkSourceWebKitUIProcessWebPageProxyh">trunk/Source/WebKit/UIProcess/WebPageProxy.h</a></li>
<li><a href="#trunkSourceWebKitUIProcessiosWKContentViewInteractionmm">trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm</a></li>
<li><a href="#trunkSourceWebKitWebKitxcodeprojprojectpbxproj">trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj</a></li>
<li><a href="#trunkSourceWebKitWebProcessWebPageWebPagecpp">trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp</a></li>
<li><a href="#trunkSourceWebKitWebProcessWebPageWebPageh">trunk/Source/WebKit/WebProcess/WebPage/WebPage.h</a></li>
<li><a href="#trunkSourceWebKitWebProcessWebPageWebPagemessagesin">trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in</a></li>
<li><a href="#trunkSourceWebKitWebProcessWebPageiosWebPageIOSmm">trunk/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceWebKitSharedImageExtractionUpdateResulth">trunk/Source/WebKit/Shared/ImageExtractionUpdateResult.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebKitChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/ChangeLog (278393 => 278394)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/ChangeLog    2021-06-03 04:57:45 UTC (rev 278393)
+++ trunk/Source/WebKit/ChangeLog       2021-06-03 04:59:05 UTC (rev 278394)
</span><span class="lines">@@ -1,3 +1,77 @@
</span><ins>+2021-06-02  Wenson Hsieh  <wenson_hsieh@apple.com>
+
+        [iOS] Show data detector context menu on long press inside image overlays
+        https://bugs.webkit.org/show_bug.cgi?id=226559
+        <rdar://problem/78789078>
+
+        Reviewed by Tim Horton.
+
+        Add additional support for data detectors that appear inside image overlays on iOS.
+
+        * Shared/ImageExtractionUpdateResult.h: Added.
+
+        Turn the `bool` propagated back to the UI process when calling `updateWithImageExtractionResult` into a separate
+        three-state enum instead; see changes below for more details.
+
+        * Shared/ios/InteractionInformationAtPosition.h:
+        * Shared/ios/InteractionInformationAtPosition.mm:
+        (WebKit::InteractionInformationAtPosition::encode const):
+        (WebKit::InteractionInformationAtPosition::decode):
+
+        Make some minor adjustments to `InteractionInformationAtPosition`:
+
+        -   Add `dataDetectorBounds`, which determines the bounds in root view coordinates of the data detector result
+            corresponding to the hit-tested element.
+
+        -   Encode and decode `dataDetectorResults`, even if `isDataDetectorLink` is `false`. Unless the data detector
+            is inside an image overlay, this (effectively) has no impact, since `dataDetectorResults` was previously
+            only set if `isDataDetectorLink` was true.
+
+        * UIProcess/WebPageProxy.cpp:
+        (WebKit::WebPageProxy::updateWithImageExtractionResult):
+        * UIProcess/WebPageProxy.h:
+        * UIProcess/ios/WKContentViewInteraction.mm:
+        (-[WKContentView dataDetectionContextForPositionInformation:]):
+
+        Let `dataDetectorResults` take precedence over regular `bounds` when returning the context for the data
+        detector menu configuration.
+
+        (-[WKContentView positionInformationHasImageOverlayDataDetector]):
+
+        Add a helper method that returns `YES` in the case where the currently cached position information object
+        contains a text data detection result inside an image overlay.
+
+        (-[WKContentView _createTargetedContextMenuHintPreviewIfPossible]):
+
+        Use `dataDetectorBounds` instead of `bounds` when creating a fallback targeted preview for a data detection
+        result in an image overlay.
+
+        (-[WKContentView continueContextMenuInteraction:]):
+        (-[WKContentView continueContextMenuInteractionWithDataDetectors:]):
+
+        Adjust these codepaths so that we'll continue through to the data detector case instead of bailing early in the
+        case where both `isImageOverlayText` is set, and `dataDetectionResults` exist.
+
+        * WebKit.xcodeproj/project.pbxproj:
+        * WebProcess/WebPage/WebPage.cpp:
+        (WebKit::WebPage::findDataDetectionResultElementInImageOverlay):
+
+        Add a static helper to locate a data detector element underneath the given point, inside the given element's
+        image overlay in the user agent shadow root. Note that we check each of the element's bounds instead of using
+        a hit-test because we normally just hit-test to the text containers instead of the data detector containers.
+
+        (WebKit::WebPage::updateWithImageExtractionResult):
+        * WebProcess/WebPage/WebPage.h:
+        * WebProcess/WebPage/WebPage.messages.in:
+        * WebProcess/WebPage/ios/WebPageIOS.mm:
+        (WebKit::dataDetectorLinkPositionInformation):
+        (WebKit::dataDetectorImageOverlayPositionInformation):
+
+        Add a static helper function to populate the given `InteractionInformationAtPosition`, if it's over a data
+        detection result inside an image overlay.
+
+        (WebKit::elementPositionInformation): Call the above helper function.
+
</ins><span class="cx"> 2021-06-02  Alex Christensen  <achristensen@webkit.org>
</span><span class="cx"> 
</span><span class="cx">         Fix WPT test resource-timing/cross-origin-redirects.html
</span></span></pre></div>
<a id="trunkSourceWebKitSharedImageExtractionUpdateResulth"></a>
<div class="addfile"><h4>Added: trunk/Source/WebKit/Shared/ImageExtractionUpdateResult.h (0 => 278394)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/Shared/ImageExtractionUpdateResult.h                         (rev 0)
+++ trunk/Source/WebKit/Shared/ImageExtractionUpdateResult.h    2021-06-03 04:59:05 UTC (rev 278394)
</span><span class="lines">@@ -0,0 +1,55 @@
</span><ins>+/*
+ * Copyright (C) 2021 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
+
+#if ENABLE(IMAGE_EXTRACTION)
+
+#include <wtf/EnumTraits.h>
+
+namespace WebKit {
+
+enum class ImageExtractionUpdateResult : uint8_t {
+    NoText,
+    Text,
+    DataDetector,
+};
+
+} // namespace WebKit
+
+namespace WTF {
+
+template<> struct EnumTraits<WebKit::ImageExtractionUpdateResult> {
+    using values = EnumValues<
+        WebKit::ImageExtractionUpdateResult,
+        WebKit::ImageExtractionUpdateResult::NoText,
+        WebKit::ImageExtractionUpdateResult::Text,
+        WebKit::ImageExtractionUpdateResult::DataDetector
+    >;
+};
+
+} // namespace WTF
+
+#endif // ENABLE(IMAGE_EXTRACTION)
</ins></span></pre></div>
<a id="trunkSourceWebKitSharediosInteractionInformationAtPositionh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/Shared/ios/InteractionInformationAtPosition.h (278393 => 278394)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/Shared/ios/InteractionInformationAtPosition.h        2021-06-03 04:57:45 UTC (rev 278393)
+++ trunk/Source/WebKit/Shared/ios/InteractionInformationAtPosition.h   2021-06-03 04:59:05 UTC (rev 278394)
</span><span class="lines">@@ -94,6 +94,7 @@
</span><span class="cx"> #if ENABLE(DATA_DETECTION)
</span><span class="cx">     String dataDetectorIdentifier;
</span><span class="cx">     RetainPtr<NSArray> dataDetectorResults;
</span><ins>+    WebCore::IntRect dataDetectorBounds;
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx">     std::optional<WebCore::ElementContext> elementContext;
</span></span></pre></div>
<a id="trunkSourceWebKitSharediosInteractionInformationAtPositionmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/Shared/ios/InteractionInformationAtPosition.mm (278393 => 278394)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/Shared/ios/InteractionInformationAtPosition.mm       2021-06-03 04:57:45 UTC (rev 278393)
+++ trunk/Source/WebKit/Shared/ios/InteractionInformationAtPosition.mm  2021-06-03 04:59:05 UTC (rev 278394)
</span><span class="lines">@@ -77,10 +77,9 @@
</span><span class="cx">     encoder << handle;
</span><span class="cx"> #if ENABLE(DATA_DETECTION)
</span><span class="cx">     encoder << isDataDetectorLink;
</span><del>-    if (isDataDetectorLink) {
-        encoder << dataDetectorIdentifier;
-        encoder << dataDetectorResults;
-    }
</del><ins>+    encoder << dataDetectorIdentifier;
+    encoder << dataDetectorResults;
+    encoder << dataDetectorBounds;
</ins><span class="cx"> #endif
</span><span class="cx"> #if ENABLE(DATALIST_ELEMENT)
</span><span class="cx">     encoder << preventTextInteraction;
</span><span class="lines">@@ -189,17 +188,18 @@
</span><span class="cx"> #if ENABLE(DATA_DETECTION)
</span><span class="cx">     if (!decoder.decode(result.isDataDetectorLink))
</span><span class="cx">         return false;
</span><del>-    
-    if (result.isDataDetectorLink) {
-        if (!decoder.decode(result.dataDetectorIdentifier))
-            return false;
</del><span class="cx"> 
</span><del>-        auto dataDetectorResults = IPC::decode<NSArray>(decoder, @[ [NSArray class], getDDScannerResultClass() ]);
-        if (!dataDetectorResults)
-            return false;
</del><ins>+    if (!decoder.decode(result.dataDetectorIdentifier))
+        return false;
</ins><span class="cx"> 
</span><del>-        result.dataDetectorResults = WTFMove(*dataDetectorResults);
-    }
</del><ins>+    auto dataDetectorResults = IPC::decode<NSArray>(decoder, @[ NSArray.class, getDDScannerResultClass() ]);
+    if (!dataDetectorResults)
+        return false;
+
+    result.dataDetectorResults = WTFMove(*dataDetectorResults);
+
+    if (!decoder.decode(result.dataDetectorBounds))
+        return false;
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(DATALIST_ELEMENT)
</span></span></pre></div>
<a id="trunkSourceWebKitUIProcessWebPageProxycpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.cpp (278393 => 278394)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/UIProcess/WebPageProxy.cpp   2021-06-03 04:57:45 UTC (rev 278393)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.cpp      2021-06-03 04:59:05 UTC (rev 278394)
</span><span class="lines">@@ -66,6 +66,7 @@
</span><span class="cx"> #include "EventDispatcherMessages.h"
</span><span class="cx"> #include "FormDataReference.h"
</span><span class="cx"> #include "FrameInfoData.h"
</span><ins>+#include "ImageExtractionUpdateResult.h"
</ins><span class="cx"> #include "LegacyGlobalSettings.h"
</span><span class="cx"> #include "LoadParameters.h"
</span><span class="cx"> #include "Logging.h"
</span><span class="lines">@@ -8481,10 +8482,10 @@
</span><span class="cx">     pageClient().computeCanRevealImage(imageURL, imageBitmap, WTFMove(completion));
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void WebPageProxy::updateWithImageExtractionResult(ImageExtractionResult&& results, const ElementContext& context, const FloatPoint& location, CompletionHandler<void(bool textExistsAtLocation)>&& completionHandler)
</del><ins>+void WebPageProxy::updateWithImageExtractionResult(ImageExtractionResult&& results, const ElementContext& context, const FloatPoint& location, CompletionHandler<void(ImageExtractionUpdateResult)>&& completionHandler)
</ins><span class="cx"> {
</span><span class="cx">     if (!hasRunningProcess()) {
</span><del>-        completionHandler(false);
</del><ins>+        completionHandler(ImageExtractionUpdateResult::NoText);
</ins><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebKitUIProcessWebPageProxyh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.h (278393 => 278394)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/UIProcess/WebPageProxy.h     2021-06-03 04:57:45 UTC (rev 278393)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.h        2021-06-03 04:59:05 UTC (rev 278394)
</span><span class="lines">@@ -406,6 +406,7 @@
</span><span class="cx"> struct WebPopupItem;
</span><span class="cx"> struct WebSpeechSynthesisVoice;
</span><span class="cx"> 
</span><ins>+enum class ImageExtractionUpdateResult : uint8_t;
</ins><span class="cx"> enum class NegotiatedLegacyTLS : bool;
</span><span class="cx"> enum class ProcessSwapRequestedByClient : bool;
</span><span class="cx"> enum class UndoOrRedo : bool;
</span><span class="lines">@@ -1664,7 +1665,7 @@
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(IMAGE_EXTRACTION)
</span><span class="cx">     void requestImageExtraction(const URL& imageURL, const ShareableBitmap::Handle& imageData, CompletionHandler<void(WebCore::ImageExtractionResult&&)>&&);
</span><del>-    void updateWithImageExtractionResult(WebCore::ImageExtractionResult&&, const WebCore::ElementContext&, const WebCore::FloatPoint& location, CompletionHandler<void(bool textExistsAtLocation)>&&);
</del><ins>+    void updateWithImageExtractionResult(WebCore::ImageExtractionResult&&, const WebCore::ElementContext&, const WebCore::FloatPoint& location, CompletionHandler<void(ImageExtractionUpdateResult)>&&);
</ins><span class="cx">     void computeCanRevealImage(const URL& imageURL, ShareableBitmap& imageBitmap, CompletionHandler<void(bool)>&&);
</span><span class="cx"> #endif
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebKitUIProcessiosWKContentViewInteractionmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm (278393 => 278394)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm    2021-06-03 04:57:45 UTC (rev 278393)
+++ trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm       2021-06-03 04:59:05 UTC (rev 278394)
</span><span class="lines">@@ -7523,6 +7523,8 @@
</span><span class="cx">     CGRect sourceRect;
</span><span class="cx">     if (positionInformation.isLink)
</span><span class="cx">         sourceRect = positionInformation.linkIndicator.textBoundingRectInRootViewCoordinates;
</span><ins>+    else if (!positionInformation.dataDetectorBounds.isEmpty())
+        sourceRect = positionInformation.dataDetectorBounds;
</ins><span class="cx">     else
</span><span class="cx">         sourceRect = positionInformation.bounds;
</span><span class="cx"> 
</span><span class="lines">@@ -8460,6 +8462,11 @@
</span><span class="cx">     return _contextMenuInteractionTargetedPreview.get();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+- (BOOL)positionInformationHasImageOverlayDataDetector
+{
+    return _positionInformation.isImageOverlayText && [_positionInformation.dataDetectorResults count];
+}
+
</ins><span class="cx"> - (UITargetedPreview *)_createTargetedContextMenuHintPreviewIfPossible
</span><span class="cx"> {
</span><span class="cx">     RetainPtr<UITargetedPreview> targetedPreview;
</span><span class="lines">@@ -8474,8 +8481,10 @@
</span><span class="cx">         targetedPreview = createTargetedPreview(image.get(), self, self.containerForContextMenuHintPreviews, _positionInformation.bounds, { }, nil);
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    if (!targetedPreview)
-        targetedPreview = createFallbackTargetedPreview(self, self.containerForContextMenuHintPreviews, _positionInformation.bounds, nil);
</del><ins>+    if (!targetedPreview) {
+        auto boundsForFallbackPreview = self.positionInformationHasImageOverlayDataDetector ? _positionInformation.dataDetectorBounds : _positionInformation.bounds;
+        targetedPreview = createFallbackTargetedPreview(self, self.containerForContextMenuHintPreviews, boundsForFallbackPreview, nil);
+    }
</ins><span class="cx"> 
</span><span class="cx">     [self _updateTargetedPreviewScrollViewUsingContainerScrollingNodeID:_positionInformation.containerScrollingNodeID];
</span><span class="cx"> 
</span><span class="lines">@@ -10281,7 +10290,7 @@
</span><span class="cx">     if (!_positionInformation.touchCalloutEnabled)
</span><span class="cx">         return continueWithContextMenuConfiguration(nil);
</span><span class="cx"> 
</span><del>-    if (!_positionInformation.isLink && !_positionInformation.isImage && !_positionInformation.isAttachment)
</del><ins>+    if (!_positionInformation.isLink && !_positionInformation.isImage && !_positionInformation.isAttachment && !self.positionInformationHasImageOverlayDataDetector)
</ins><span class="cx">         return continueWithContextMenuConfiguration(nil);
</span><span class="cx"> 
</span><span class="cx">     URL linkURL = _positionInformation.url;
</span><span class="lines">@@ -10405,7 +10414,7 @@
</span><span class="cx"> #if ENABLE(DATA_DETECTION)
</span><span class="cx">         // FIXME: Support JavaScript urls here. But make sure they don't show a preview.
</span><span class="cx">         // <rdar://problem/50572283>
</span><del>-        if (!linkURL.protocolIsInHTTPFamily() && !WebCore::DataDetection::canBePresentedByDataDetectors(linkURL)) {
</del><ins>+        if (!linkURL.protocolIsInHTTPFamily() && !WebCore::DataDetection::canBePresentedByDataDetectors(linkURL) && ![strongSelf positionInformationHasImageOverlayDataDetector]) {
</ins><span class="cx">             continueWithContextMenuConfiguration(nil);
</span><span class="cx">             return;
</span><span class="cx">         }
</span><span class="lines">@@ -10449,20 +10458,29 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(DATA_DETECTION)
</span><ins>+
</ins><span class="cx"> - (void)continueContextMenuInteractionWithDataDetectors:(void(^)(UIContextMenuConfiguration *))continueWithContextMenuConfiguration
</span><span class="cx"> {
</span><span class="cx">     BEGIN_BLOCK_OBJC_EXCEPTIONS
</span><span class="cx">     auto ddContextMenuActionClass = getDDContextMenuActionClass();
</span><del>-    URL linkURL = _positionInformation.url;
-    NSDictionary *context = [self dataDetectionContextForPositionInformation:_positionInformation];
-    UIContextMenuConfiguration *configurationFromDD = [ddContextMenuActionClass contextMenuConfigurationForURL:linkURL identifier:_positionInformation.dataDetectorIdentifier selectedText:[self selectedText] results:_positionInformation.dataDetectorResults.get() inView:self context:context menuIdentifier:nil];
</del><ins>+    auto context = retainPtr([self dataDetectionContextForPositionInformation:_positionInformation]);
+    RetainPtr<UIContextMenuConfiguration> configurationFromDataDetectors;
+
+    if (self.positionInformationHasImageOverlayDataDetector) {
+        DDScannerResult *scannerResult = [_positionInformation.dataDetectorResults firstObject];
+        configurationFromDataDetectors = [ddContextMenuActionClass contextMenuConfigurationWithResult:scannerResult.coreResult inView:self context:context.get() menuIdentifier:nil];
+    } else {
+        configurationFromDataDetectors = [ddContextMenuActionClass contextMenuConfigurationForURL:_positionInformation.url identifier:_positionInformation.dataDetectorIdentifier selectedText:[self selectedText] results:_positionInformation.dataDetectorResults.get() inView:self context:context.get() menuIdentifier:nil];
+        _page->startInteractionWithPositionInformation(_positionInformation);
+    }
+
</ins><span class="cx">     _contextMenuActionProviderDelegateNeedsOverride = YES;
</span><del>-    _page->startInteractionWithPositionInformation(_positionInformation);
-    continueWithContextMenuConfiguration(configurationFromDD);
</del><ins>+    continueWithContextMenuConfiguration(configurationFromDataDetectors.get());
</ins><span class="cx">     END_BLOCK_OBJC_EXCEPTIONS
</span><span class="cx"> }
</span><del>-#endif
</del><span class="cx"> 
</span><ins>+#endif // ENABLE(DATA_DETECTION)
+
</ins><span class="cx"> - (NSArray<UIMenuElement *> *)_contextMenuInteraction:(UIContextMenuInteraction *)interaction overrideSuggestedActionsForConfiguration:(UIContextMenuConfiguration *)configuration
</span><span class="cx"> {
</span><span class="cx">     // If we're here we're in the legacy path, which ignores the suggested actions anyway.
</span></span></pre></div>
<a id="trunkSourceWebKitWebKitxcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj (278393 => 278394)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj     2021-06-03 04:57:45 UTC (rev 278393)
+++ trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj        2021-06-03 04:59:05 UTC (rev 278394)
</span><span class="lines">@@ -5985,6 +5985,7 @@
</span><span class="cx">          F4975CF12624B80A003C626E /* WKImageExtractionPreviewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WKImageExtractionPreviewController.h; sourceTree = "<group>"; };
</span><span class="cx">          F4975CF32624B918003C626E /* WKImageExtractionPreviewController.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = WKImageExtractionPreviewController.mm; sourceTree = "<group>"; };
</span><span class="cx">          F4A6D6BB254CA3E900B65FAA /* SharedDisplayListHandle.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SharedDisplayListHandle.h; sourceTree = "<group>"; };
</span><ins>+               F4A7CE842667EB4E00228685 /* ImageExtractionUpdateResult.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ImageExtractionUpdateResult.h; sourceTree = "<group>"; };
</ins><span class="cx">           F4AC655E22A3140E00A05607 /* WebPreferencesDefaultValuesIOS.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = WebPreferencesDefaultValuesIOS.mm; path = ios/WebPreferencesDefaultValuesIOS.mm; sourceTree = "<group>"; };
</span><span class="cx">          F4B378D021DDBBAB0095A378 /* WebUndoStepID.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WebUndoStepID.h; sourceTree = "<group>"; };
</span><span class="cx">          F4BA33F025757E89000A3CE8 /* WKImageExtractionGestureRecognizer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = WKImageExtractionGestureRecognizer.h; path = ios/WKImageExtractionGestureRecognizer.h; sourceTree = "<group>"; };
</span><span class="lines">@@ -6719,6 +6720,7 @@
</span><span class="cx">                          46AC532425DED81E003B57EC /* GPUProcessConnectionParameters.h */,
</span><span class="cx">                          F40BBB40257FF46E0067463A /* GPUProcessWakeupMessageArguments.h */,
</span><span class="cx">                          1AC75A1A1B3368270056745B /* HangDetectionDisabler.h */,
</span><ins>+                               F4A7CE842667EB4E00228685 /* ImageExtractionUpdateResult.h */,
</ins><span class="cx">                           BCCF6B2312C93E7A008F9C35 /* ImageOptions.h */,
</span><span class="cx">                          999B7ED82550E4A800F450A4 /* InspectorExtensionTypes.cpp */,
</span><span class="cx">                          99BE3B1625433B9400C6551C /* InspectorExtensionTypes.h */,
</span></span></pre></div>
<a id="trunkSourceWebKitWebProcessWebPageWebPagecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp (278393 => 278394)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp       2021-06-03 04:57:45 UTC (rev 278393)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp  2021-06-03 04:59:05 UTC (rev 278394)
</span><span class="lines">@@ -40,6 +40,7 @@
</span><span class="cx"> #include "FormDataReference.h"
</span><span class="cx"> #include "FrameTreeNodeData.h"
</span><span class="cx"> #include "GeolocationPermissionRequestManager.h"
</span><ins>+#include "ImageExtractionUpdateResult.h"
</ins><span class="cx"> #include "InjectUserScriptImmediately.h"
</span><span class="cx"> #include "InjectedBundle.h"
</span><span class="cx"> #include "InjectedBundleScriptWorld.h"
</span><span class="lines">@@ -4063,6 +4064,23 @@
</span><span class="cx">     completionHandler(WTFMove(mainFrameResult));
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+std::optional<std::pair<Ref<WebCore::HTMLElement>, WebCore::IntRect>> WebPage::findDataDetectionResultElementInImageOverlay(const FloatPoint& location, const HTMLElement& imageOverlayHost)
+{
+    Vector<Ref<HTMLElement>> dataDetectorElements;
+    for (auto& child : descendantsOfType<HTMLElement>(*imageOverlayHost.shadowRoot())) {
+        if (child.isImageOverlayDataDetectorResult())
+            dataDetectorElements.append(child);
+    }
+
+    for (auto& element : dataDetectorElements) {
+        auto elementBounds = element->boundsInRootViewSpace();
+        if (elementBounds.contains(roundedIntPoint(location)))
+            return {{ WTFMove(element), elementBounds }};
+    }
+
+    return std::nullopt;
+}
+
</ins><span class="cx"> #endif // ENABLE(DATA_DETECTION)
</span><span class="cx"> 
</span><span class="cx"> #if PLATFORM(COCOA)
</span><span class="lines">@@ -7458,11 +7476,11 @@
</span><span class="cx">     });
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void WebPage::updateWithImageExtractionResult(ImageExtractionResult&& result, const ElementContext& context, const FloatPoint& location, CompletionHandler<void(bool)>&& completionHandler)
</del><ins>+void WebPage::updateWithImageExtractionResult(ImageExtractionResult&& result, const ElementContext& context, const FloatPoint& location, CompletionHandler<void(ImageExtractionUpdateResult)>&& completionHandler)
</ins><span class="cx"> {
</span><span class="cx">     auto elementToUpdate = elementForContext(context);
</span><span class="cx">     if (!is<HTMLElement>(elementToUpdate)) {
</span><del>-        completionHandler(false);
</del><ins>+        completionHandler(ImageExtractionUpdateResult::NoText);
</ins><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -7474,12 +7492,22 @@
</span><span class="cx">     });
</span><span class="cx"> 
</span><span class="cx">     auto nodeAtLocation = makeRefPtr(hitTestResult.innerNonSharedNode());
</span><del>-    if (!nodeAtLocation || nodeAtLocation->shadowHost() != elementToUpdate) {
-        completionHandler(false);
-        return;
-    }
</del><ins>+    auto updateResult = ([&] {
+        if (!nodeAtLocation || nodeAtLocation->shadowHost() != elementToUpdate || !HTMLElement::isInsideImageOverlay(*nodeAtLocation))
+            return ImageExtractionUpdateResult::NoText;
</ins><span class="cx"> 
</span><del>-    completionHandler(HTMLElement::isImageOverlayText(*nodeAtLocation));
</del><ins>+#if ENABLE(DATA_DETECTION)
+        if (findDataDetectionResultElementInImageOverlay(location, downcast<HTMLElement>(*elementToUpdate)))
+            return ImageExtractionUpdateResult::DataDetector;
+#endif
+
+        if (HTMLElement::isImageOverlayText(*nodeAtLocation))
+            return ImageExtractionUpdateResult::Text;
+
+        return ImageExtractionUpdateResult::NoText;
+    })();
+
+    completionHandler(updateResult);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> #endif // ENABLE(IMAGE_EXTRACTION)
</span></span></pre></div>
<a id="trunkSourceWebKitWebProcessWebPageWebPageh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/WebProcess/WebPage/WebPage.h (278393 => 278394)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/WebProcess/WebPage/WebPage.h 2021-06-03 04:57:45 UTC (rev 278393)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebPage.h    2021-06-03 04:59:05 UTC (rev 278394)
</span><span class="lines">@@ -310,6 +310,7 @@
</span><span class="cx"> 
</span><span class="cx"> enum class FindOptions : uint16_t;
</span><span class="cx"> enum class DragControllerAction : uint8_t;
</span><ins>+enum class ImageExtractionUpdateResult : uint8_t;
</ins><span class="cx"> enum class SyntheticEditingCommandType : uint8_t;
</span><span class="cx"> 
</span><span class="cx"> struct BackForwardListItemState;
</span><span class="lines">@@ -1153,6 +1154,8 @@
</span><span class="cx">     void setDataDetectionResults(NSArray *);
</span><span class="cx">     void detectDataInAllFrames(uint64_t, CompletionHandler<void(const DataDetectionResult&)>&&);
</span><span class="cx">     void removeDataDetectedLinks(CompletionHandler<void(const DataDetectionResult&)>&&);
</span><ins>+    void handleClickForDataDetectionResult(const WebCore::DataDetectorElementInfo&, const WebCore::IntPoint&);
+    static std::optional<std::pair<Ref<WebCore::HTMLElement>, WebCore::IntRect>> findDataDetectionResultElementInImageOverlay(const WebCore::FloatPoint& locationInRootView, const WebCore::HTMLElement& host);
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx">     unsigned extendIncrementalRenderingSuppression();
</span><span class="lines">@@ -1176,10 +1179,6 @@
</span><span class="cx">     void handleSelectionServiceClick(WebCore::FrameSelection&, const Vector<String>& telephoneNumbers, const WebCore::IntPoint&);
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><del>-#if ENABLE(DATA_DETECTION)
-    void handleClickForDataDetectionResult(const WebCore::DataDetectorElementInfo&, const WebCore::IntPoint&);
-#endif
-
</del><span class="cx">     void didChangeScrollOffsetForFrame(WebCore::Frame*);
</span><span class="cx"> 
</span><span class="cx">     void setMainFrameProgressCompleted(bool completed) { m_mainFrameProgressCompleted = completed; }
</span><span class="lines">@@ -1404,7 +1403,7 @@
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(IMAGE_EXTRACTION)
</span><span class="cx">     void requestImageExtraction(WebCore::Element&, CompletionHandler<void(RefPtr<WebCore::Element>&&)>&&);
</span><del>-    void updateWithImageExtractionResult(WebCore::ImageExtractionResult&&, const WebCore::ElementContext&, const WebCore::FloatPoint& location, CompletionHandler<void(bool)>&&);
</del><ins>+    void updateWithImageExtractionResult(WebCore::ImageExtractionResult&&, const WebCore::ElementContext&, const WebCore::FloatPoint& location, CompletionHandler<void(ImageExtractionUpdateResult)>&&);
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx"> #if HAVE(TRANSLATION_UI_SERVICES) && ENABLE(CONTEXT_MENUS)
</span></span></pre></div>
<a id="trunkSourceWebKitWebProcessWebPageWebPagemessagesin"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in (278393 => 278394)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in       2021-06-03 04:57:45 UTC (rev 278393)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in  2021-06-03 04:59:05 UTC (rev 278394)
</span><span class="lines">@@ -643,6 +643,6 @@
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(IMAGE_EXTRACTION)
</span><del>-    UpdateWithImageExtractionResult(struct WebCore::ImageExtractionResult result, struct WebCore::ElementContext element, WebCore::FloatPoint location) -> (bool textExistsAtLocation) Async
</del><ins>+    UpdateWithImageExtractionResult(struct WebCore::ImageExtractionResult result, struct WebCore::ElementContext element, WebCore::FloatPoint location) -> (enum:uint8_t WebKit::ImageExtractionUpdateResult result) Async
</ins><span class="cx"> #endif
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebKitWebProcessWebPageiosWebPageIOSmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm (278393 => 278394)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm 2021-06-03 04:57:45 UTC (rev 278393)
+++ trunk/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm    2021-06-03 04:59:05 UTC (rev 278394)
</span><span class="lines">@@ -148,6 +148,7 @@
</span><span class="cx"> #import <wtf/SetForScope.h>
</span><span class="cx"> #import <wtf/SoftLinking.h>
</span><span class="cx"> #import <wtf/cocoa/Entitlements.h>
</span><ins>+#import <wtf/text/StringToIntegerConversion.h>
</ins><span class="cx"> #import <wtf/text/TextStream.h>
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(ATTACHMENT_ELEMENT)
</span><span class="lines">@@ -2747,6 +2748,7 @@
</span><span class="cx">         return;
</span><span class="cx">     
</span><span class="cx">     info.isDataDetectorLink = true;
</span><ins>+    info.dataDetectorBounds = info.bounds;
</ins><span class="cx">     const int dataDetectionExtendedContextLength = 350;
</span><span class="cx">     info.dataDetectorIdentifier = DataDetection::dataDetectorIdentifier(element);
</span><span class="cx">     if (auto* results = element.document().frame()->dataDetectionResultsIfExists())
</span><span class="lines">@@ -2762,8 +2764,39 @@
</span><span class="cx">         dataDetectionExtendedContextLength, SelectionDirection::Forward));
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-#endif
</del><ins>+static void dataDetectorImageOverlayPositionInformation(const HTMLElement& overlayHost, const InteractionInformationRequest& request, InteractionInformationAtPosition& info)
+{
+    auto frame = makeRefPtr(overlayHost.document().frame());
+    if (!frame)
+        return;
</ins><span class="cx"> 
</span><ins>+    auto elementAndBounds = WebPage::findDataDetectionResultElementInImageOverlay(request.point, overlayHost);
+    if (!elementAndBounds)
+        return;
+
+    auto [foundElement, elementBounds] = *elementAndBounds;
+    auto identifierValue = parseInteger<uint64_t>(foundElement->attributeWithoutSynchronization(HTMLNames::x_apple_data_detectors_resultAttr));
+    if (!identifierValue)
+        return;
+
+    auto identifier = makeObjectIdentifier<ImageOverlayDataDetectionResultIdentifierType>(*identifierValue);
+    if (!identifier.isValid())
+        return;
+
+    auto* dataDetectionResults = frame->dataDetectionResultsIfExists();
+    if (!dataDetectionResults)
+        return;
+
+    auto dataDetectionResult = retainPtr(dataDetectionResults->imageOverlayDataDetectionResult(identifier));
+    if (!dataDetectionResult)
+        return;
+
+    info.dataDetectorBounds = WTFMove(elementBounds);
+    info.dataDetectorResults = @[ dataDetectionResult.get() ];
+}
+
+#endif // ENABLE(DATA_DETECTION)
+
</ins><span class="cx"> static std::optional<std::pair<RenderImage&, Image&>> imageRendererAndImage(Element& element)
</span><span class="cx"> {
</span><span class="cx">     if (!is<RenderImage>(element.renderer()))
</span><span class="lines">@@ -2863,6 +2896,11 @@
</span><span class="cx">         boundsPositionInformation(*renderer, info);
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+#if ENABLE(DATA_DETECTION)
+    if (info.isImageOverlayText && is<HTMLElement>(element))
+        dataDetectorImageOverlayPositionInformation(downcast<HTMLElement>(element), request, info);
+#endif
+
</ins><span class="cx">     info.elementContext = page.contextForElement(element);
</span><span class="cx"> }
</span><span class="cx">     
</span></span></pre>
</div>
</div>

</body>
</html>