Implement action menus for data detected items
authortimothy_horton@apple.com <timothy_horton@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 29 Oct 2014 18:48:23 +0000 (18:48 +0000)
committertimothy_horton@apple.com <timothy_horton@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 29 Oct 2014 18:48:23 +0000 (18:48 +0000)
https://bugs.webkit.org/show_bug.cgi?id=138178
<rdar://problem/18709436>

Reviewed by Anders Carlsson.

* WebCore.exp.in:
Export a symbol from Position that we need.

* WebCore.xcodeproj/project.pbxproj:
* platform/spi/mac/DataDetectorsSPI.h:
Add a combined SPI header for all of the random bits of DataDetectors that we use.

* Shared/API/c/WKActionMenuTypes.h:
Add a new type.

* Shared/WebHitTestResult.cpp:
(WebKit::WebHitTestResult::Data::Data):
(WebKit::WebHitTestResult::Data::encode):
(WebKit::WebHitTestResult::Data::decode):
* Shared/WebHitTestResult.h:
(WebKit::WebHitTestResult::isTextNode):
Determine, store, encode, and decode whether or not the hit node is a text node.

* Shared/mac/ActionMenuHitTestResult.h:
* Shared/mac/ActionMenuHitTestResult.mm: Renamed from Source/WebKit2/Shared/mac/ActionMenuHitTestResult.cpp.
(WebKit::ActionMenuHitTestResult::encode):
(WebKit::ActionMenuHitTestResult::decode):
Make ActionMenuHitTestResult an Obj-C++ file.
Store, encode, and decode (securely!) a DDActionContext and FloatRect
representing the bounding box of the data detected item, if any.

* UIProcess/API/mac/WKView.mm:
(-[WKView initWithFrame:context:configuration:webView:]):
(-[WKView willOpenMenu:withEvent:]): Deleted.
Stop using willOpenMenu; we'll use NSMenuDelegate's menuNeedsUpdate: instead.
Hook up WKActionMenuController as our action menu's delegate.

* UIProcess/mac/WKActionMenuController.mm:
(-[WKActionMenuController prepareForMenu:withEvent:]):
Call _updateActionMenuItems *after* we've adjusted _state, so that it
can depend on the value being correct.

(-[WKActionMenuController willOpenMenu:withEvent:]):
(-[WKActionMenuController didPerformActionMenuHitTest:]):
Move menu updating to menuNeedsUpdate for more accurate timing.

(_updateActionMenuItems):
When building the menu, if we have a text node that is not a link,
and hit a data detected item, retrieve the menu from the DDActionContext.
If we have nothing, make sure to reset _type, and if the final hit-test
is still pending, build a menu with a dummy item.

* WebKit2.xcodeproj/project.pbxproj:
* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::performActionMenuHitTestAtLocation): Moved to WebPageMac.
* WebProcess/WebPage/mac/WebPageMac.mm:
(WebKit::rangeExpandedAroundPosition):
Factor this out of performDictionaryLookupAtLocation.

(WebKit::WebPage::performDictionaryLookupAtLocation):
Make use of rangeExpandedAroundPosition.

(WebKit::scanForDataDetectedItems):
Expand to four lines of context around the hit point.
Convert that range to plain text, and feed it to DataDetectors.
Find the result that intersects the hit point, and make a DDActionContext
for it. Also, store the bounding box of the first quad of the detected
text, to provide to Data Detectors as a hint for UI placement.

(WebKit::WebPage::performActionMenuHitTestAtLocation):
If the hit node is a text node, call scanForDataDetectedItems and
store the resultant DDActionContext and bounding rect on our
ActionMenuHitTestResult for transfer to the UI process.

* WebKitSystemInterface.h:
* libWebKitSystemInterfaceMavericks.a:
* libWebKitSystemInterfaceMountainLion.a:
* libWebKitSystemInterfaceYosemite.a:
Update WebKitSystemInterface.

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

21 files changed:
Source/WebCore/ChangeLog
Source/WebCore/WebCore.exp.in
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/platform/spi/mac/DataDetectorsSPI.h [new file with mode: 0644]
Source/WebKit2/ChangeLog
Source/WebKit2/Shared/API/c/WKActionMenuTypes.h
Source/WebKit2/Shared/WebHitTestResult.cpp
Source/WebKit2/Shared/WebHitTestResult.h
Source/WebKit2/Shared/mac/ActionMenuHitTestResult.h
Source/WebKit2/Shared/mac/ActionMenuHitTestResult.mm [moved from Source/WebKit2/Shared/mac/ActionMenuHitTestResult.cpp with 55% similarity]
Source/WebKit2/UIProcess/API/mac/WKView.mm
Source/WebKit2/UIProcess/mac/WKActionMenuController.h
Source/WebKit2/UIProcess/mac/WKActionMenuController.mm
Source/WebKit2/WebKit2.xcodeproj/project.pbxproj
Source/WebKit2/WebProcess/WebPage/WebPage.cpp
Source/WebKit2/WebProcess/WebPage/mac/WebPageMac.mm
WebKitLibraries/ChangeLog
WebKitLibraries/WebKitSystemInterface.h
WebKitLibraries/libWebKitSystemInterfaceMavericks.a
WebKitLibraries/libWebKitSystemInterfaceMountainLion.a
WebKitLibraries/libWebKitSystemInterfaceYosemite.a

index 322d860..ac69c3f 100644 (file)
@@ -1,3 +1,18 @@
+2014-10-29  Tim Horton  <timothy_horton@apple.com>
+
+        Implement action menus for data detected items
+        https://bugs.webkit.org/show_bug.cgi?id=138178
+        <rdar://problem/18709436>
+
+        Reviewed by Anders Carlsson.
+
+        * WebCore.exp.in:
+        Export a symbol from Position that we need.
+
+        * WebCore.xcodeproj/project.pbxproj:
+        * platform/spi/mac/DataDetectorsSPI.h:
+        Add a combined SPI header for all of the random bits of DataDetectors that we use.
+
 2014-10-29  Jer Noble  <jer.noble@apple.com>
 
         [EME] NULL-dereference crash in MediaKeys::setMediaElement().
