Expose the "Share" menu for links, images, and media.
authorbeidson@apple.com <beidson@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 8 Apr 2015 23:11:38 +0000 (23:11 +0000)
committerbeidson@apple.com <beidson@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 8 Apr 2015 23:11:38 +0000 (23:11 +0000)
<rdar://problem/20435340> and https://bugs.webkit.org/show_bug.cgi?id=143502

Reviewed by Tim Horton.

Source/WebCore:

* loader/EmptyClients.h:
* page/ContextMenuClient.h:
(WebCore::ContextMenuClient::shareSelectedTextMenuItem): Deleted.

* page/ContextMenuController.cpp:
(WebCore::ContextMenuController::populate):
(WebCore::selectionContainsPossibleWord): Deleted.
* page/ContextMenuController.h:
(WebCore::ContextMenuController::page):

* platform/ContextMenuItem.cpp:
(WebCore::ContextMenuItem::ContextMenuItem):
(WebCore::ContextMenuItem::isNull):
(WebCore::ContextMenuItem::shareMenuItem):
(WebCore::ContextMenuItem::supportsShareMenu): Deleted.
(WebCore::ContextMenuItem::shareSelectedTextMenuItem): Deleted.
* platform/ContextMenuItem.h:

* platform/gtk/ContextMenuItemGtk.cpp:
(WebCore::ContextMenuItem::shareMenuItem): Return a null item.
(WebCore::ContextMenuItem::supportsShareMenu): Deleted.
(WebCore::ContextMenuItem::shareSelectedTextMenuItem): Deleted.

* platform/mac/ContextMenuItemMac.mm:
(WebCore::ContextMenuItem::shareMenuItem): Create a full-featured Share menu item instead of just for selected text.
(WebCore::ContextMenuItem::supportsShareMenu): Deleted.
(WebCore::ContextMenuItem::shareSelectedTextMenuItem): Deleted.

* rendering/HitTestResult.cpp:
(WebCore::HitTestResult::selectedText): Instead of calculating selected text outside the HitTestResult, let the
  HitTestResult do what it does best: Calculate things!
* rendering/HitTestResult.h:

Source/WebKit/mac:

* WebCoreSupport/WebContextMenuClient.h:
* WebCoreSupport/WebContextMenuClient.mm:
(WebContextMenuClient::shareMenuItem):

Source/WebKit/win:

* WebCoreSupport/WebContextMenuClient.cpp:
(WebContextMenuClient::shareMenuItem):
* WebCoreSupport/WebContextMenuClient.h:

Source/WebKit2:

* Shared/ContextMenuContextData.cpp:
(WebKit::ContextMenuContextData::ContextMenuContextData):

* Shared/WebHitTestResult.cpp:
(WebKit::WebHitTestResult::Data::Data):
* Shared/WebHitTestResult.h:

* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::internalShowContextMenu):

* WebProcess/WebCoreSupport/WebContextMenuClient.cpp:
(WebKit::WebContextMenuClient::shareMenuItem):
* WebProcess/WebCoreSupport/WebContextMenuClient.h:

* WebProcess/WebCoreSupport/mac/WebContextMenuClientMac.mm:
(WebKit::WebContextMenuClient::shareSelectedTextMenuItem): Deleted.

* WebProcess/WebPage/mac/WebPageMac.mm:
(WebKit::WebPage::performActionMenuHitTestAtLocation):

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

26 files changed:
Source/WebCore/ChangeLog
Source/WebCore/loader/EmptyClients.h
Source/WebCore/page/ContextMenuClient.h
Source/WebCore/page/ContextMenuController.cpp
Source/WebCore/page/ContextMenuController.h
Source/WebCore/platform/ContextMenuItem.cpp
Source/WebCore/platform/ContextMenuItem.h
Source/WebCore/platform/gtk/ContextMenuItemGtk.cpp
Source/WebCore/platform/mac/ContextMenuItemMac.mm
Source/WebCore/rendering/HitTestResult.cpp
Source/WebCore/rendering/HitTestResult.h
Source/WebKit/mac/ChangeLog
Source/WebKit/mac/WebCoreSupport/WebContextMenuClient.h
Source/WebKit/mac/WebCoreSupport/WebContextMenuClient.mm
Source/WebKit/win/ChangeLog
Source/WebKit/win/WebCoreSupport/WebContextMenuClient.cpp
Source/WebKit/win/WebCoreSupport/WebContextMenuClient.h
Source/WebKit2/ChangeLog
Source/WebKit2/Shared/ContextMenuContextData.cpp
Source/WebKit2/Shared/WebHitTestResult.cpp
Source/WebKit2/Shared/WebHitTestResult.h
Source/WebKit2/UIProcess/WebPageProxy.cpp
Source/WebKit2/WebProcess/WebCoreSupport/WebContextMenuClient.cpp
Source/WebKit2/WebProcess/WebCoreSupport/WebContextMenuClient.h
Source/WebKit2/WebProcess/WebCoreSupport/mac/WebContextMenuClientMac.mm
Source/WebKit2/WebProcess/WebPage/mac/WebPageMac.mm

