⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 286762 in webkit


Ignore:
Timestamp:
Dec 8, 2021, 9:27:01 PM (5 years ago)
Author:
Megan Gardner
Message:

Show correct content menu for images services chevron.
https://bugs.webkit.org/show_bug.cgi?id=233970

Reviewed by Tim Horton.

Add support for showing the correct context menu for image services.
Since this is internal only and can never be affected by web content, we bypass
the web content round trip and directly message the UIProcess about showing
a context menu for images. And because it would be bizarre if the web content
could prevent a menu from popping up on a button they have no control over.

Source/WebCore:

  • dom/mac/ImageControlsMac.cpp:

(WebCore::ImageControlsMac::isImageControlsButtonElement):
(WebCore::ImageControlsMac::imageFromImageElementNode):
(WebCore::ImageControlsMac::handleEvent):
(WebCore::ImageControlsMac::imageControlHost): Deleted.

  • dom/mac/ImageControlsMac.h:
  • html/HTMLButtonElement.cpp:

(WebCore::HTMLButtonElement::defaultEventHandler):

  • page/ChromeClient.h:

(WebCore::ChromeClient::handleImageServiceClick):

  • page/ContextMenuController.cpp:

(WebCore::ContextMenuController::maybeCreateContextMenu):
(WebCore::imageFromImageElementNode): Deleted.

Source/WebKit:

  • Shared/ContextMenuContextData.cpp:

(WebKit::ContextMenuContextData::ContextMenuContextData):
(WebKit::m_selectionIsEditable):
(WebKit::ContextMenuContextData::setImage):
(WebKit::ContextMenuContextData::controlledDataIsEditable const):

  • Shared/ContextMenuContextData.h:

(WebKit::ContextMenuContextData::webHitTestResultData):
(WebKit::ContextMenuContextData::webHitTestResultData const):

  • UIProcess/WebContextMenuProxy.cpp:

(WebKit::WebContextMenuProxy::show):

  • UIProcess/WebPageProxy.cpp:

(WebKit::WebPageProxy::contextMenuItemSelected):

  • UIProcess/mac/WebContextMenuProxyMac.mm:

(WebKit::WebContextMenuProxyMac::getShareMenuItem):
(WebKit::WebContextMenuProxyMac::getContextMenuFromItems):
(WebKit::WebContextMenuProxyMac::useContextMenuItems):

  • UIProcess/mac/WebPageProxyMac.mm:

(WebKit::WebPageProxy::handleContextMenuQuickLookImage):

  • WebProcess/WebCoreSupport/WebChromeClient.cpp:

(WebKit::WebChromeClient::handleImageServiceClick):

  • WebProcess/WebCoreSupport/WebChromeClient.h:
  • WebProcess/WebPage/WebPage.h:
  • WebProcess/WebPage/mac/WebPageMac.mm:

(WebKit::WebPage::handleImageServiceClick):