index e2d8528..e05eed1 100644 (file)
@@ -1342,6 +1342,7 @@ __ZN7WebCore8Gradient12addColorStopEfRKNS_5ColorE
 __ZN7WebCore8GradientC1ERKNS_10FloatPointES3_
 __ZN7WebCore8GradientD1Ev
 __ZN7WebCore8PositionC1EN3WTF10PassRefPtrINS_4NodeEEENS0_10AnchorTypeE
+__ZN7WebCore8PositionC1EN3WTF10PassRefPtrINS_4NodeEEENS0_19LegacyEditingOffsetE
 __ZN7WebCore8PositionC1EN3WTF10PassRefPtrINS_4NodeEEEiNS0_10AnchorTypeE
 __ZN7WebCore8Settings13gQTKitEnabledE
 __ZN7WebCore8Settings14setJavaEnabledEb
index c91c166..936423a 100644 (file)
                2D481F02146B5C5500AA7834 /* CrossfadeGeneratedImage.h in Headers */ = {isa = PBXBuildFile; fileRef = 2D2FC0551460CD6F00263633 /* CrossfadeGeneratedImage.h */; };
                2D481F03146B5C6500AA7834 /* GradientImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2D2FC0561460CD6F00263633 /* GradientImage.cpp */; };
                2D481F04146B5C6B00AA7834 /* GradientImage.h in Headers */ = {isa = PBXBuildFile; fileRef = 2D2FC0571460CD6F00263633 /* GradientImage.h */; };
