<!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>[175182] 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/175182">175182</a></dd>
<dt>Author</dt> <dd>bdakin@apple.com</dd>
<dt>Date</dt> <dd>2014-10-24 14:45:54 -0700 (Fri, 24 Oct 2014)</dd>
</dl>

<h3>Log Message</h3>
<pre>WebKit1 should support action menus
https://bugs.webkit.org/show_bug.cgi?id=138032

Reviewed by Tim Horton.

This patch adds basic support for action menus and adds actions for links.

Helper class takes care of all of the action menu work. WebView will forward the 
prepareForMenu: message, and then the helper class takes it from there.
* WebView/WebActionMenuController.h: Added.
* WebView/WebActionMenuController.mm: Added.
(-[WebActionMenuController webViewClosed]):
(-[WebActionMenuController prepareForMenu:withEvent:]):

Selectors for link actions.
(-[WebActionMenuController _openURLFromActionMenu:]):
(-[WebActionMenuController _addToReadingListFromActionMenu:]):
(-[WebActionMenuController _elementBoundingBoxFromDOMElement:]):
(-[WebActionMenuController _quickLookURLFromActionMenu:]):
(-[WebActionMenuController _createActionMenuItemForTag:withHitTestResult:]):
(webKitBundleImageNamed):
(-[WebActionMenuController _defaultMenuItemsForLink:]):
(-[WebActionMenuController _defaultMenuItemsForHitTestResult:]):

Tags for the action menu items.
* WebView/WebUIDelegatePrivate.h:
* WebView/WebView.mm:

Set the action menu if possible and create the controller.
(-[WebView _initWithFrame:frameName:groupName:]):
(-[WebView _close]):
(-[WebView prepareForMenu:withEvent:]):