Location:
trunk/Source
Files:
17 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r286759 r286762  
     12021-12-08  Megan Gardner  <megan_gardner@apple.com>
     2
     3        Show correct content menu for images services chevron.
     4        https://bugs.webkit.org/show_bug.cgi?id=233970
     5
     6        Reviewed by Tim Horton.
     7
     8        Add support for showing the correct context menu for image services.
     9        Since this is internal only and can never be affected by web content, we bypass
     10        the web content round trip and directly message the UIProcess about showing
     11        a context menu for images. And because it would be bizarre if the web content
     12        could prevent a menu from popping up on a button they have no control over.
     13
     14        * dom/mac/ImageControlsMac.cpp:
     15        (WebCore::ImageControlsMac::isImageControlsButtonElement):
     16        (WebCore::ImageControlsMac::imageFromImageElementNode):
     17        (WebCore::ImageControlsMac::handleEvent):
     18        (WebCore::ImageControlsMac::imageControlHost): Deleted.
     19        * dom/mac/ImageControlsMac.h:
     20        * html/HTMLButtonElement.cpp:
     21        (WebCore::HTMLButtonElement::defaultEventHandler):
     22        * page/ChromeClient.h:
     23        (WebCore::ChromeClient::handleImageServiceClick):
     24        * page/ContextMenuController.cpp:
     25        (WebCore::ContextMenuController::maybeCreateContextMenu):
     26        (WebCore::imageFromImageElementNode): Deleted.
     27
    1282021-12-08  Myles C. Maxfield  <mmaxfield@apple.com>
    229
  • trunk/Source/WebCore/dom/mac/ImageControlsMac.cpp

    r286461 r286762  
    2727#include "ImageControlsMac.h"
    2828
     29#include "Chrome.h"
     30#include "ChromeClient.h"
     31#include "ContextMenuController.h"
    2932#include "ElementInlines.h"
     33#include "EventHandler.h"
    3034#include "HTMLButtonElement.h"
    3135#include "HTMLDivElement.h"
     36#include "HTMLImageElement.h"
    3237#include "HTMLNames.h"
    3338#include "HTMLStyleElement.h"
     
    6368}
    6469
    65 static RefPtr<HTMLElement> imageControlHost(const Node& node)
    66 {
    67     auto host = node.shadowHost();
    68     if (!is<HTMLElement>(host))
    69         return nullptr;
    70 
    71     RefPtr element { &downcast<HTMLElement>(*host) };
    72     return hasControls(*element) ? element : nullptr;
    73 }
    74 
    7570bool isImageControlsButtonElement(const Node& node)
    7671{
    77     auto host = imageControlHost(node);
    78     if (!host)
    79         return false;
    80 
    81     if (RefPtr controlRoot = static_cast<TreeScope&>(*host->userAgentShadowRoot()).getElementById(imageControlsButtonIdentifier()))
    82         return node.isDescendantOf(*controlRoot);
    83 
    84     return false;
     72    return is<Element>(node) && downcast<Element>(node).getIdAttribute() == imageControlsButtonIdentifier();
    8573}
    8674
     
    10694}
    10795
     96static Image* imageFromImageElementNode(Node& node)
     97{
     98    auto* renderer = node.renderer();
     99    if (!is<RenderImage>(renderer))
     100        return nullptr;
     101    auto* image = downcast<RenderImage>(*renderer).cachedImage();
     102    if (!image || image->errorOccurred())
     103        return nullptr;
     104    return image->imageForRenderer(renderer);
     105}
     106
     107bool handleEvent(HTMLElement& element, Event& event)
     108{
     109    if (event.type() != eventNames().clickEvent)
     110        return false;
     111   
     112    RefPtr frame = element.document().frame();
     113    if (!frame)
     114        return false;
     115
     116    Page* page = element.document().page();
     117    if (!page)
     118        return false;
     119   
     120    if (!is<MouseEvent>(event))
     121        return false;
     122   
     123    auto& mouseEvent = downcast<MouseEvent>(event);
     124    if (!is<Node>(mouseEvent.target()))
     125        return false;
     126    auto& node = downcast<Node>(*mouseEvent.target());
     127
     128    if (ImageControlsMac::isImageControlsButtonElement(node)) {
     129        auto imageElement = node.shadowHost();
     130        if (!imageElement)
     131            return false;
     132        if (auto* image = imageFromImageElementNode(*imageElement)) {
     133            page->chrome().client().handleImageServiceClick(roundedIntPoint(mouseEvent.absoluteLocation()), *image, imageElement->isContentEditable());
     134            event.setDefaultHandled();
     135            return true;
     136        }
     137    }
     138    return false;
     139}
     140
    108141#endif // ENABLE(SERVICE_CONTROLS)
    109142
  • trunk/Source/WebCore/dom/mac/ImageControlsMac.h

    r286461 r286762  
    4040bool isImageControlsButtonElement(const Node&);
    4141void createImageControls(HTMLElement&);
     42bool handleEvent(HTMLElement&, Event&);
    4243
    4344#endif // ENABLE(SERVICE_CONTROLS)
  • trunk/Source/WebCore/html/HTMLButtonElement.cpp

    r286447 r286762  
    3737#include <wtf/SetForScope.h>
    3838#include <wtf/StdLibExtras.h>
     39
     40#if ENABLE(SERVICE_CONTROLS)
     41#include "ImageControlsMac.h"
     42#endif
    3943
    4044namespace WebCore {
     
    129133void HTMLButtonElement::defaultEventHandler(Event& event)
    130134{
     135#if ENABLE(SERVICE_CONTROLS)
     136    if (ImageControlsMac::handleEvent(*this, event))
     137        return;
     138#endif
    131139    if (event.type() == eventNames().DOMActivateEvent && !isDisabledFormControl()) {
    132140        RefPtr<HTMLFormElement> protectedForm(form());
  • trunk/Source/WebCore/page/ChromeClient.h

    r286640 r286762  
    533533    virtual void handleSelectionServiceClick(FrameSelection&, const Vector<String>&, const IntPoint&) { }
    534534    virtual bool hasRelevantSelectionServices(bool /*isTextOnly*/) const { return false; }
     535    virtual void handleImageServiceClick(const IntPoint&, Image&, bool /*isEditable*/) { }
    535536#endif
    536537
  • trunk/Source/WebCore/page/ContextMenuController.cpp

    r286461 r286762  
    148148}
    149149
    150 #if ENABLE(SERVICE_CONTROLS)
    151 
    152 static Image* imageFromImageElementNode(Node& node)
    153 {
    154     auto* renderer = node.renderer();
    155     if (!is<RenderImage>(renderer))
    156         return nullptr;
    157     auto* image = downcast<RenderImage>(*renderer).cachedImage();
    158     if (!image || image->errorOccurred())
    159         return nullptr;
    160     return image->imageForRenderer(renderer);
    161 }
    162 
    163 #endif
    164 
    165150std::unique_ptr<ContextMenu> ContextMenuController::maybeCreateContextMenu(Event& event, OptionSet<HitTestRequest::Type> hitType, ContextMenuContext::Type contextType)
    166151{
     
    181166
    182167    m_context = ContextMenuContext(contextType, result);
    183 
    184 #if ENABLE(SERVICE_CONTROLS)
    185     if (ImageControlsMac::isImageControlsButtonElement(node)) {
    186         if (auto* image = imageFromImageElementNode(*result.innerNonSharedNode()))
    187             m_context.setControlledImage(image);
    188 
    189         // FIXME: If we couldn't get the image then we shouldn't try to show the image controls menu for it.
    190         return nullptr;
    191     }
    192 #endif
    193168   
    194169    return makeUnique<ContextMenu>();
  • trunk/Source/WebKit/ChangeLog

    r286757 r286762  
     12021-12-08  Megan Gardner  <megan_gardner@apple.com>
     2
     3        Show correct content menu for images services chevron.
     4        https://bugs.webkit.org/show_bug.cgi?id=233970
     5
     6        Reviewed by Tim Horton.
     7
     8        Add support for showing the correct context menu for image services.
     9        Since this is internal only and can never be affected by web content, we bypass
     10        the web content round trip and directly message the UIProcess about showing
     11        a context menu for images. And because it would be bizarre if the web content
     12        could prevent a menu from popping up on a button they have no control over.
     13
     14        * Shared/ContextMenuContextData.cpp:
     15        (WebKit::ContextMenuContextData::ContextMenuContextData):
     16        (WebKit::m_selectionIsEditable):
     17        (WebKit::ContextMenuContextData::setImage):
     18        (WebKit::ContextMenuContextData::controlledDataIsEditable const):
     19        * Shared/ContextMenuContextData.h:
     20        (WebKit::ContextMenuContextData::webHitTestResultData):
     21        (WebKit::ContextMenuContextData::webHitTestResultData const):
     22        * UIProcess/WebContextMenuProxy.cpp:
     23        (WebKit::WebContextMenuProxy::show):
     24        * UIProcess/WebPageProxy.cpp:
     25        (WebKit::WebPageProxy::contextMenuItemSelected):
     26        * UIProcess/mac/WebContextMenuProxyMac.mm:
     27        (WebKit::WebContextMenuProxyMac::getShareMenuItem):
     28        (WebKit::WebContextMenuProxyMac::getContextMenuFromItems):
     29        (WebKit::WebContextMenuProxyMac::useContextMenuItems):
     30        * UIProcess/mac/WebPageProxyMac.mm:
     31        (WebKit::WebPageProxy::handleContextMenuQuickLookImage):
     32        * WebProcess/WebCoreSupport/WebChromeClient.cpp:
     33        (WebKit::WebChromeClient::handleImageServiceClick):
     34        * WebProcess/WebCoreSupport/WebChromeClient.h:
     35        * WebProcess/WebPage/WebPage.h:
     36        * WebProcess/WebPage/mac/WebPageMac.mm:
     37        (WebKit::WebPage::handleImageServiceClick):
     38
    1392021-12-08  Kyle Piddington  <kpiddington@apple.com>
    240
  • trunk/Source/WebKit/Shared/ContextMenuContextData.cpp

    r276181 r286762  
    5252    , m_menuLocation(menuLocation)
    5353    , m_menuItems(menuItems)
    54     , m_webHitTestResultData(context.hitTestResult(), true)
     54    , m_webHitTestResultData({ context.hitTestResult(), true })
    5555    , m_selectedText(context.selectedText())
    5656#if ENABLE(SERVICE_CONTROLS)
     
    6262    if (!image)
    6363        return;
     64   
     65    setImage(image);
     66#endif
     67}
    6468
     69#if ENABLE(SERVICE_CONTROLS)
     70ContextMenuContextData::ContextMenuContextData(const WebCore::IntPoint& menuLocation, WebCore::Image& image, bool isEditable)
     71    : m_type(Type::ServicesMenu)
     72    , m_menuLocation(menuLocation)
     73    , m_selectionIsEditable(isEditable)
     74{
     75    setImage(&image);
     76}
     77
     78void ContextMenuContextData::setImage(WebCore::Image* image)
     79{
    6580    // FIXME: figure out the rounding strategy for ShareableBitmap.
    6681    m_controlledImage = ShareableBitmap::createShareable(IntSize(image->size()), { });
     
    6984        return;
    7085    graphicsContext->drawImage(*image, IntPoint());
     86}
    7187#endif
    72 }
    7388
    7489void ContextMenuContextData::encode(IPC::Encoder& encoder) const
     
    130145bool ContextMenuContextData::controlledDataIsEditable() const
    131146{
    132     if (!m_controlledSelectionData.isEmpty())
     147    if (!m_controlledSelectionData.isEmpty() || m_controlledImage)
    133148        return m_selectionIsEditable;
    134 
    135     if (m_controlledImage)
    136         return m_webHitTestResultData.isContentEditable;
    137149
    138150    return false;
  • trunk/Source/WebKit/Shared/ContextMenuContextData.h

    r276181 r286762  
    5252    const Vector<WebKit::WebContextMenuItemData>& menuItems() const { return m_menuItems; }
    5353
    54     WebHitTestResultData& webHitTestResultData() { return m_webHitTestResultData; }
    55     const WebHitTestResultData& webHitTestResultData() const { return m_webHitTestResultData; }
     54    const std::optional<WebHitTestResultData>& webHitTestResultData() const { return m_webHitTestResultData; }
    5655    const String& selectedText() const { return m_selectedText; }
    5756
     
    6564    {
    6665    }
     66   
     67    ContextMenuContextData(const WebCore::IntPoint& menuLocation, WebCore::Image&, bool isEditable);
    6768
    6869    ShareableBitmap* controlledImage() const { return m_controlledImage.get(); }
     
    8384    Vector<WebKit::WebContextMenuItemData> m_menuItems;
    8485
    85     WebHitTestResultData m_webHitTestResultData;
     86    std::optional<WebHitTestResultData> m_webHitTestResultData;
    8687    String m_selectedText;
    8788
    8889#if ENABLE(SERVICE_CONTROLS)
     90    void setImage(WebCore::Image*);
     91   
    8992    RefPtr<ShareableBitmap> m_controlledImage;
    9093    Vector<uint8_t> m_controlledSelectionData;
  • trunk/Source/WebKit/UIProcess/WebContextMenuProxy.cpp

    r284142 r286762  
    5454void WebContextMenuProxy::show()
    5555{
     56    ASSERT(m_context.webHitTestResultData());
     57   
    5658    m_contextMenuListener = WebContextMenuListenerProxy::create(*this);
    57     page()->contextMenuClient().getContextMenuFromProposedMenu(*page(), proposedItems(), *m_contextMenuListener, m_context.webHitTestResultData(), page()->process().transformHandlesToObjects(m_userData.object()).get());
     59    page()->contextMenuClient().getContextMenuFromProposedMenu(*page(), proposedItems(), *m_contextMenuListener, m_context.webHitTestResultData().value(), page()->process().transformHandlesToObjects(m_userData.object()).get());
    5860}
    5961
  • trunk/Source/WebKit/UIProcess/WebPageProxy.cpp

    r286751 r286762  
    69316931    };
    69326932    std::optional<DownloadInfo> downloadInfo;
     6933   
     6934    ASSERT(m_activeContextMenuContextData.webHitTestResultData());
     6935   
     6936    auto hitTestData = m_activeContextMenuContextData.webHitTestResultData().value();
    69336937
    69346938    switch (item.action()) {
     
    69696973
    69706974    case ContextMenuItemTagDownloadImageToDisk:
    6971         downloadInfo = {{ m_activeContextMenuContextData.webHitTestResultData().absoluteImageURL, { } }};
     6975        downloadInfo = { { hitTestData.absoluteImageURL, { } } };
    69726976        break;
    69736977
    69746978    case ContextMenuItemTagDownloadLinkToDisk: {
    6975         auto& hitTestResult = m_activeContextMenuContextData.webHitTestResultData();
    6976         downloadInfo = {{ hitTestResult.absoluteLinkURL, hitTestResult.linkSuggestedFilename }};
     6979        downloadInfo = { { hitTestData.absoluteLinkURL, hitTestData.linkSuggestedFilename } };
    69776980        break;
    69786981    }
    69796982
    69806983    case ContextMenuItemTagDownloadMediaToDisk:
    6981         downloadInfo = {{ m_activeContextMenuContextData.webHitTestResultData().absoluteMediaURL, { } }};
     6984        downloadInfo = { { hitTestData.absoluteMediaURL, { } } };
    69826985        break;
    69836986
  • trunk/Source/WebKit/UIProcess/mac/WebContextMenuProxyMac.mm

    r284142 r286762  
    310310void WebContextMenuProxyMac::getShareMenuItem(CompletionHandler<void(NSMenuItem *)>&& completionHandler)
    311311{
    312     const WebHitTestResultData& hitTestData = m_context.webHitTestResultData();
     312    ASSERT(m_context.webHitTestResultData());
     313    auto hitTestData = m_context.webHitTestResultData().value();
    313314
    314315    auto items = adoptNS([[NSMutableArray alloc] init]);
     
    534535#endif
    535536
    536     auto imageURL = URL { URL { }, m_context.webHitTestResultData().absoluteImageURL };
    537     auto imageBitmap = m_context.webHitTestResultData().imageBitmap;
     537    ASSERT(m_context.webHitTestResultData());
     538    auto hitTestData = m_context.webHitTestResultData().value();
     539   
     540    auto imageURL = URL { URL { }, hitTestData.absoluteImageURL };
     541    auto imageBitmap = hitTestData.imageBitmap;
    538542
    539543    auto sparseMenuItems = retainPtr([NSPointerArray strongObjectsPointerArray]);
     
    716720            return;
    717721        }
    718 
    719         page()->contextMenuClient().menuFromProposedMenu(*page(), menu, m_context.webHitTestResultData(), m_userData.object(), WTFMove(menuFromProposedMenu));
     722       
     723        ASSERT(m_context.webHitTestResultData());
     724        page()->contextMenuClient().menuFromProposedMenu(*page(), menu, m_context.webHitTestResultData().value(), m_userData.object(), WTFMove(menuFromProposedMenu));
    720725    });
    721726}
  • trunk/Source/WebKit/UIProcess/mac/WebPageProxyMac.mm

    r286705 r286762  
    752752void WebPageProxy::handleContextMenuQuickLookImage(QuickLookPreviewActivity activity)
    753753{
    754     auto& result = m_activeContextMenuContextData.webHitTestResultData();
     754    ASSERT(m_activeContextMenuContextData.webHitTestResultData());
     755   
     756    auto result = m_activeContextMenuContextData.webHitTestResultData().value();
    755757    if (!result.imageBitmap)
    756758        return;
  • trunk/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.cpp

    r286640 r286762  
    13481348}
    13491349
     1350void WebChromeClient::handleImageServiceClick(const IntPoint& point, Image& image, bool isEditable)
     1351{
     1352    m_page.handleImageServiceClick(point, image, isEditable);
     1353}
     1354
    13501355#endif
    13511356
  • trunk/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.h

    r286640 r286762  
    382382    void handleSelectionServiceClick(WebCore::FrameSelection&, const Vector<String>& telephoneNumbers, const WebCore::IntPoint&) final;
    383383    bool hasRelevantSelectionServices(bool isTextOnly) const final;
     384    void handleImageServiceClick(const WebCore::IntPoint&, WebCore::Image&, bool isEditable) final;
    384385#endif
    385386
  • trunk/Source/WebKit/WebProcess/WebPage/WebPage.h

    r286705 r286762  
    12041204    void handleTelephoneNumberClick(const String& number, const WebCore::IntPoint&);
    12051205    void handleSelectionServiceClick(WebCore::FrameSelection&, const Vector<String>& telephoneNumbers, const WebCore::IntPoint&);
     1206    void handleImageServiceClick(const WebCore::IntPoint&, WebCore::Image&, bool isEditable);
    12061207#endif
    12071208
  • trunk/Source/WebKit/WebProcess/WebPage/mac/WebPageMac.mm

    r286097 r286762  
    829829}
    830830
     831void WebPage::handleImageServiceClick(const IntPoint& point, Image& image, bool isEditable)
     832{
     833    send(Messages::WebPageProxy::ShowContextMenu(ContextMenuContextData(point, image, isEditable), UserData()));
     834}
     835
    831836#endif
    832837
Note: See TracChangeset for help on using the changeset viewer.