+               2D59F1BF1A0044C6001F3D29 /* DataDetectorsSPI.h in Headers */ = {isa = PBXBuildFile; fileRef = 2D59F1BE1A0044C6001F3D29 /* DataDetectorsSPI.h */; settings = {ATTRIBUTES = (Private, ); }; };
                2D5A592F152525230036EE51 /* ImageOrientation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A8748D7412CC3F89001FBA41 /* ImageOrientation.cpp */; };
                2D5A5931152525D00036EE51 /* ImageOrientation.h in Headers */ = {isa = PBXBuildFile; fileRef = A8748D6612CC3763001FBA41 /* ImageOrientation.h */; settings = {ATTRIBUTES = (Private, ); }; };
                2D5BC42716F882EE007048D0 /* SecurityPolicyViolationEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = 2D5BC42516F882BE007048D0 /* SecurityPolicyViolationEvent.h */; };
                2D3EF4471917915C00034184 /* WebCoreCALayerExtras.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WebCoreCALayerExtras.mm; sourceTree = "<group>"; };
                2D46F04D17B96FBD005647F0 /* IntPoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IntPoint.cpp; sourceTree = "<group>"; };
                2D46F04F17B96FD2005647F0 /* IntSize.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IntSize.cpp; sourceTree = "<group>"; };
+               2D59F1BE1A0044C6001F3D29 /* DataDetectorsSPI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DataDetectorsSPI.h; sourceTree = "<group>"; };
                2D5BC42516F882BE007048D0 /* SecurityPolicyViolationEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecurityPolicyViolationEvent.h; sourceTree = "<group>"; };
                2D5BC42616F882BE007048D0 /* SecurityPolicyViolationEvent.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = SecurityPolicyViolationEvent.idl; sourceTree = "<group>"; };
                2D5C9CFB19C7B52E00B3C5C1 /* PageOverlay.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PageOverlay.cpp; sourceTree = "<group>"; };
                9348428019F1A9190009D5AE /* mac */ = {
                        isa = PBXGroup;
                        children = (
+                               2D59F1BE1A0044C6001F3D29 /* DataDetectorsSPI.h */,
                                2DCB837719F99BBA00A7FBE4 /* NSSharingServicePickerSPI.h */,
                                2DCB837819F99BBA00A7FBE4 /* NSSharingServiceSPI.h */,
                                9348428119F1A9190009D5AE /* NSViewSPI.h */,
                                8538F05B0AD722F1006A81D1 /* DOMRange.h in Headers */,
                                851EE8210ABCA58100A6AA33 /* DOMRangeException.h in Headers */,
                                8538F05D0AD722F1006A81D1 /* DOMRangeInternal.h in Headers */,
+                               2D59F1BF1A0044C6001F3D29 /* DataDetectorsSPI.h in Headers */,
                                8538F0850AD72CB6006A81D1 /* DOMRanges.h in Headers */,
                                858C38A70AA8F20400B187A4 /* DOMRect.h in Headers */,
                                85E711D60AC5D5350053270F /* DOMRectInternal.h in Headers */,
diff --git a/Source/WebCore/platform/spi/mac/DataDetectorsSPI.h b/Source/WebCore/platform/spi/mac/DataDetectorsSPI.h
new file mode 100644 (file)
index 0000000..f528250
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2014 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 "SoftLinking.h"
+#import <objc/runtime.h>
+
+typedef struct __DDScanner DDScanner, *DDScannerRef;
+typedef struct __DDScanQuery *DDScanQueryRef;
+typedef struct __DDResult *DDResultRef;
+
+typedef enum {
+    DDScannerTypeStandard = 0,
+} DDScannerType;
+
+enum {
+    DDScannerOptionStopAtFirstMatch = 1,
+};
+typedef CFIndex DDScannerOptions;
+
+enum {
+    DDScannerCopyResultsOptionsNone = 0,
+    DDScannerCopyResultsOptionsNoOverlap = 1 << 0,
+};
+typedef CFIndex DDScannerCopyResultsOptions;
+
+SOFT_LINK_PRIVATE_FRAMEWORK_OPTIONAL(DataDetectors)
+SOFT_LINK_PRIVATE_FRAMEWORK_OPTIONAL(DataDetectorsCore)
+
+extern "C" {
+
+SOFT_LINK(DataDetectorsCore, DDScannerCreate, DDScannerRef, (DDScannerType type, DDScannerOptions options, CFErrorRef* errorRef), (type, options, errorRef))
+SOFT_LINK(DataDetectorsCore, DDScanQueryCreateFromString, DDScanQueryRef, (CFAllocatorRef allocator, CFStringRef string, CFRange range), (allocator, string, range))
+SOFT_LINK(DataDetectorsCore, DDScannerScanQuery, DDScanQueryRef, (DDScannerRef scanner, DDScanQueryRef query), (scanner, query))
+SOFT_LINK(DataDetectorsCore, DDScannerCopyResultsWithOptions, CFArrayRef, (DDScannerRef scanner, DDScannerCopyResultsOptions options), (scanner, options))
+SOFT_LINK(DataDetectorsCore, DDResultGetRange, CFRange, (DDResultRef result), (result))
+
+}
+
+SOFT_LINK_CLASS(DataDetectors, DDActionContext)
+SOFT_LINK_CLASS(DataDetectors, DDActionsManager)
+
+@interface DDActionContext : NSObject <NSCopying, NSSecureCoding>
+
+@property NSRect highlightFrame;
+@property (retain) NSArray *allResults;
+@property (retain) __attribute__((NSObject)) DDResultRef mainResult;
+
+@end
+
+@interface DDActionsManager : NSObject
+
++ (DDActionsManager *)sharedManager;
+- (NSArray *)menuItemsForResult:(DDResultRef)result actionContext:(DDActionContext *)context;
+
+@end
index 1061071..1ec81c2 100644 (file)
@@ -1,3 +1,73 @@
+2014-10-29  Tim Horton  <timothy_horton@apple.com>
+
+        Implement action menus for data detected items
+        https://bugs.webkit.org/show_bug.cgi?id=138178
+        <rdar://problem/18709436>
+
+        Reviewed by Anders Carlsson.
+
+        * Shared/API/c/WKActionMenuTypes.h:
+        Add a new type.
+
+        * Shared/WebHitTestResult.cpp:
+        (WebKit::WebHitTestResult::Data::Data):
+        (WebKit::WebHitTestResult::Data::encode):
+        (WebKit::WebHitTestResult::Data::decode):
+        * Shared/WebHitTestResult.h:
+        (WebKit::WebHitTestResult::isTextNode):
+        Determine, store, encode, and decode whether or not the hit node is a text node.
+
+        * Shared/mac/ActionMenuHitTestResult.h:
+        * Shared/mac/ActionMenuHitTestResult.mm: Renamed from Source/WebKit2/Shared/mac/ActionMenuHitTestResult.cpp.
+        (WebKit::ActionMenuHitTestResult::encode):
+        (WebKit::ActionMenuHitTestResult::decode):
+        Make ActionMenuHitTestResult an Obj-C++ file.
+        Store, encode, and decode (securely!) a DDActionContext and FloatRect
+        representing the bounding box of the data detected item, if any.
+
+        * UIProcess/API/mac/WKView.mm:
+        (-[WKView initWithFrame:context:configuration:webView:]):
+        (-[WKView willOpenMenu:withEvent:]): Deleted.
+        Stop using willOpenMenu; we'll use NSMenuDelegate's menuNeedsUpdate: instead.
+        Hook up WKActionMenuController as our action menu's delegate.
+
+        * UIProcess/mac/WKActionMenuController.mm:
+        (-[WKActionMenuController prepareForMenu:withEvent:]):
+        Call _updateActionMenuItems *after* we've adjusted _state, so that it
+        can depend on the value being correct.
+
+        (-[WKActionMenuController willOpenMenu:withEvent:]):
+        (-[WKActionMenuController didPerformActionMenuHitTest:]):
+        Move menu updating to menuNeedsUpdate for more accurate timing.
+
+        (_updateActionMenuItems):
+        When building the menu, if we have a text node that is not a link,
+        and hit a data detected item, retrieve the menu from the DDActionContext.
+        If we have nothing, make sure to reset _type, and if the final hit-test
+        is still pending, build a menu with a dummy item.
+
+        * WebKit2.xcodeproj/project.pbxproj:
+        * WebProcess/WebPage/WebPage.cpp:
+        (WebKit::WebPage::performActionMenuHitTestAtLocation): Moved to WebPageMac.
+        * WebProcess/WebPage/mac/WebPageMac.mm:
+        (WebKit::rangeExpandedAroundPosition):
+        Factor this out of performDictionaryLookupAtLocation.
+
+        (WebKit::WebPage::performDictionaryLookupAtLocation):
+        Make use of rangeExpandedAroundPosition.
+
+        (WebKit::scanForDataDetectedItems):
+        Expand to four lines of context around the hit point.
+        Convert that range to plain text, and feed it to DataDetectors.
+        Find the result that intersects the hit point, and make a DDActionContext
+        for it. Also, store the bounding box of the first quad of the detected
+        text, to provide to Data Detectors as a hint for UI placement.
+
+        (WebKit::WebPage::performActionMenuHitTestAtLocation):
+        If the hit node is a text node, call scanForDataDetectedItems and
+        store the resultant DDActionContext and bounding rect on our
+        ActionMenuHitTestResult for transfer to the UI process.
+
 2014-10-29  Joseph Pecoraro  <pecoraro@apple.com>
 
         [iOS] iPad: Occasional <select> crashes attempting to scroll to non-existing row 0 in viewWillAppear
index 6a129a7..2427902 100644 (file)
@@ -35,7 +35,8 @@ extern "C" {
 enum {
     kWKActionMenuNone = 0,
     kWKActionMenuLink,
-    kWKActionMenuImage
+    kWKActionMenuImage,
+    kWKActionMenuDataDetectedItem
 };
 typedef uint32_t _WKActionMenuType;
 
index 0974e43..49ae714 100644 (file)
@@ -53,6 +53,7 @@ WebHitTestResult::Data::Data(const HitTestResult& hitTestResult)
     , elementBoundingBox(elementBoundingBoxInWindowCoordinates(hitTestResult))
     , isScrollbar(hitTestResult.scrollbar())
     , isSelected(hitTestResult.isSelected())
+    , isTextNode(hitTestResult.innerNode() && hitTestResult.innerNode()->isTextNode())
 {
 }
 
@@ -72,6 +73,7 @@ void WebHitTestResult::Data::encode(IPC::ArgumentEncoder& encoder) const
     encoder << elementBoundingBox;
     encoder << isScrollbar;
     encoder << isSelected;
+    encoder << isTextNode;
 }
 
 bool WebHitTestResult::Data::decode(IPC::ArgumentDecoder& decoder, WebHitTestResult::Data& hitTestResultData)
@@ -85,7 +87,8 @@ bool WebHitTestResult::Data::decode(IPC::ArgumentDecoder& decoder, WebHitTestRes
         || !decoder.decode(hitTestResultData.isContentEditable)
         || !decoder.decode(hitTestResultData.elementBoundingBox)
         || !decoder.decode(hitTestResultData.isScrollbar)
-        || !decoder.decode(hitTestResultData.isSelected))
+        || !decoder.decode(hitTestResultData.isSelected)
+        || !decoder.decode(hitTestResultData.isTextNode))
         return false;
 
     return true;
index b942cdd..39a05eb 100644 (file)
@@ -53,6 +53,7 @@ public:
         WebCore::IntRect elementBoundingBox;
         bool isScrollbar;
         bool isSelected;
+        bool isTextNode;
 
         Data();
         explicit Data(const WebCore::HitTestResult&);
@@ -82,6 +83,8 @@ public:
 
     bool isSelected() const { return m_data.isSelected; }
 
+    bool isTextNode() const { return m_data.isTextNode; }
+
 private:
     explicit WebHitTestResult(const WebHitTestResult::Data& hitTestResultData)
         : m_data(hitTestResultData)
index 2dca549..c352f03 100644 (file)
@@ -27,6 +27,9 @@
 #define ActionMenuHitTestResult_h
 
 #include "ShareableBitmap.h"
+#include <WebCore/FloatRect.h>
+
+OBJC_CLASS DDActionContext;
 
 namespace IPC {
 class ArgumentDecoder;
@@ -40,6 +43,9 @@ struct ActionMenuHitTestResult {
     static bool decode(IPC::ArgumentDecoder&, ActionMenuHitTestResult&);
 
     RefPtr<ShareableBitmap> image;
+
+    RetainPtr<DDActionContext> actionContext;
+    WebCore::FloatRect actionBoundingBox;
 };
 
 } // namespace WebKit
  * THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include "config.h"
-#include "ActionMenuHitTestResult.h"
+#import "config.h"
+#import "ActionMenuHitTestResult.h"
 
-#include "ArgumentDecoder.h"
-#include "ArgumentEncoder.h"
+#import "ArgumentCodersCF.h"
+#import "ArgumentDecoder.h"
+#import "ArgumentEncoder.h"
+#import "WebCoreArgumentCoders.h"
+#import <WebCore/DataDetectorsSPI.h>
 
 namespace WebKit {
 
@@ -40,6 +43,20 @@ void ActionMenuHitTestResult::encode(IPC::ArgumentEncoder& encoder) const
         image->createHandle(handle, SharedMemory::ReadOnly);
 
     encoder << handle;
+
+    bool hasActionContext = actionContext;
+    encoder << hasActionContext;
+    if (hasActionContext) {
+        RetainPtr<NSMutableData> data = adoptNS([[NSMutableData alloc] init]);
+        RetainPtr<NSKeyedArchiver> archiver = adoptNS([[NSKeyedArchiver alloc] initForWritingWithMutableData:data.get()]);
+        [archiver setRequiresSecureCoding:YES];
+        [archiver encodeObject:actionContext.get() forKey:@"actionContext"];
+        [archiver finishEncoding];
+
+        IPC::encode(encoder, reinterpret_cast<CFDataRef>(data.get()));
+    }
+
+    encoder << actionBoundingBox;
 }
 
 bool ActionMenuHitTestResult::decode(IPC::ArgumentDecoder& decoder, ActionMenuHitTestResult& actionMenuHitTestResult)
@@ -51,6 +68,30 @@ bool ActionMenuHitTestResult::decode(IPC::ArgumentDecoder& decoder, ActionMenuHi
     if (!handle.isNull())
         actionMenuHitTestResult.image = ShareableBitmap::create(handle, SharedMemory::ReadOnly);
 
+    bool hasActionContext;
+    if (!decoder.decode(hasActionContext))
+        return false;
+
+    if (hasActionContext) {
+        RetainPtr<CFDataRef> data;
+        if (!IPC::decode(decoder, data))
+            return false;
+
+        RetainPtr<NSKeyedUnarchiver> unarchiver = adoptNS([[NSKeyedUnarchiver alloc] initForReadingWithData:(NSData *)data.get()]);
+        [unarchiver setRequiresSecureCoding:YES];
+        @try {
+            actionMenuHitTestResult.actionContext = [unarchiver decodeObjectOfClass:getDDActionContextClass() forKey:@"actionContext"];
+        } @catch (NSException *exception) {
+            LOG_ERROR("Failed to decode DDActionContext: %@", exception);
+            return false;
+        }
+        
+        [unarchiver finishDecoding];
+    }
+
+    if (!decoder.decode(actionMenuHitTestResult.actionBoundingBox))
+        return false;
+
     return true;
 }
     
index bd8ae21..4fac357 100644 (file)
@@ -3538,6 +3538,7 @@ static NSString *pathWithUniqueFilenameForPath(NSString *path)
         RetainPtr<NSMenu> menu = adoptNS([[NSMenu alloc] init]);
         self.actionMenu = menu.get();
         _data->_actionMenuController = adoptNS([[WKActionMenuController alloc] initWithPage:*_data->_page view:self]);
+        self.actionMenu.delegate = _data->_actionMenuController.get();
     }
 
     return self;