WebViewData stores the WebActionMenuHelper
* WebView/WebViewData.h:
* WebView/WebViewData.mm:
(-[WebViewPrivate dealloc]):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebKitWebKitxcodeprojprojectpbxproj">trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj</a></li>
<li><a href="#trunkSourceWebKitmacChangeLog">trunk/Source/WebKit/mac/ChangeLog</a></li>
<li><a href="#trunkSourceWebKitmacWebViewWebUIDelegatePrivateh">trunk/Source/WebKit/mac/WebView/WebUIDelegatePrivate.h</a></li>
<li><a href="#trunkSourceWebKitmacWebViewWebViewmm">trunk/Source/WebKit/mac/WebView/WebView.mm</a></li>
<li><a href="#trunkSourceWebKitmacWebViewWebViewDatah">trunk/Source/WebKit/mac/WebView/WebViewData.h</a></li>
<li><a href="#trunkSourceWebKitmacWebViewWebViewDatamm">trunk/Source/WebKit/mac/WebView/WebViewData.mm</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li>trunk/Source/WebKit/Source/</li>
<li>trunk/Source/WebKit/Source/WebKit/</li>
<li>trunk/Source/WebKit/Source/WebKit/mac/</li>
<li>trunk/Source/WebKit/Source/WebKit/mac/Resources/</li>
<li><a href="#trunkSourceWebKitmacWebViewWebActionMenuControllerh">trunk/Source/WebKit/mac/WebView/WebActionMenuController.h</a></li>
<li><a href="#trunkSourceWebKitmacWebViewWebActionMenuControllermm">trunk/Source/WebKit/mac/WebView/WebActionMenuController.mm</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebKitWebKitxcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj (175181 => 175182)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj        2014-10-24 21:45:01 UTC (rev 175181)
+++ trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj        2014-10-24 21:45:54 UTC (rev 175182)
</span><span class="lines">@@ -159,6 +159,8 @@
</span><span class="cx">                 934C11670D8710BB00C32ABD /* WebDynamicScrollBarsViewInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 934C11660D8710BB00C32ABD /* WebDynamicScrollBarsViewInternal.h */; };
</span><span class="cx">                 934C4A910F01406C009372C0 /* WebNSObjectExtras.mm in Sources */ = {isa = PBXBuildFile; fileRef = 934C4A900F01406C009372C0 /* WebNSObjectExtras.mm */; };
</span><span class="cx">                 934C4AA00F0141F7009372C0 /* WebResourceInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 934C4A9F0F0141F7009372C0 /* WebResourceInternal.h */; };
</span><ins>+                935D44E419F9AFF000FB5306 /* WebActionMenuController.h in Headers */ = {isa = PBXBuildFile; fileRef = 935D44E219F9AFF000FB5306 /* WebActionMenuController.h */; };
+                935D44E519F9AFF000FB5306 /* WebActionMenuController.mm in Sources */ = {isa = PBXBuildFile; fileRef = 935D44E319F9AFF000FB5306 /* WebActionMenuController.mm */; };
</ins><span class="cx">                 936A2DE80FD2D08000D312DB /* WebTextCompletionController.mm in Sources */ = {isa = PBXBuildFile; fileRef = 936A2DE70FD2D08000D312DB /* WebTextCompletionController.mm */; };
</span><span class="cx">                 936A2DEA0FD2D08400D312DB /* WebTextCompletionController.h in Headers */ = {isa = PBXBuildFile; fileRef = 936A2DE90FD2D08400D312DB /* WebTextCompletionController.h */; };
</span><span class="cx">                 9391F275121B38BD00EBF7E8 /* WebFrameNetworkingContext.h in Headers */ = {isa = PBXBuildFile; fileRef = 9391F273121B38BD00EBF7E8 /* WebFrameNetworkingContext.h */; };
</span><span class="lines">@@ -692,6 +694,8 @@
</span><span class="cx">                 934C11660D8710BB00C32ABD /* WebDynamicScrollBarsViewInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebDynamicScrollBarsViewInternal.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 934C4A900F01406C009372C0 /* WebNSObjectExtras.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WebNSObjectExtras.mm; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 934C4A9F0F0141F7009372C0 /* WebResourceInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebResourceInternal.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                935D44E219F9AFF000FB5306 /* WebActionMenuController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebActionMenuController.h; sourceTree = &quot;&lt;group&gt;&quot;; };
+                935D44E319F9AFF000FB5306 /* WebActionMenuController.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WebActionMenuController.mm; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 936A2DE70FD2D08000D312DB /* WebTextCompletionController.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WebTextCompletionController.mm; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 936A2DE90FD2D08400D312DB /* WebTextCompletionController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebTextCompletionController.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 9391F273121B38BD00EBF7E8 /* WebFrameNetworkingContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebFrameNetworkingContext.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -1278,6 +1282,8 @@
</span><span class="cx">                                 F52CA6BD02DF9D0F018635CA /* HTML */,
</span><span class="cx">                                 51E94C0706C02CA300A9B09E /* PDF */,
</span><span class="cx">                                 A10C1D79182030190036883A /* ios */,
</span><ins>+                                935D44E219F9AFF000FB5306 /* WebActionMenuController.h */,
+                                935D44E319F9AFF000FB5306 /* WebActionMenuController.mm */,
</ins><span class="cx">                                 8373435A0624EE0D00F3B289 /* WebArchive.h */,
</span><span class="cx">                                 8373435B0624EE0D00F3B289 /* WebArchive.mm */,
</span><span class="cx">                                 44BB8B131241A022001E3A22 /* WebArchiveInternal.h */,
</span><span class="lines">@@ -1709,6 +1715,7 @@
</span><span class="cx">                                 9398104B0824BF01008DF038 /* WebDataSource.h in Headers */,
</span><span class="cx">                                 658A40960A14853B005E6987 /* WebDataSourceInternal.h in Headers */,
</span><span class="cx">                                 9398104C0824BF01008DF038 /* WebDataSourcePrivate.h in Headers */,
</span><ins>+                                935D44E419F9AFF000FB5306 /* WebActionMenuController.h in Headers */,
</ins><span class="cx">                                 9398104E0824BF01008DF038 /* WebDefaultContextMenuDelegate.h in Headers */,
</span><span class="cx">                                 9398108D0824BF01008DF038 /* WebDefaultEditingDelegate.h in Headers */,
</span><span class="cx">                                 9398104F0824BF01008DF038 /* WebDefaultPolicyDelegate.h in Headers */,
</span><span class="lines">@@ -2223,6 +2230,7 @@
</span><span class="cx">                                 A5687BDB135B791A0074CBCB /* WebNodeHighlighter.mm in Sources */,
</span><span class="cx">                                 1C68F672095B5FC100C2984E /* WebNodeHighlightView.mm in Sources */,
</span><span class="cx">                                 A10C1D611820300E0036883A /* SearchPopupMenuIOS.cpp in Sources */,
</span><ins>+                                935D44E519F9AFF000FB5306 /* WebActionMenuController.mm in Sources */,
</ins><span class="cx">                                 A10C1D6C1820300E0036883A /* WebFrameIOS.mm in Sources */,
</span><span class="cx">                                 312E2FE614E48182007CCA18 /* WebNotification.mm in Sources */,
</span><span class="cx">                                 31C11A6F1476552E0049A4CC /* WebNotificationClient.mm in Sources */,
</span></span></pre></div>
<a id="trunkSourceWebKitmacChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/mac/ChangeLog (175181 => 175182)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/mac/ChangeLog        2014-10-24 21:45:01 UTC (rev 175181)
+++ trunk/Source/WebKit/mac/ChangeLog        2014-10-24 21:45:54 UTC (rev 175182)
</span><span class="lines">@@ -1,3 +1,43 @@
</span><ins>+2014-10-24  Beth Dakin  &lt;bdakin@apple.com&gt;
+
+        WebKit1 should support action menus
+        https://bugs.webkit.org/show_bug.cgi?id=138032
+
+        Reviewed by Tim Horton.
+
+        This patch adds basic support for action menus and adds actions for links.
+
+        Helper class takes care of all of the action menu work. WebView will forward the 
+        prepareForMenu: message, and then the helper class takes it from there.
+        * WebView/WebActionMenuController.h: Added.
+        * WebView/WebActionMenuController.mm: Added.
+        (-[WebActionMenuController webViewClosed]):
+        (-[WebActionMenuController prepareForMenu:withEvent:]):
+
+        Selectors for link actions.
+        (-[WebActionMenuController _openURLFromActionMenu:]):
+        (-[WebActionMenuController _addToReadingListFromActionMenu:]):
+        (-[WebActionMenuController _elementBoundingBoxFromDOMElement:]):
+        (-[WebActionMenuController _quickLookURLFromActionMenu:]):
+        (-[WebActionMenuController _createActionMenuItemForTag:withHitTestResult:]):
+        (webKitBundleImageNamed):
+        (-[WebActionMenuController _defaultMenuItemsForLink:]):
+        (-[WebActionMenuController _defaultMenuItemsForHitTestResult:]):
+
+        Tags for the action menu items.
+        * WebView/WebUIDelegatePrivate.h:
+        * WebView/WebView.mm:
+
+        Set the action menu if possible and create the controller.
+        (-[WebView _initWithFrame:frameName:groupName:]):
+        (-[WebView _close]):
+        (-[WebView prepareForMenu:withEvent:]):
+
+        WebViewData stores the WebActionMenuHelper
+        * WebView/WebViewData.h:
+        * WebView/WebViewData.mm:
+        (-[WebViewPrivate dealloc]):
+
</ins><span class="cx"> 2014-10-23  Joseph Pecoraro  &lt;pecoraro@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Web Inspector: Provide a way to have alternate inspector agents
</span></span></pre></div>
<a id="trunkSourceWebKitmacWebViewWebActionMenuControllerh"></a>
<div class="addfile"><h4>Added: trunk/Source/WebKit/mac/WebView/WebActionMenuController.h (0 => 175182)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/mac/WebView/WebActionMenuController.h                                (rev 0)
+++ trunk/Source/WebKit/mac/WebView/WebActionMenuController.h        2014-10-24 21:45:54 UTC (rev 175182)
</span><span class="lines">@@ -0,0 +1,37 @@
</span><ins>+/*
+ * 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.
+ */
+
+@class WebView;
+
+@interface WebActionMenuController : NSObject {
+@private
+    WebView *_webView;
+}
+
+- (id)initWithWebView:(WebView *)webView;
+- (void)webViewClosed;
+- (void)prepareForMenu:(NSMenu *)menu withEvent:(NSEvent *)event;
+
+@end
</ins></span></pre></div>
<a id="trunkSourceWebKitmacWebViewWebActionMenuControllermm"></a>
<div class="addfile"><h4>Added: trunk/Source/WebKit/mac/WebView/WebActionMenuController.mm (0 => 175182)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/mac/WebView/WebActionMenuController.mm                                (rev 0)
+++ trunk/Source/WebKit/mac/WebView/WebActionMenuController.mm        2014-10-24 21:45:54 UTC (rev 175182)
</span><span class="lines">@@ -0,0 +1,245 @@
</span><ins>+/*
+ * 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 &quot;WebActionMenuController.h&quot;
+
+#import &quot;DOMElementInternal.h&quot;
+#import &quot;DOMNodeInternal.h&quot;
+#import &quot;WebUIDelegatePrivate.h&quot;
+#import &quot;WebViewInternal.h&quot;
+#import &lt;WebCore/Element.h&gt;
+#import &lt;WebCore/Frame.h&gt;
+#import &lt;WebCore/FrameView.h&gt;
+#import &lt;WebCore/NSViewSPI.h&gt;
+#import &lt;WebCore/SoftLinking.h&gt;
+#import &lt;objc/objc-class.h&gt;
+#import &lt;objc/objc.h&gt;
+
+SOFT_LINK_FRAMEWORK_IN_UMBRELLA(Quartz, QuickLookUI)
+SOFT_LINK_CLASS(QuickLookUI, QLPreviewBubble)
+
+@class QLPreviewBubble;
+@interface NSObject (WKQLPreviewBubbleDetails)
+@property (copy) NSArray * controls;
+@property NSSize maximumSize;
+@property NSRectEdge preferredEdge;
+@property (retain) IBOutlet NSWindow* parentWindow;
+- (void)showPreviewItem:(id)previewItem itemFrame:(NSRect)frame;
+- (void)setAutomaticallyCloseWithMask:(NSEventMask)autocloseMask filterMask:(NSEventMask)filterMask block:(void (^)(void))block;
+@end
+
+using namespace WebCore;
+
+@implementation WebActionMenuController
+
+- (id)initWithWebView:(WebView *)webView
+{
+    if (!(self = [super init]))
+        return nil;
+    _webView = webView;
+
+    return self;
+}
+
+- (void)webViewClosed
+{
+    _webView = nil;
+}
+
+- (void)prepareForMenu:(NSMenu *)menu withEvent:(NSEvent *)event
+{
+    if (!_webView)
+        return;
+
+    NSMenu *actionMenu = _webView.actionMenu;
+    if (menu != actionMenu)
+        return;
+
+    [actionMenu removeAllItems];
+
+    NSDictionary *hitTestResult = [_webView elementAtPoint:[_webView convertPoint:event.locationInWindow fromView:nil]];
+
+    // FIXME: We should support API for clients to customize the menu items.
+    NSArray *menuItems = [self _defaultMenuItemsForHitTestResult:hitTestResult];
+
+    for (NSMenuItem *item in menuItems)
+        [actionMenu addItem:item];
+}
+
+- (void)_openURLFromActionMenu:(id)sender
+{
+    if (!_webView)
+        return;
+
+    NSURL *url = sender.representedObject;
+    if (!url)
+        return;
+
+    ASSERT([url isKindOfClass:[NSURL class]]);
+
+    [[NSWorkspace sharedWorkspace] openURL:url];
+}
+
+- (void)_addToReadingListFromActionMenu:(id)sender
+{
+    if (!_webView)
+        return;
+
+    NSURL *url = sender.representedObject;
+    if (!url)
+        return;
+
+    ASSERT([url isKindOfClass:[NSURL class]]);
+
+    NSSharingService *service = [NSSharingService sharingServiceNamed:NSSharingServiceNameAddToSafariReadingList];
+    [service performWithItems:@[ url ]];
+}
+
+- (NSRect)_elementBoundingBoxFromDOMElement:(DOMElement *)domElement
+{
+    if (!domElement)
+        return NSZeroRect;
+
+    Node* node = core(domElement);
+    Frame* frame = node-&gt;document().frame();
+    if (!frame)
+        return NSZeroRect;
+
+    FrameView* view = frame-&gt;view();
+    if (!view)
+        return NSZeroRect;
+
+    return view-&gt;contentsToWindow(node-&gt;pixelSnappedBoundingBox());
+}
+
+- (void)_quickLookURLFromActionMenu:(id)sender
+{
+    if (!_webView)
+        return;
+
+    NSDictionary *hitTestResult = sender.representedObject;
+    if (!hitTestResult)
+        return;
+
+    ASSERT([hitTestResult isKindOfClass:[NSDictionary class]]);
+
+    NSURL *url = [hitTestResult objectForKey:WebElementLinkURLKey];
+    if (!url)
+        return;
+
+    DOMElement *domElement = [hitTestResult objectForKey:WebElementDOMNodeKey];
+    if (!domElement)
+        return;
+
+    NSRect itemFrame = [_webView convertRect:[self _elementBoundingBoxFromDOMElement:domElement] toView:nil];
+    NSSize maximumPreviewSize = NSMakeSize(_webView.bounds.size.width * 0.75, _webView.bounds.size.height * 0.75);
+
+    RetainPtr&lt;QLPreviewBubble&gt; bubble = adoptNS([[getQLPreviewBubbleClass() alloc] init]);
+    [bubble setParentWindow:_webView.window];
+    [bubble setMaximumSize:maximumPreviewSize];
+    [bubble setPreferredEdge:NSMaxYEdge];
+    [bubble setControls:@[ ]];
+    NSEventMask filterMask = NSAnyEventMask &amp; ~(NSAppKitDefinedMask | NSSystemDefinedMask | NSApplicationDefinedMask | NSMouseEnteredMask | NSMouseExitedMask);
+    NSEventMask autocloseMask = NSLeftMouseDownMask | NSRightMouseDownMask | NSKeyDownMask;
+    [bubble setAutomaticallyCloseWithMask:autocloseMask filterMask:filterMask block:[bubble] {
+        [bubble close];
+    }];
+    [bubble showPreviewItem:url itemFrame:itemFrame];
+}
+
+- (RetainPtr&lt;NSMenuItem&gt;)_createActionMenuItemForTag:(uint32_t)tag withHitTestResult:(NSDictionary *)hitTestResult
+{
+    SEL selector = nullptr;
+    NSString *title = nil;
+    NSImage *image = nil;
+    id representedObject = nil;
+
+    // FIXME: We should localize these strings.
+    switch (tag) {
+    case WebActionMenuItemTagOpenLinkInDefaultBrowser:
+        selector = @selector(_openURLFromActionMenu:);
+        title = @&quot;Open&quot;;
+        image = webKitBundleImageNamed(@&quot;OpenInNewWindowTemplate&quot;);
+        representedObject = [hitTestResult objectForKey:WebElementLinkURLKey];
+        break;
+
+    case WebActionMenuItemTagPreviewLink:
+        selector = @selector(_quickLookURLFromActionMenu:);
+        title = @&quot;Preview&quot;;
+        image = [NSImage imageNamed:NSImageNameQuickLookTemplate];
+        representedObject = hitTestResult;
+        break;
+
+    case WebActionMenuItemTagAddLinkToSafariReadingList:
+        selector = @selector(_addToReadingListFromActionMenu:);
+        title = @&quot;Add to Safari Reading List&quot;;
+        image = [NSImage imageNamed:NSImageNameBookmarksTemplate];
+        representedObject = [hitTestResult objectForKey:WebElementLinkURLKey];
+        break;
+
+    default:
+        ASSERT_NOT_REACHED();
+        return nil;
+    }
+
+    RetainPtr&lt;NSMenuItem&gt; item = adoptNS([[NSMenuItem alloc] initWithTitle:title action:selector keyEquivalent:@&quot;&quot;]);
+    [item setImage:image];
+    [item setTarget:self];
+    [item setTag:tag];
+    [item setRepresentedObject:representedObject];
+    return item;
+}
+
+static NSImage *webKitBundleImageNamed(NSString *name)
+{
+    return [[NSBundle bundleForClass:NSClassFromString(@&quot;WKView&quot;)] imageForResource:name];
+}
+
+- (NSArray *)_defaultMenuItemsForLink:(NSDictionary *)hitTestResult
+{
+    NSURL *url = [hitTestResult objectForKey:WebElementLinkURLKey];
+    if (!url)
+        return @[ ];
+
+    if (!WebCore::protocolIsInHTTPFamily([url absoluteString]))
+        return @[ ];
+
+    RetainPtr&lt;NSMenuItem&gt; openLinkItem = [self _createActionMenuItemForTag:WebActionMenuItemTagOpenLinkInDefaultBrowser withHitTestResult:hitTestResult];
+    RetainPtr&lt;NSMenuItem&gt; previewLinkItem = [self _createActionMenuItemForTag:WebActionMenuItemTagPreviewLink withHitTestResult:hitTestResult];
+    RetainPtr&lt;NSMenuItem&gt; readingListItem = [self _createActionMenuItemForTag:WebActionMenuItemTagAddLinkToSafariReadingList withHitTestResult:hitTestResult];
+
+    return @[ openLinkItem.get(), previewLinkItem.get(), [NSMenuItem separatorItem], readingListItem.get() ];
+}
+
+- (NSArray *)_defaultMenuItemsForHitTestResult:(NSDictionary *)hitTestResult
+{
+    NSURL *url = [hitTestResult objectForKey:WebElementLinkURLKey];
+    if (url)
+        return [self _defaultMenuItemsForLink:hitTestResult];
+
+    return @[ ];
+}
+
+@end
</ins></span></pre></div>
<a id="trunkSourceWebKitmacWebViewWebUIDelegatePrivateh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/mac/WebView/WebUIDelegatePrivate.h (175181 => 175182)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/mac/WebView/WebUIDelegatePrivate.h        2014-10-24 21:45:01 UTC (rev 175181)
+++ trunk/Source/WebKit/mac/WebView/WebUIDelegatePrivate.h        2014-10-24 21:45:54 UTC (rev 175182)
</span><span class="lines">@@ -269,4 +269,11 @@
</span><span class="cx"> 
</span><span class="cx"> - (NSData *)webCryptoMasterKeyForWebView:(WebView *)sender;
</span><span class="cx"> 
</span><ins>+enum {
+    WebActionMenuItemTagNoAction = 0,
+    WebActionMenuItemTagOpenLinkInDefaultBrowser,
+    WebActionMenuItemTagPreviewLink,
+    WebActionMenuItemTagAddLinkToSafariReadingList
+};
+
</ins><span class="cx"> @end
</span></span></pre></div>
<a id="trunkSourceWebKitmacWebViewWebViewmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/mac/WebView/WebView.mm (175181 => 175182)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/mac/WebView/WebView.mm        2014-10-24 21:45:01 UTC (rev 175181)
+++ trunk/Source/WebKit/mac/WebView/WebView.mm        2014-10-24 21:45:54 UTC (rev 175182)
</span><span class="lines">@@ -200,6 +200,7 @@
</span><span class="cx"> #import &lt;wtf/StdLibExtras.h&gt;
</span><span class="cx"> 
</span><span class="cx"> #if !PLATFORM(IOS)
</span><ins>+#import &quot;WebActionMenuController.h&quot;
</ins><span class="cx"> #import &quot;WebContextMenuClient.h&quot;
</span><span class="cx"> #import &quot;WebFullScreenController.h&quot;
</span><span class="cx"> #import &quot;WebNSEventExtras.h&quot;
</span><span class="lines">@@ -207,6 +208,7 @@
</span><span class="cx"> #import &quot;WebNSPasteboardExtras.h&quot;
</span><span class="cx"> #import &quot;WebNSPrintOperationExtras.h&quot;
</span><span class="cx"> #import &quot;WebPDFView.h&quot;
</span><ins>+#import &lt;WebCore/NSViewSPI.h&gt;
</ins><span class="cx"> #import &lt;WebCore/WebVideoFullscreenController.h&gt;
</span><span class="cx"> #else
</span><span class="cx"> #import &quot;MemoryMeasure.h&quot;
</span><span class="lines">@@ -1061,6 +1063,12 @@
</span><span class="cx">     [self setMaintainsBackForwardList: YES];
</span><span class="cx"> #if !PLATFORM(IOS)
</span><span class="cx">     _private-&gt;page-&gt;setDeviceScaleFactor([self _deviceScaleFactor]);
</span><ins>+
+    if ([self respondsToSelector:@selector(setActionMenu:)]) {
+        RetainPtr&lt;NSMenu&gt; actionMenu = adoptNS([[NSMenu alloc] init]);
+        self.actionMenu = actionMenu.get();
+        _private-&gt;actionMenuController = [[WebActionMenuController alloc] initWithWebView:self];
+    }
</ins><span class="cx"> #endif
</span><span class="cx">     return self;
</span><span class="cx"> }
</span><span class="lines">@@ -1702,6 +1710,7 @@
</span><span class="cx">     [self setUIDelegate:nil];
</span><span class="cx"> 
</span><span class="cx">     [_private-&gt;inspector webViewClosed];
</span><ins>+    [_private-&gt;actionMenuController webViewClosed];
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx"> #if !PLATFORM(IOS)
</span><span class="lines">@@ -8516,6 +8525,14 @@
</span><span class="cx">     return NSMakeRect(rect.origin.x, [self bounds].size.height - rect.origin.y - rect.size.height, rect.size.width, rect.size.height);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+- (void)prepareForMenu:(NSMenu *)menu withEvent:(NSEvent *)event
+{
+    if (menu != self.actionMenu)
+        return;
+
+    [_private-&gt;actionMenuController prepareForMenu:menu withEvent:event];
+}
+
</ins><span class="cx"> @end
</span><span class="cx"> 
</span><span class="cx"> @implementation WebView (WebViewDeviceOrientation)
</span></span></pre></div>
<a id="trunkSourceWebKitmacWebViewWebViewDatah"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/mac/WebView/WebViewData.h (175181 => 175182)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/mac/WebView/WebViewData.h        2014-10-24 21:45:01 UTC (rev 175181)
+++ trunk/Source/WebKit/mac/WebView/WebViewData.h        2014-10-24 21:45:54 UTC (rev 175182)
</span><span class="lines">@@ -49,6 +49,7 @@
</span><span class="cx"> class Page;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+@class WebActionMenuController;
</ins><span class="cx"> @class WebInspector;
</span><span class="cx"> @class WebNodeHighlight;
</span><span class="cx"> @class WebPluginDatabase;
</span><span class="lines">@@ -145,6 +146,8 @@
</span><span class="cx">     WebInspector *inspector;
</span><span class="cx">     WebNodeHighlight *currentNodeHighlight;
</span><span class="cx"> 
</span><ins>+    WebActionMenuController *actionMenuController;
+
</ins><span class="cx">     BOOL allowsUndo;
</span><span class="cx">         
</span><span class="cx">     float zoomMultiplier;
</span></span></pre></div>
<a id="trunkSourceWebKitmacWebViewWebViewDatamm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/mac/WebView/WebViewData.mm (175181 => 175182)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/mac/WebView/WebViewData.mm        2014-10-24 21:45:01 UTC (rev 175181)
+++ trunk/Source/WebKit/mac/WebView/WebViewData.mm        2014-10-24 21:45:54 UTC (rev 175182)
</span><span class="lines">@@ -144,6 +144,7 @@
</span><span class="cx"> #endif
</span><span class="cx">     [inspector release];
</span><span class="cx">     [currentNodeHighlight release];
</span><ins>+    [actionMenuController release];
</ins><span class="cx">     [hostWindow release];
</span><span class="cx">     [policyDelegateForwarder release];
</span><span class="cx">     [UIDelegateForwarder release];
</span></span></pre>
</div>
</div>

</body>
</html>