index 4da32e84969633affe2fe4024fa688b4bb50a32c..b73639df27cd208fc2a51ee64b8c613d4616d130 100644 (file)
@@ -1,3 +1,43 @@
+2015-04-08  Brady Eidson  <beidson@apple.com>
+
+        Expose the "Share" menu for links, images, and media.
+        <rdar://problem/20435340> and https://bugs.webkit.org/show_bug.cgi?id=143502
+
+        Reviewed by Tim Horton.
+
+        * loader/EmptyClients.h:
+        * page/ContextMenuClient.h:
+        (WebCore::ContextMenuClient::shareSelectedTextMenuItem): Deleted.
+
+        * page/ContextMenuController.cpp:
+        (WebCore::ContextMenuController::populate):
+        (WebCore::selectionContainsPossibleWord): Deleted.
+        * page/ContextMenuController.h:
+        (WebCore::ContextMenuController::page):
+
+        * platform/ContextMenuItem.cpp:
+        (WebCore::ContextMenuItem::ContextMenuItem):
+        (WebCore::ContextMenuItem::isNull):
+        (WebCore::ContextMenuItem::shareMenuItem):
+        (WebCore::ContextMenuItem::supportsShareMenu): Deleted.
+        (WebCore::ContextMenuItem::shareSelectedTextMenuItem): Deleted.
+        * platform/ContextMenuItem.h:
+
+        * platform/gtk/ContextMenuItemGtk.cpp:
+        (WebCore::ContextMenuItem::shareMenuItem): Return a null item.
+        (WebCore::ContextMenuItem::supportsShareMenu): Deleted.
+        (WebCore::ContextMenuItem::shareSelectedTextMenuItem): Deleted.
+
+        * platform/mac/ContextMenuItemMac.mm:
+        (WebCore::ContextMenuItem::shareMenuItem): Create a full-featured Share menu item instead of just for selected text.
+        (WebCore::ContextMenuItem::supportsShareMenu): Deleted.
+        (WebCore::ContextMenuItem::shareSelectedTextMenuItem): Deleted.
+
+        * rendering/HitTestResult.cpp:
+        (WebCore::HitTestResult::selectedText): Instead of calculating selected text outside the HitTestResult, let the
+          HitTestResult do what it does best: Calculate things!
+        * rendering/HitTestResult.h:
+
 2015-04-08  Per Arne Vollan  <peavo@outlook.com>
 
         [Curl] Compile error in CurlCacheEntry::parseResponseHeaders method.
index 9ca43d0ab03ae27a1febdc8d2148eb68da18aa1a..ce8c240b73f1b826df715a4de750e78c58092a62 100644 (file)
@@ -557,6 +557,8 @@ public:
     virtual void speak(const String&) override { }
     virtual void stopSpeaking() override { }
 
+    virtual ContextMenuItem shareMenuItem(const HitTestResult&) override { return ContextMenuItem(); }
+
 #if PLATFORM(COCOA)
     virtual void searchWithSpotlight() override { }
 #endif