@@ -3642,11 +3643,6 @@ static NSString *pathWithUniqueFilenameForPath(NSString *path)
     [_data->_actionMenuController prepareForMenu:menu withEvent:event];
 }
 
-- (void)willOpenMenu:(NSMenu *)menu withEvent:(NSEvent *)event
-{
-    [_data->_actionMenuController willOpenMenu:menu withEvent:event];
-}
-
 - (void)didCloseMenu:(NSMenu *)menu withEvent:(NSEvent *)event
 {
     [_data->_actionMenuController didCloseMenu:menu withEvent:event];
index 143dd12..443c2cc 100644 (file)
@@ -44,7 +44,7 @@ enum class ActionMenuState {
 
 @class WKView;
 
-@interface WKActionMenuController : NSObject {
+@interface WKActionMenuController : NSObject <NSMenuDelegate> {
 @private
     WebKit::WebPageProxy *_page;
     WKView *_wkView;
@@ -59,7 +59,6 @@ enum class ActionMenuState {
 - (void)willDestroyView:(WKView *)view;
 
 - (void)prepareForMenu:(NSMenu *)menu withEvent:(NSEvent *)event;
-- (void)willOpenMenu:(NSMenu *)menu withEvent:(NSEvent *)event;
 - (void)didCloseMenu:(NSMenu *)menu withEvent:(NSEvent *)event;
 
 - (void)didPerformActionMenuHitTest:(const WebKit::ActionMenuHitTestResult&)hitTestResult;
index 46d2348..5586a15 100644 (file)
 #import "WKNSURLExtras.h"
 #import "WKViewInternal.h"
 #import "WebContext.h"
+#import "WebKitSystemInterface.h"
 #import "WebPageMessages.h"
 #import "WebPageProxy.h"
 #import "WebPageProxyMessages.h"
 #import "WebProcessProxy.h"
+#import <Foundation/Foundation.h>
 #import <ImageIO/ImageIO.h>
 #import <ImageKit/ImageKit.h>
+#import <WebCore/DataDetectorsSPI.h>
 #import <WebCore/NSSharingServicePickerSPI.h>
 #import <WebCore/NSViewSPI.h>
 #import <WebCore/SoftLinking.h>
@@ -94,29 +97,10 @@ using namespace WebKit;
     if (menu != _wkView.actionMenu)
         return;
 
-    [self _updateActionMenuItems];
-
     _page->performActionMenuHitTestAtLocation([_wkView convertPoint:event.locationInWindow fromView:nil]);
 
     _state = ActionMenuState::Pending;
-}
-
-- (void)willOpenMenu:(NSMenu *)menu withEvent:(NSEvent *)event
-{
-    if (menu != _wkView.actionMenu)
-        return;
-
-    ASSERT(_state != ActionMenuState::None);
-
-    // FIXME: We need to be able to cancel this if the menu goes away.
-    // FIXME: Connection can be null if the process is closed; we should clean up better in that case.
-    if (_state == ActionMenuState::Pending) {
-        if (auto* connection = _page->process().connection())
-            connection->waitForAndDispatchImmediately<Messages::WebPageProxy::DidPerformActionMenuHitTest>(_page->pageID(), std::chrono::milliseconds(500));
-    }
-
-    if (_state == ActionMenuState::Ready)
-        [self _updateActionMenuItems];
+    [self _updateActionMenuItems];
 }
 
 - (void)didCloseMenu:(NSMenu *)menu withEvent:(NSEvent *)event
@@ -297,6 +281,25 @@ static NSString *pathToPhotoOnDisk(NSString *suggestedFilename)
     });
 }
 
+#pragma mark NSMenuDelegate implementation
+
+- (void)menuNeedsUpdate:(NSMenu *)menu
+{
+    if (menu != _wkView.actionMenu)
+        return;
+
+    ASSERT(_state != ActionMenuState::None);
+
+    // FIXME: We need to be able to cancel this if the menu goes away.
+    // FIXME: Connection can be null if the process is closed; we should clean up better in that case.
+    if (_state == ActionMenuState::Pending) {
+        if (auto* connection = _page->process().connection())
+            connection->waitForAndDispatchImmediately<Messages::WebPageProxy::DidPerformActionMenuHitTest>(_page->pageID(), std::chrono::milliseconds(500));
+    }
+
+    [self _updateActionMenuItems];
+}
+
 #pragma mark NSSharingServicePickerDelegate implementation
 
 - (id <NSSharingServiceDelegate>)sharingServicePicker:(NSSharingServicePicker *)sharingServicePicker delegateForSharingService:(NSSharingService *)sharingService
@@ -385,13 +388,28 @@ static NSImage *webKitBundleImageNamed(NSString *name)
         if (!hitTestResult->absoluteImageURL().isEmpty() && _hitTestResult.image) {
             _type = kWKActionMenuImage;
             return [self _defaultMenuItemsForImage];
-        } if (!hitTestResult->absoluteLinkURL().isEmpty()) {
+        }
+
+        if (!hitTestResult->absoluteLinkURL().isEmpty()) {
             _type = kWKActionMenuLink;
             return [self _defaultMenuItemsForLink];
         }
+
+        if (hitTestResult->isTextNode()) {
+            if (DDActionContext *actionContext = _hitTestResult.actionContext.get()) {
+                WKSetDDActionContextIsForActionMenu(actionContext);
+                actionContext.highlightFrame = [_wkView.window convertRectToScreen:[_wkView convertRect:_hitTestResult.actionBoundingBox toView:nil]];
+                NSArray *dataDetectorMenuItems = [[getDDActionsManagerClass() sharedManager] menuItemsForResult:[_hitTestResult.actionContext mainResult] actionContext:actionContext];
+                if (dataDetectorMenuItems.count) {
+                    _type = kWKActionMenuDataDetectedItem;
+                    return dataDetectorMenuItems;
+                }
+            }
+        }
     }
 
-    return @[ ];
+    _type = kWKActionMenuNone;
+    return _state != ActionMenuState::Ready ? @[ [NSMenuItem separatorItem] ] : @[ ];
 }
 
 - (void)_updateActionMenuItems
index a86243d..d8a4ebc 100644 (file)
                2D2ADF0916362DD500197E47 /* PDFPluginTextAnnotation.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2D2ADF0616362DC700197E47 /* PDFPluginTextAnnotation.mm */; };
                2D2ADF0B16362DDB00197E47 /* PDFPluginAnnotation.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2D2ADF031636243500197E47 /* PDFPluginAnnotation.mm */; };
                2D2ADF1016364D8200197E47 /* PDFPluginChoiceAnnotation.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2D2ADF0E16364D8200197E47 /* PDFPluginChoiceAnnotation.mm */; };
-               2D353B1219F8305D000EEACD /* ActionMenuHitTestResult.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2D353B1019F8305D000EEACD /* ActionMenuHitTestResult.cpp */; };
+               2D353B1219F8305D000EEACD /* ActionMenuHitTestResult.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2D353B1019F8305D000EEACD /* ActionMenuHitTestResult.mm */; };
                2D353B1319F8305D000EEACD /* ActionMenuHitTestResult.h in Headers */ = {isa = PBXBuildFile; fileRef = 2D353B1119F8305D000EEACD /* ActionMenuHitTestResult.h */; };
                2D3EF4421917646300034184 /* WebMemoryPressureHandlerIOS.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2D3EF4401917646300034184 /* WebMemoryPressureHandlerIOS.mm */; };
                2D3EF4431917646300034184 /* WebMemoryPressureHandlerIOS.h in Headers */ = {isa = PBXBuildFile; fileRef = 2D3EF4411917646300034184 /* WebMemoryPressureHandlerIOS.h */; };
                2D2ADF0C16363DEC00197E47 /* PDFLayerControllerDetails.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = PDFLayerControllerDetails.h; path = PDF/PDFLayerControllerDetails.h; sourceTree = "<group>"; };
                2D2ADF0D16364D8200197E47 /* PDFPluginChoiceAnnotation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PDFPluginChoiceAnnotation.h; path = PDF/PDFPluginChoiceAnnotation.h; sourceTree = "<group>"; };
                2D2ADF0E16364D8200197E47 /* PDFPluginChoiceAnnotation.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = PDFPluginChoiceAnnotation.mm; path = PDF/PDFPluginChoiceAnnotation.mm; sourceTree = "<group>"; };
-               2D353B1019F8305D000EEACD /* ActionMenuHitTestResult.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ActionMenuHitTestResult.cpp; sourceTree = "<group>"; };
+               2D353B1019F8305D000EEACD /* ActionMenuHitTestResult.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ActionMenuHitTestResult.mm; sourceTree = "<group>"; };
                2D353B1119F8305D000EEACD /* ActionMenuHitTestResult.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ActionMenuHitTestResult.h; sourceTree = "<group>"; };
                2D3EF4401917646300034184 /* WebMemoryPressureHandlerIOS.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = WebMemoryPressureHandlerIOS.mm; path = ios/WebMemoryPressureHandlerIOS.mm; sourceTree = "<group>"; };
                2D3EF4411917646300034184 /* WebMemoryPressureHandlerIOS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WebMemoryPressureHandlerIOS.h; path = ios/WebMemoryPressureHandlerIOS.h; sourceTree = "<group>"; };
                BC111B5A112F628200337BAB /* mac */ = {
                        isa = PBXGroup;
                        children = (
-                               2D353B1019F8305D000EEACD /* ActionMenuHitTestResult.cpp */,
+                               2D353B1019F8305D000EEACD /* ActionMenuHitTestResult.mm */,
                                2D353B1119F8305D000EEACD /* ActionMenuHitTestResult.h */,
                                E179FD9B134D38060015B883 /* ArgumentCodersMac.h */,
                                E179FD9E134D38250015B883 /* ArgumentCodersMac.mm */,
                                1AE00D5C182DADE100087DD7 /* KeyedEncoder.cpp in Sources */,
                                1AC8702E130B49A2002C1257 /* WebPluginSiteDataManager.cpp in Sources */,
                                BC5744EF12638FB3006F0F12 /* WebPopupItem.cpp in Sources */,
-                               2D353B1219F8305D000EEACD /* ActionMenuHitTestResult.cpp in Sources */,
+                               2D353B1219F8305D000EEACD /* ActionMenuHitTestResult.mm in Sources */,
                                0F931C1D18C5711900DBA7C3 /* ScrollingTreeOverflowScrollingNodeIOS.mm in Sources */,
                                D3B9484611FF4B6500032B39 /* WebPopupMenu.cpp in Sources */,
                                1AAF08A1192681D100B6390C /* WebUserContentControllerProxy.cpp in Sources */,
index 156c4a9..21be105 100644 (file)
 #include <WebCore/Icon.h>
 #endif
 
-#if PLATFORM(MAC)
-#include "ActionMenuHitTestResult.h"
-#endif
-
 #ifndef NDEBUG
 #include <wtf/RefCountedLeakCounter.h>
 #endif
@@ -4799,34 +4795,4 @@ void WebPage::willChangeCurrentHistoryItemForMainFrame()
     send(Messages::WebPageProxy::WillChangeCurrentHistoryItemForMainFrame());
 }
 
-#if PLATFORM(MAC)
-void WebPage::performActionMenuHitTestAtLocation(WebCore::FloatPoint locationInViewCooordinates)
-{
-    layoutIfNeeded();
-
-    MainFrame& mainFrame = corePage()->mainFrame();
-    if (!mainFrame.view() || !mainFrame.view()->renderView()) {
-        send(Messages::WebPageProxy::DidPerformActionMenuHitTest(ActionMenuHitTestResult()));
-        return;
-    }
-
-    RenderView& mainRenderView = *mainFrame.view()->renderView();
-
-    HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::AllowChildFrameContent | HitTestRequest::IgnoreClipping | HitTestRequest::DisallowShadowContent);
-
-    HitTestResult hitTestResult(mainFrame.view()->rootViewToContents(roundedIntPoint(locationInViewCooordinates)));
-    mainRenderView.hitTest(request, hitTestResult);
-
-    ActionMenuHitTestResult actionMenuResult;
-
-    if (Image* image = hitTestResult.image()) {
-        actionMenuResult.image = ShareableBitmap::createShareable(IntSize(image->size()), ShareableBitmap::SupportsAlpha);
-        if (actionMenuResult.image)
-            actionMenuResult.image->createGraphicsContext()->drawImage(image, ColorSpaceDeviceRGB, IntPoint());
-    }
-
-    send(Messages::WebPageProxy::DidPerformActionMenuHitTest(actionMenuResult));
-}
-#endif
-
 } // namespace WebKit