index 41c9d2804de0238a2f0611f8ca01fa767f9ad324..54a200d76ffefb95642984a9a3e3b60dff646017 100644 (file)
@@ -58,9 +58,10 @@ namespace WebCore {
         virtual void speak(const String&) = 0;
         virtual void stopSpeaking() = 0;
 
+        virtual ContextMenuItem shareMenuItem(const HitTestResult&) = 0;
+
 #if PLATFORM(COCOA)
         virtual void searchWithSpotlight() = 0;
-        virtual ContextMenuItem shareSelectedTextMenuItem(const String& selectedText) { return ContextMenuItem::shareSelectedTextMenuItem(selectedText); }
 #endif
 
 #if USE(ACCESSIBILITY_CONTEXT_MENUS)
index d511beaf0c80fb0fbaa7d486e06bdab07097f517..d441fae40fdb203c6d15e239619c257767aee43d 100644 (file)
@@ -731,19 +731,6 @@ void ContextMenuController::createAndAppendTransformationsSubMenu(ContextMenuIte
 
 #endif
 
-static bool selectionContainsPossibleWord(Frame* frame)
-{
-    // Current algorithm: look for a character that's not just a separator.
-    for (TextIterator it(frame->selection().toNormalizedRange().get()); !it.atEnd(); it.advance()) {
-        int length = it.text().length();
-        for (int i = 0; i < length; ++i) {
-            if (!(U_GET_GC_MASK(it.text()[i]) & U_GC_Z_MASK))
-                return true;
-        }
-    }
-    return false;
-}
-
 #if PLATFORM(COCOA)
 #define SUPPORTS_TOGGLE_VIDEO_FULLSCREEN 1
 #else
@@ -826,6 +813,8 @@ void ContextMenuController::populate()
     ContextMenuItem SelectAllItem(ActionType, ContextMenuItemTagSelectAll, contextMenuItemTagSelectAll());
 #endif
 
+    ContextMenuItem ShareMenuItem = m_client.shareMenuItem(m_context.hitTestResult());
+
     Node* node = m_context.hitTestResult().innerNonSharedNode();
     if (!node)
         return;
@@ -844,6 +833,9 @@ void ContextMenuController::populate()
 #endif
 
     if (!m_context.hitTestResult().isContentEditable()) {
+        String selectedString = m_context.hitTestResult().selectedText();
+        m_context.setSelectedText(selectedString);
+
         FrameLoader& loader = frame->loader();
         URL linkURL = m_context.hitTestResult().absoluteLinkURL();
         if (!linkURL.isEmpty()) {
@@ -892,10 +884,8 @@ void ContextMenuController::populate()
 
         if (imageURL.isEmpty() && linkURL.isEmpty() && mediaURL.isEmpty()) {
             if (m_context.hitTestResult().isSelected()) {
-                String selectedString;
-                if (selectionContainsPossibleWord(frame)) {
+                if (!selectedString.isEmpty()) {
 #if PLATFORM(COCOA)
-                    selectedString = frame->displayStringModifiedByEncoding(frame->editor().selectedText());
                     ContextMenuItem LookUpInDictionaryItem(ActionType, ContextMenuItemTagLookUpInDictionary, contextMenuItemTagLookUpInDictionary(selectedString));
 
                     appendItem(LookUpInDictionaryItem, m_contextMenu.get());
@@ -911,12 +901,9 @@ void ContextMenuController::populate()
 #if PLATFORM(COCOA)
                 appendItem(*separatorItem(), m_contextMenu.get());
 
-                if (!selectedString.isEmpty() && ContextMenuItem::supportsShareMenu()) {
-                    ContextMenuItem ShareItem(m_client.shareSelectedTextMenuItem(selectedString));
-                    appendItem(ShareItem, m_contextMenu.get());
+                if (!ShareMenuItem.isNull()) {
+                    appendItem(ShareMenuItem, m_contextMenu.get());
                     appendItem(*separatorItem(), m_contextMenu.get());
-
-                    m_context.setSelectedText(selectedString);
                 }
 
                 ContextMenuItem SpeechMenuItem(SubmenuType, ContextMenuItemTagSpeechMenu, contextMenuItemTagSpeechMenu());
@@ -950,7 +937,15 @@ void ContextMenuController::populate()
 
                 if (frame->page() && !frame->isMainFrame())
                     appendItem(OpenFrameItem, m_contextMenu.get());
+
+                if (!ShareMenuItem.isNull()) {
+                    appendItem(*separatorItem(), m_contextMenu.get());
+                    appendItem(ShareMenuItem, m_contextMenu.get());
+                }
             }
+        } else if (!ShareMenuItem.isNull()) {
+            appendItem(*separatorItem(), m_contextMenu.get());
+            appendItem(ShareMenuItem, m_contextMenu.get());
         }
     } else { // Make an editing context menu
         bool inPasswordField = frame->selection().selection().isInPasswordField();
@@ -1028,10 +1023,10 @@ void ContextMenuController::populate()
             appendItem(*separatorItem(), m_contextMenu.get());
         }
 
-        if (m_context.hitTestResult().isSelected() && !inPasswordField && selectionContainsPossibleWord(frame)) {
+        String selectedText = m_context.hitTestResult().selectedText();
+        if (m_context.hitTestResult().isSelected() && !inPasswordField && !selectedText.isEmpty()) {
 #if PLATFORM(COCOA)
-            String selectedString = frame->displayStringModifiedByEncoding(frame->editor().selectedText());
-            ContextMenuItem LookUpInDictionaryItem(ActionType, ContextMenuItemTagLookUpInDictionary, contextMenuItemTagLookUpInDictionary(selectedString));
+            ContextMenuItem LookUpInDictionaryItem(ActionType, ContextMenuItemTagLookUpInDictionary, contextMenuItemTagLookUpInDictionary(selectedText));
 
             appendItem(LookUpInDictionaryItem, m_contextMenu.get());
 #endif
@@ -1111,6 +1106,11 @@ void ContextMenuController::populate()
             }
 #endif
         }
+
+        if (!ShareMenuItem.isNull()) {
+            appendItem(*separatorItem(), m_contextMenu.get());
+            appendItem(ShareMenuItem, m_contextMenu.get());
+        }
     }
 }
 
index 817aa0c6f1705b422f63551f17c4b3e9829a112b..35739d8a931ab572310b9cbc8c3c276cab9c9057 100644 (file)
@@ -48,6 +48,8 @@ public:
     ContextMenuController(Page&, ContextMenuClient&);
     ~ContextMenuController();
 
+    Page& page() { return m_page; }
+
     ContextMenu* contextMenu() const { return m_contextMenu.get(); }
     WEBCORE_EXPORT void clearContextMenu();
 
index 21dde0dae7045540c3adf487622abe1d5a0b31e2..c1b9e58337516d05dc04e76b8bd4e9b729a065b1 100644 (file)
@@ -62,10 +62,24 @@ ContextMenuItem::ContextMenuItem(ContextMenuAction action, const String& title,
 {
 }
 
+ContextMenuItem::ContextMenuItem()
+    : m_type(SeparatorType)
+    , m_action(ContextMenuItemTagNoAction)
+    , m_enabled(false)
+    , m_checked(false)
+{
+}
+
 ContextMenuItem::~ContextMenuItem()
 {
 }
 
+bool ContextMenuItem::isNull() const
+{
+    // FIXME: This is a bit of a hack. Cross-platform ContextMenuItem users need a concrete way to track "isNull".
+    return m_action == ContextMenuItemTagNoAction && m_title.isNull() && m_subMenuItems.isEmpty();
+}
+
 void ContextMenuItem::setSubMenu(ContextMenu* subMenu)
 {
     if (subMenu) {
@@ -117,12 +131,7 @@ bool ContextMenuItem::enabled() const
     return m_enabled;
 }
 
-bool ContextMenuItem::supportsShareMenu()
-{
-    return false;
-}
-
-ContextMenuItem ContextMenuItem::shareSelectedTextMenuItem(const String&)
+ContextMenuItem ContextMenuItem::shareMenuItem(const URL&, const URL&, Image*, const String&)
 {
     return ContextMenuItem(SubmenuType, ContextMenuItemTagShareMenu, emptyString());
 }
index 090534c9db50a93f7fc400d9baa2bb4903556a44..d90cbd22e735f1bd8fd2581a61a8af4698aa817b 100644 (file)
@@ -45,6 +45,8 @@ typedef struct _GtkAction GtkAction;
 namespace WebCore {
 
     class ContextMenu;
+    class Image;
+    class URL;
 
     // This enum needs to be in sync with the WebMenuItemTag enum in WebUIDelegate.h and the
     // extra values in WebUIDelegatePrivate.h
@@ -206,8 +208,7 @@ namespace WebCore {
 
         void setSubMenu(ContextMenu*);
 
-        static bool supportsShareMenu();
-        WEBCORE_EXPORT static ContextMenuItem shareSelectedTextMenuItem(const String&);
+        WEBCORE_EXPORT static ContextMenuItem shareMenuItem(const URL& absoluteLinkURL, const URL& downloadableMediaURL, Image*, const String& selectedText);
 
 #if PLATFORM(GTK)
         GtkAction* gtkAction() const;
@@ -216,6 +217,9 @@ namespace WebCore {
 #if USE(CROSS_PLATFORM_CONTEXT_MENUS)
         ContextMenuItem(ContextMenuAction, const String&, bool enabled, bool checked, const Vector<ContextMenuItem>& subMenuItems);
         explicit ContextMenuItem(const PlatformContextMenuItem&);
+        ContextMenuItem();
+
+        bool isNull() const;
 
         // On Windows, the title (dwTypeData of the MENUITEMINFO) is not set in this function. Callers can set the title themselves,
         // and handle the lifetime of the title, if they need it.
@@ -230,7 +234,7 @@ namespace WebCore {
         WEBCORE_EXPORT explicit ContextMenuItem(PlatformMenuItemDescription);
         explicit ContextMenuItem(ContextMenu* subMenu);
         ContextMenuItem(ContextMenuAction, const String&, bool enabled, bool checked, Vector<ContextMenuItem>& submenuItems);
-        ContextMenuItem();
+        WEBCORE_EXPORT ContextMenuItem();
 
         bool isNull() const { return !m_platformDescription; }
 
index 5ab14371885dd61641a2e096d785e726901b3480..f70ff2196d7c80aa1953e081fefa7eff891ac227 100644 (file)
@@ -288,12 +288,7 @@ GtkAction* ContextMenuItem::gtkAction() const
     return gtk_activatable_get_related_action(GTK_ACTIVATABLE(m_platformDescription));
 }
 
-bool ContextMenuItem::supportsShareMenu()
-{
-    return false;
-}
-
-ContextMenuItem ContextMenuItem::shareSelectedTextMenuItem(const String&)
+ContextMenuItem ContextMenuItem::shareMenuItem(const URL&, const URL&, Image*, const String&)
 {
     return ContextMenuItem(SubmenuType, ContextMenuItemTagShareMenu, emptyString());
 }
index 1fde8796ce10b783efdd1284223b44a5b44808b3..a2b8da66754c6418ef19ee911fd76c554cc84a92 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006 Apple Inc.  All rights reserved.
+ * Copyright (C) 2006, 2015 Apple Inc.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
 #if ENABLE(CONTEXT_MENUS)
 
 #include "ContextMenu.h"
+#include "Document.h"
+#include "Frame.h"
+#include "HitTestResult.h"
+#include "Image.h"
 #include "NSMenuSPI.h"
+#include "Node.h"
+#include "URL.h"
 
 namespace WebCore {
 
@@ -190,15 +196,32 @@ bool ContextMenuItem::checked() const
     return [m_platformDescription.get() state] == NSOnState;
 }
 
-bool ContextMenuItem::supportsShareMenu()
+ContextMenuItem ContextMenuItem::shareMenuItem(const URL& absoluteLinkURL, const URL& downloadableMediaURL, Image* image, const String& selectedText)
 {
-    static bool supportsShareMenu = [[NSMenuItem class] respondsToSelector:@selector(standardShareMenuItemWithItems:)];
-    return supportsShareMenu;
-}
+    if (![[NSMenuItem class] respondsToSelector:@selector(standardShareMenuItemWithItems:)])
+        return ContextMenuItem();
 
-ContextMenuItem ContextMenuItem::shareSelectedTextMenuItem(const String& selectedText)
-{
-    ContextMenuItem item([NSMenuItem standardShareMenuItemWithItems:@[ (NSString *)selectedText ]]);
+    RetainPtr<NSMutableArray> items = adoptNS([[NSMutableArray alloc] init]);
+
+    if (!absoluteLinkURL.isEmpty())
+        [items addObject:(NSURL *)absoluteLinkURL];
+
+    if (!downloadableMediaURL.isEmpty())
+        [items addObject:(NSURL *)downloadableMediaURL];
+
+    if (image) {
+        NSImage *nsImage = image->getNSImage();
+        if (nsImage)
+            [items addObject:nsImage];
+    }
+
+    if (!selectedText.isEmpty())
+        [items addObject:(NSString *)selectedText];
+
+    if (![items count])
+        return ContextMenuItem();
+
+    ContextMenuItem item([NSMenuItem standardShareMenuItemWithItems:items.get()]);
     item.setAction(ContextMenuItemTagShareMenu);
     return item;
 }
index a480effa0dce035ecd4468a049104a9f9fb10a1b..a8da1802c03d269c7649cc146e27331221dd61aa 100644 (file)
@@ -51,6 +51,7 @@
 #include "SVGNames.h"
 #include "Scrollbar.h"
 #include "ShadowRoot.h"
+#include "TextIterator.h"
 #include "UserGestureIndicator.h"
 #include "VisibleUnits.h"
 #include "XLinkNames.h"
@@ -189,6 +190,26 @@ bool HitTestResult::isSelected() const
     return frame->selection().contains(m_hitTestLocation.point());
 }
 
+String HitTestResult::selectedText() const
+{
+    if (!m_innerNonSharedNode)
+        return emptyString();
+
+    Frame* frame = m_innerNonSharedNode->document().frame();
+    if (!frame)
+        return emptyString();
+
+    // Look for a character that's not just a separator.
+    for (TextIterator it(frame->selection().toNormalizedRange().get()); !it.atEnd(); it.advance()) {
+        int length = it.text().length();
+        for (int i = 0; i < length; ++i) {
+            if (!(U_GET_GC_MASK(it.text()[i]) & U_GC_Z_MASK))
+                return frame->displayStringModifiedByEncoding(frame->editor().selectedText());
+        }
+    }
+    return emptyString();
+}
+
 String HitTestResult::spellingToolTip(TextDirection& dir) const
 {
     dir = LTR;
index 1494c1168178c48fe4e31c8a3a8c6d2ae11c3c9d..ab1aec7ef7fd41a3a7862905f7b254bce9d894e6 100644 (file)
@@ -94,6 +94,7 @@ public:
 
     WEBCORE_EXPORT Frame* targetFrame() const;
     WEBCORE_EXPORT bool isSelected() const;
+    WEBCORE_EXPORT String selectedText() const;
     WEBCORE_EXPORT String spellingToolTip(TextDirection&) const;
     String replacedString() const;
     WEBCORE_EXPORT String title(TextDirection&) const;
index 0052c2344c2e01cb2e6831eb7a43f1a5f6439392..9a219f2739ed9701eaeccc168b667cb5a1f85587 100644 (file)
@@ -1,3 +1,14 @@
+2015-04-08  Brady Eidson  <beidson@apple.com>
+
+        Expose the "Share" menu for links, images, and media.
+        <rdar://problem/20435340> and https://bugs.webkit.org/show_bug.cgi?id=143502
+
+        Reviewed by Tim Horton.
+
+        * WebCoreSupport/WebContextMenuClient.h:
+        * WebCoreSupport/WebContextMenuClient.mm:
+        (WebContextMenuClient::shareMenuItem): 
+
 2015-04-08  Anders Carlsson  <andersca@apple.com>
 
         Move some ApplicationCache static member functions to ApplicationCacheStorage
index 265a83af77e9b74b5e35271bbfaf79c46b1d3f6a..194e2068d7a037274d9eb7b8d03461b008a2617f 100644 (file)
@@ -57,6 +57,7 @@ public:
     virtual bool isSpeaking() override;
     virtual void speak(const WTF::String&) override;
     virtual void stopSpeaking() override;
+    virtual WebCore::ContextMenuItem shareMenuItem(const WebCore::HitTestResult&) override;
     virtual void searchWithSpotlight() override;
     virtual void showContextMenu() override;
 
index 6d860615cb5eaf7c3ebcf4640572d88c16215174..70e2944710d6597c6c7c8fba7e00564e2f71bc15 100644 (file)
@@ -366,6 +366,26 @@ void WebContextMenuClient::stopSpeaking()
     [NSApp stopSpeaking:nil];
 }
 
+ContextMenuItem WebContextMenuClient::shareMenuItem(const HitTestResult& hitTestResult)
+{
+    if (![[NSMenuItem class] respondsToSelector:@selector(standardShareMenuItemWithItems:)])
+        return ContextMenuItem();
+
+    Node* node = hitTestResult.innerNonSharedNode();
+    if (!node)
+        return ContextMenuItem();
+
+    Frame* frame = node->document().frame();
+    if (!frame)
+        return ContextMenuItem();
+
+    URL downloadableMediaURL;
+    if (!hitTestResult.absoluteMediaURL().isEmpty() && hitTestResult.isDownloadableMedia())
+        downloadableMediaURL = hitTestResult.absoluteMediaURL();
+
+    return ContextMenuItem::shareMenuItem(hitTestResult.absoluteLinkURL(), downloadableMediaURL, hitTestResult.image(), hitTestResult.selectedText());
+}
+
 bool WebContextMenuClient::clientFloatRectForNode(Node& node, FloatRect& rect) const
 {
     RenderObject* renderer = node.renderer();
index 755ba48ea694548f608a53f9f43804213427d77c..2b118491e9c43ff7b6e6ac49b2209ed2f89811cd 100644 (file)
@@ -1,3 +1,14 @@
+2015-04-08  Brady Eidson  <beidson@apple.com>
+
+        Expose the "Share" menu for links, images, and media.
+        <rdar://problem/20435340> and https://bugs.webkit.org/show_bug.cgi?id=143502
+
+        Reviewed by Tim Horton.
+
+        * WebCoreSupport/WebContextMenuClient.cpp:
+        (WebContextMenuClient::shareMenuItem):
+        * WebCoreSupport/WebContextMenuClient.h:
+
 2015-04-08  Anders Carlsson  <andersca@apple.com>
 
         Add a WebApplicationCache::storage() and use it instead of the WebCore singleton
index 794436604ecf0901a399c313809925841b04a291..b261b97d0e0f0ac681c660ffa8233cfc9a03d103 100644 (file)
@@ -144,3 +144,9 @@ bool WebContextMenuClient::isSpeaking()
     notImplemented();
     return false;
 }
+
+ContextMenuItem WebContextMenuClient::shareMenuItem(const HitTestResult&)
+{
+    notImplemented();
+    return ContextMenuItem();
+}
index 251736ac18cc785c56c06631900b1aa882c9444d..59a88dce1ef3fe720fd2e0c56e84931523e03b78 100644 (file)
@@ -45,6 +45,8 @@ public:
     virtual void stopSpeaking();
     virtual bool isSpeaking();
 
+    virtual WebCore::ContextMenuItem shareMenuItem(const WebCore::HitTestResult&);
+
 private:
     WebView* m_webView;
 };
index e09dd1abdc601d07f38a8f022678211c81c1baef..097140c71f41c7c12eedf078f01897eb40363cef 100644 (file)
@@ -1,3 +1,30 @@
+2015-04-08  Brady Eidson  <beidson@apple.com>
+
+        Expose the "Share" menu for links, images, and media.
+        <rdar://problem/20435340> and https://bugs.webkit.org/show_bug.cgi?id=143502
+
+        Reviewed by Tim Horton.
+
+        * Shared/ContextMenuContextData.cpp:
+        (WebKit::ContextMenuContextData::ContextMenuContextData):
+
+        * Shared/WebHitTestResult.cpp:
+        (WebKit::WebHitTestResult::Data::Data):
+        * Shared/WebHitTestResult.h:
+
+        * UIProcess/WebPageProxy.cpp:
+        (WebKit::WebPageProxy::internalShowContextMenu):
+
+        * WebProcess/WebCoreSupport/WebContextMenuClient.cpp:
+        (WebKit::WebContextMenuClient::shareMenuItem):
+        * WebProcess/WebCoreSupport/WebContextMenuClient.h:
+
+        * WebProcess/WebCoreSupport/mac/WebContextMenuClientMac.mm:
+        (WebKit::WebContextMenuClient::shareSelectedTextMenuItem): Deleted.
+
+        * WebProcess/WebPage/mac/WebPageMac.mm:
+        (WebKit::WebPage::performActionMenuHitTestAtLocation):
+
 2015-04-08  Anders Carlsson  <andersca@apple.com>
 
         Add encoding and decoding of ints to WKRemoteObjectCoder
index a889ab0f64a951f530099a5c8b65898c8a7f2569..22f869b974b28625226cd775490c02f13bacbd0a 100644 (file)
@@ -45,7 +45,7 @@ ContextMenuContextData::ContextMenuContextData()
 }
 
 ContextMenuContextData::ContextMenuContextData(const ContextMenuContext& context)
-    : m_webHitTestResultData(WebHitTestResult::Data(context.hitTestResult()))
+    : m_webHitTestResultData(context.hitTestResult(), true)
     , m_selectedText(context.selectedText())
 #if ENABLE(SERVICE_CONTROLS)
     , m_selectionIsEditable(false)
index 5fa4f6eb8abdf010086d924a434c67e78c382070..91e0f7932d11a5343ac09929b11d16190569403c 100644 (file)
@@ -62,6 +62,38 @@ WebHitTestResult::Data::Data(const HitTestResult& hitTestResult)
 {
 }
 
+WebHitTestResult::Data::Data(const WebCore::HitTestResult& hitTestResult, bool includeImage)
+    : absoluteImageURL(hitTestResult.absoluteImageURL().string())
+    , absolutePDFURL(hitTestResult.absolutePDFURL().string())
+    , absoluteLinkURL(hitTestResult.absoluteLinkURL().string())
+    , absoluteMediaURL(hitTestResult.absoluteMediaURL().string())
+    , linkLabel(hitTestResult.textContent())
+    , linkTitle(hitTestResult.titleDisplayString())
+    , isContentEditable(hitTestResult.isContentEditable())
+    , elementBoundingBox(elementBoundingBoxInWindowCoordinates(hitTestResult))
+    , isScrollbar(hitTestResult.scrollbar())
+    , isSelected(hitTestResult.isSelected())
+    , isTextNode(hitTestResult.innerNode() && hitTestResult.innerNode()->isTextNode())
+    , isOverTextInsideFormControlElement(hitTestResult.isOverTextInsideFormControlElement())
+    , allowsCopy(hitTestResult.allowsCopy())
+    , isDownloadableMedia(hitTestResult.isDownloadableMedia())
+    , imageSize(0)
+{
+    if (!includeImage)
+        return;
+
+    if (Image* image = hitTestResult.image()) {
+        RefPtr<SharedBuffer> buffer = image->data();
+        String imageExtension = image->filenameExtension();
+        if (!imageExtension.isEmpty() && buffer) {
+            imageSharedMemory = SharedMemory::create(buffer->size());
+            memcpy(imageSharedMemory->data(), buffer->data(), buffer->size());
+            imageExtension = imageExtension;
+            imageSize = buffer->size();
+        }
+    }
+}
+
 WebHitTestResult::Data::~Data()
 {
 }
index d857e3cef08068dd573e3c99f44bbd3dccaf7aa0..044559e504425f0e581fc821ecfa84bc307a1288 100644 (file)
@@ -84,6 +84,7 @@ public:
 
         Data();
         explicit Data(const WebCore::HitTestResult&);
+        Data(const WebCore::HitTestResult&, bool includeImage);
         ~Data();
 
         void encode(IPC::ArgumentEncoder&) const;
index 27551aa895b578f39ae5c2b7192f74101b848a23..06f0e92c82d9480e956d92e79115fd855f7f5f5d 100644 (file)
 #include "WebProtectionSpace.h"
 #include "WebUserContentControllerProxy.h"
 #include "WebsiteDataStore.h"
+#include <WebCore/BitmapImage.h>
 #include <WebCore/DragController.h>
 #include <WebCore/DragData.h>
 #include <WebCore/FloatRect.h>
@@ -4042,8 +4043,23 @@ void WebPageProxy::internalShowContextMenu(const IntPoint& menuLocation, const C
             continue;
         }
 
-        // Currently we only support the share menu for text selection, so create the appropriate menu item for that text selection now.
-        ContextMenuItem coreItem = ContextMenuItem::shareSelectedTextMenuItem(contextMenuContextData.selectedText());
+        // Create the real Share menu item
+        URL absoluteLinkURL;
+        if (!contextMenuContextData.webHitTestResultData().absoluteLinkURL.isEmpty())
+            absoluteLinkURL = URL(ParsedURLString, contextMenuContextData.webHitTestResultData().absoluteLinkURL);
+
+        URL downloadableMediaURL;
+        if (!contextMenuContextData.webHitTestResultData().absoluteMediaURL.isEmpty() && contextMenuContextData.webHitTestResultData().isDownloadableMedia)
+            downloadableMediaURL = URL(ParsedURLString, contextMenuContextData.webHitTestResultData().absoluteMediaURL);
+
+        RefPtr<Image> image;
+        if (contextMenuContextData.webHitTestResultData().imageSharedMemory && contextMenuContextData.webHitTestResultData().imageSize) {
+            image = BitmapImage::create();
+            RefPtr<SharedBuffer> imageData = SharedBuffer::create((unsigned char*)contextMenuContextData.webHitTestResultData().imageSharedMemory->data(), contextMenuContextData.webHitTestResultData().imageSize);
+            image->setData(imageData.release(), true);
+        }
+
+        ContextMenuItem coreItem = ContextMenuItem::shareMenuItem(absoluteLinkURL, downloadableMediaURL, image.get(), contextMenuContextData.selectedText());
         proposedAPIItems.append(WebContextMenuItem::create(coreItem));
     }
 
index 40a60d86b679dcbffe8f0e54ef69ff6567f2f1e9..b0a5dbce0c680de9da0e40c775419491c7b32708 100644 (file)
@@ -74,6 +74,11 @@ void WebContextMenuClient::downloadURL(const URL&)
     ASSERT_NOT_REACHED();
 }
 
+ContextMenuItem WebContextMenuClient::shareMenuItem(const HitTestResult&)
+{
+    return ContextMenuItem(SubmenuType, ContextMenuItemTagShareMenu, emptyString());
+}
+
 #if !PLATFORM(COCOA)
 void WebContextMenuClient::searchWithGoogle(const Frame* frame)
 {
index cebcd11eabf732ad94c98b18a00acf7adfd2e61e..5cf98137be9f6043a3a93917af4d424f719e2ace 100644 (file)
@@ -57,10 +57,10 @@ private:
     virtual bool isSpeaking() override;
     virtual void speak(const String&) override;
     virtual void stopSpeaking() override;
-    
+    virtual WebCore::ContextMenuItem shareMenuItem(const WebCore::HitTestResult&) override;
+
 #if PLATFORM(COCOA)
     virtual void searchWithSpotlight() override;
-    virtual WebCore::ContextMenuItem shareSelectedTextMenuItem(const String&) override;
 #endif
 
 #if USE(ACCESSIBILITY_CONTEXT_MENUS)
index 10c4400341bc61ed940de6e2cc1b38fe9b4987a0..8c52f44b41980860918fc8528a1305f17f785047 100644 (file)
@@ -94,11 +94,6 @@ void WebContextMenuClient::searchWithSpotlight()
     m_page->send(Messages::WebPageProxy::SearchWithSpotlight(selectedString));
 }
 
-ContextMenuItem WebContextMenuClient::shareSelectedTextMenuItem(const String& selectedText)
-{
-    return ContextMenuItem(SubmenuType, ContextMenuItemTagShareMenu, emptyString());
-}
-
 } // namespace WebKit
 
 #endif // ENABLE(CONTEXT_MENUS)
index fe121342448db5725c124031fdc313041f9d7986..302ac7b800cfb572b254abd6b611f90fec480a08 100644 (file)
@@ -1033,7 +1033,7 @@ void WebPage::performActionMenuHitTestAtLocation(WebCore::FloatPoint locationInV
             actionMenuHitTestPreventsDefault = element->dispatchMouseForceWillBegin();
     }
 
-    WebHitTestResult::Data actionMenuResult(hitTestResult);
+    WebHitTestResult::Data actionMenuResult(hitTestResult, !forImmediateAction);
     actionMenuResult.hitTestLocationInViewCooordinates = locationInViewCooordinates;
 
     RefPtr<Range> selectionRange = corePage()->focusController().focusedOrMainFrame().selection().selection().firstRange();
@@ -1059,19 +1059,6 @@ void WebPage::performActionMenuHitTestAtLocation(WebCore::FloatPoint locationInV
     m_lastActionMenuRangeForSelection = lookupRange;
     m_lastActionMenuHitTestResult = hitTestResult;
 
-    if (!forImmediateAction) {
-        if (Image* image = hitTestResult.image()) {
-            RefPtr<SharedBuffer> buffer = image->data();
-            String imageExtension = image->filenameExtension();
-            if (!imageExtension.isEmpty() && buffer) {
-                actionMenuResult.imageSharedMemory = SharedMemory::create(buffer->size());
-                memcpy(actionMenuResult.imageSharedMemory->data(), buffer->data(), buffer->size());
-                actionMenuResult.imageExtension = imageExtension;
-                actionMenuResult.imageSize = buffer->size();
-            }
-        }
-    }
-
     bool pageOverlayDidOverrideDataDetectors = false;
     for (const auto& overlay : mainFrame.pageOverlayController().pageOverlays()) {
         WebPageOverlay* webOverlay = WebPageOverlay::fromCoreOverlay(*overlay);