index e0b5581..f9e6f75 100644 (file)
@@ -28,6 +28,7 @@
 
 #if PLATFORM(MAC)
 
+#import "ActionMenuHitTestResult.h"
 #import "AttributedString.h"
 #import "DataReference.h"
 #import "DictionaryPopupInfo.h"
 #import <QuartzCore/QuartzCore.h>
 #import <WebCore/AXObjectCache.h>
 #import <WebCore/BackForwardController.h>
+#import <WebCore/DataDetectorsSPI.h>
 #import <WebCore/EventHandler.h>
 #import <WebCore/FocusController.h>
 #import <WebCore/FrameLoader.h>
 #import <WebCore/FrameView.h>
+#import <WebCore/GraphicsContext.h>
 #import <WebCore/HTMLConverter.h>
 #import <WebCore/HitTestResult.h>
 #import <WebCore/KeyboardEvent.h>
 #import <WebCore/RenderElement.h>
 #import <WebCore/RenderObject.h>
 #import <WebCore/RenderStyle.h>
+#import <WebCore/RenderView.h>
 #import <WebCore/ResourceHandle.h>
 #import <WebCore/ScrollView.h>
 #import <WebCore/StyleInheritedData.h>
 #import <WebCore/TextIterator.h>
 #import <WebCore/VisibleUnits.h>
 #import <WebCore/WindowsKeyboardCodes.h>
+#import <WebCore/htmlediting.h>
 #import <WebKitSystemInterface.h>
 
 using namespace WebCore;
@@ -496,6 +501,34 @@ static bool shouldUseSelection(const VisiblePosition& position, const VisibleSel
     return isPositionInRange(position, selectedRange.get());
 }
 
+static PassRefPtr<Range> rangeExpandedAroundPosition(const VisiblePosition& position, int numberOfLinesToExpand)
+{
+    VisiblePosition contextStart = position;
+    VisiblePosition contextEnd = position;
+    for (int i = 0; i < numberOfLinesToExpand; i++) {
+        VisiblePosition n = previousLinePosition(contextStart, contextStart.lineDirectionPointForBlockDirectionNavigation());
+        if (n.isNull() || n == contextStart)
+            break;
+        contextStart = n;
+    }
+    for (int i = 0; i < numberOfLinesToExpand; i++) {
+        VisiblePosition n = nextLinePosition(contextEnd, contextEnd.lineDirectionPointForBlockDirectionNavigation());
+        if (n.isNull() || n == contextEnd)
+            break;
+        contextEnd = n;
+    }
+
+    VisiblePosition lineStart = startOfLine(contextStart);
+    if (!lineStart.isNull())
+        contextStart = lineStart;
+
+    VisiblePosition lineEnd = endOfLine(contextEnd);
+    if (!lineEnd.isNull())
+        contextEnd = lineEnd;
+    
+    return makeRange(contextStart, contextEnd);
+}
+
 void WebPage::performDictionaryLookupAtLocation(const FloatPoint& floatPoint)
 {
     if (PluginView* pluginView = pluginViewForFrame(&m_page->mainFrame())) {
@@ -524,33 +557,9 @@ void WebPage::performDictionaryLookupAtLocation(const FloatPoint& floatPoint)
     NSDictionary *options = nil;
 
     // As context, we are going to use four lines of text before and after the point. (Dictionary can sometimes look up things that are four lines long)
-    const int numberOfLinesOfContext = 4;
-    VisiblePosition contextStart = position;
-    VisiblePosition contextEnd = position;
-    for (int i = 0; i < numberOfLinesOfContext; i++) {
-        VisiblePosition n = previousLinePosition(contextStart, contextStart.lineDirectionPointForBlockDirectionNavigation());
-        if (n.isNull() || n == contextStart)
-            break;
-        contextStart = n;
-    }
-    for (int i = 0; i < numberOfLinesOfContext; i++) {
-        VisiblePosition n = nextLinePosition(contextEnd, contextEnd.lineDirectionPointForBlockDirectionNavigation());
-        if (n.isNull() || n == contextEnd)
-            break;
-        contextEnd = n;
-    }
+    RefPtr<Range> fullCharacterRange = rangeExpandedAroundPosition(position, 4);
+    NSRange rangeToPass = NSMakeRange(TextIterator::rangeLength(makeRange(fullCharacterRange->startPosition(), position).get()), 0);
 
-    VisiblePosition lineStart = startOfLine(contextStart);
-    if (!lineStart.isNull())
-        contextStart = lineStart;
-
-    VisiblePosition lineEnd = endOfLine(contextEnd);
-    if (!lineEnd.isNull())
-        contextEnd = lineEnd;
-
-    NSRange rangeToPass = NSMakeRange(TextIterator::rangeLength(makeRange(contextStart, position).get()), 0);
-
-    RefPtr<Range> fullCharacterRange = makeRange(contextStart, contextEnd);
     String fullPlainTextString = plainText(fullCharacterRange.get());
 
     NSRange extractedRange = WKExtractWordDefinitionTokenRangeFromContextualString(fullPlainTextString, rangeToPass, &options);
@@ -1050,6 +1059,95 @@ String WebPage::platformUserAgent(const URL&) const
     return String();
 }
 
+static RetainPtr<DDActionContext> scanForDataDetectedItems(const HitTestResult& hitTestResult, FloatRect& actionBoundingBox)
+{
+    Node* node = hitTestResult.innerNonSharedNode();
+    if (!node)
+        return nullptr;
+    auto renderer = node->renderer();
+    if (!renderer)
+        return nullptr;
+    VisiblePosition position = renderer->positionForPoint(hitTestResult.localPoint(), nullptr);
+    if (position.isNull())
+        position = firstPositionInOrBeforeNode(node);
+
+    RefPtr<Range> contextRange = rangeExpandedAroundPosition(position, 4);
+    String fullPlainTextString = plainText(contextRange.get());
+    int hitLocation = TextIterator::rangeLength(makeRange(contextRange->startPosition(), position).get());
+
+    RetainPtr<DDScannerRef> scanner = adoptCF(DDScannerCreate(DDScannerTypeStandard, 0, nullptr));
+    RetainPtr<DDScanQueryRef> scanQuery = adoptCF(DDScanQueryCreateFromString(kCFAllocatorDefault, fullPlainTextString.createCFString().get(), CFRangeMake(0, fullPlainTextString.length())));
+
+    if (!DDScannerScanQuery(scanner.get(), scanQuery.get()))
+        return nullptr;
+
+    RetainPtr<CFArrayRef> results = adoptCF(DDScannerCopyResultsWithOptions(scanner.get(), DDScannerCopyResultsOptionsNoOverlap));
+
+    // Find the DDResultRef that intersects the hitTestResult's VisiblePosition.
+    DDResultRef mainResult = nullptr;
+    RefPtr<Range> mainResultRange;
+    CFIndex resultCount = CFArrayGetCount(results.get());
+    for (CFIndex i = 0; i < resultCount; i++) {
+        DDResultRef result = (DDResultRef)CFArrayGetValueAtIndex(results.get(), i);
+        CFRange resultRangeInContext = DDResultGetRange(result);
+        if (hitLocation >= resultRangeInContext.location && (hitLocation - resultRangeInContext.location) < resultRangeInContext.length) {
+            mainResult = result;
+            mainResultRange = TextIterator::subrange(contextRange.get(), resultRangeInContext.location, resultRangeInContext.length);
+            break;
+        }
+    }
+
+    if (!mainResult)
+        return nullptr;
+
+    RetainPtr<DDActionContext> actionContext = adoptNS([[getDDActionContextClass() alloc] init]);
+    [actionContext setAllResults:(NSArray *)results.get()];
+    [actionContext setMainResult:mainResult];
+
+    Vector<FloatQuad> quads;
+    mainResultRange->textQuads(quads);
+    if (!quads.isEmpty())
+        actionBoundingBox = mainResultRange->ownerDocument().view()->contentsToWindow(quads[0].enclosingBoundingBox());
+
+    return actionContext;
+}
+
+void WebPage::performActionMenuHitTestAtLocation(WebCore::FloatPoint locationInViewCooordinates)
+{
+    layoutIfNeeded();
+
+    MainFrame& mainFrame = corePage()->mainFrame();
+    if (!mainFrame.view() || !mainFrame.view()->renderView()) {
+        send(Messages::WebPageProxy::DidPerformActionMenuHitTest(ActionMenuHitTestResult()));
+        return;
+    }
+
+    RenderView& mainRenderView = *mainFrame.view()->renderView();
+
+    HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::AllowChildFrameContent | HitTestRequest::IgnoreClipping | HitTestRequest::DisallowShadowContent);
+
+    IntPoint locationInContentCoordinates = mainFrame.view()->rootViewToContents(roundedIntPoint(locationInViewCooordinates));
+    HitTestResult hitTestResult(locationInContentCoordinates);
+    mainRenderView.hitTest(request, hitTestResult);
+
+    ActionMenuHitTestResult actionMenuResult;
+
+    if (Image* image = hitTestResult.image()) {
+        actionMenuResult.image = ShareableBitmap::createShareable(IntSize(image->size()), ShareableBitmap::SupportsAlpha);
+        if (actionMenuResult.image)
+            actionMenuResult.image->createGraphicsContext()->drawImage(image, ColorSpaceDeviceRGB, IntPoint());
+    }
+
+    // FIXME: Avoid scanning if we will just throw away the result (e.g. we're over a link).
+    if (hitTestResult.innerNode() && hitTestResult.innerNode()->isTextNode()) {
+        FloatRect actionBoundingBox;
+        actionMenuResult.actionContext = scanForDataDetectedItems(hitTestResult, actionBoundingBox);
+        actionMenuResult.actionBoundingBox = actionBoundingBox;
+    }
+    
+    send(Messages::WebPageProxy::DidPerformActionMenuHitTest(actionMenuResult));
+}
+
 } // namespace WebKit
 
 #endif // PLATFORM(MAC)
index 53f54a9..00ada63 100644 (file)
@@ -1,3 +1,17 @@
+2014-10-29  Tim Horton  <timothy_horton@apple.com>
+
+        Implement action menus for data detected items
+        https://bugs.webkit.org/show_bug.cgi?id=138178
+        <rdar://problem/18709436>
+
+        Reviewed by Anders Carlsson.
+
+        * WebKitSystemInterface.h:
+        * libWebKitSystemInterfaceMavericks.a:
+        * libWebKitSystemInterfaceMountainLion.a:
+        * libWebKitSystemInterfaceYosemite.a:
+        Update WebKitSystemInterface.
+
 2014-10-14  Brent Fulgham  <bfulgham@apple.com>
 
         [Win] Enable Encrypted Media Support
index 09fbe35..d6e7b6d 100644 (file)
@@ -22,6 +22,7 @@
 
 @class AVAsset;
 @class AVPlayer;
+@class DDActionContext;
 @class QTMovie;
 @class QTMovieView;
 
@@ -128,8 +129,9 @@ void WKSetDragImage(NSImage *image, NSPoint offset);
 
 void WKDrawBezeledTextArea(NSRect, BOOL enabled);
 
-void WKPopupMenu(NSMenu*, NSPoint location, float width, NSView*, int selectedItem, NSFont*, NSControlSize controlSize, bool hideArrows);
+void WKPopupMenu(NSMenu*, NSPoint location, float width, NSView*, int selectedItem, NSFont*, NSControlSize controlSize, bool usesCustomAppearance);
 void WKPopupContextMenu(NSMenu *menu, NSPoint screenLocation);
+void WKSetDDActionContextIsForActionMenu(DDActionContext *actionContext);
 void WKSendUserChangeNotifications(void);
 #ifndef __LP64__
 BOOL WKConvertNSEventToCarbonEvent(EventRecord *carbonEvent, NSEvent *cocoaEvent);
index b881fc4..2a0ed4d 100644 (file)
Binary files a/WebKitLibraries/libWebKitSystemInterfaceMavericks.a and b/WebKitLibraries/libWebKitSystemInterfaceMavericks.a differ
index ce42769..30ac065 100644 (file)
Binary files a/WebKitLibraries/libWebKitSystemInterfaceMountainLion.a and b/WebKitLibraries/libWebKitSystemInterfaceMountainLion.a differ
index 185764a..6c9ce03 100644 (file)
Binary files a/WebKitLibraries/libWebKitSystemInterfaceYosemite.a and b/WebKitLibraries/libWebKitSystemInterfaceYosemite.a differ