1/* 2 * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. 3 * Copyright (C) 2010 Igalia S.L 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY 15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR 18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27#include "config.h" 28#include "core/page/ContextMenuController.h" 29 30#include "core/dom/Document.h" 31#include "core/events/Event.h" 32#include "core/events/MouseEvent.h" 33#include "core/dom/Node.h" 34#include "core/frame/LocalFrame.h" 35#include "core/page/ContextMenuClient.h" 36#include "core/page/ContextMenuProvider.h" 37#include "core/page/EventHandler.h" 38#include "platform/ContextMenu.h" 39#include "platform/ContextMenuItem.h" 40 41namespace WebCore { 42 43ContextMenuController::ContextMenuController(Page*, ContextMenuClient* client) 44 : m_client(client) 45{ 46 ASSERT_ARG(client, client); 47} 48 49ContextMenuController::~ContextMenuController() 50{ 51} 52 53PassOwnPtr<ContextMenuController> ContextMenuController::create(Page* page, ContextMenuClient* client) 54{ 55 return adoptPtr(new ContextMenuController(page, client)); 56} 57 58void ContextMenuController::clearContextMenu() 59{ 60 m_contextMenu.clear(); 61 if (m_menuProvider) 62 m_menuProvider->contextMenuCleared(); 63 m_menuProvider = nullptr; 64 m_client->clearContextMenu(); 65 m_hitTestResult = HitTestResult(); 66} 67 68void ContextMenuController::documentDetached(Document* document) 69{ 70 if (Node* innerNode = m_hitTestResult.innerNode()) { 71 // Invalidate the context menu info if its target document is detached. 72 if (innerNode->document() == document) 73 clearContextMenu(); 74 } 75} 76 77void ContextMenuController::handleContextMenuEvent(Event* event) 78{ 79 m_contextMenu = createContextMenu(event); 80 if (!m_contextMenu) 81 return; 82 83 showContextMenu(event); 84} 85 86void ContextMenuController::showContextMenu(Event* event, PassRefPtr<ContextMenuProvider> menuProvider) 87{ 88 m_menuProvider = menuProvider; 89 90 m_contextMenu = createContextMenu(event); 91 if (!m_contextMenu) { 92 clearContextMenu(); 93 return; 94 } 95 96 m_menuProvider->populateContextMenu(m_contextMenu.get()); 97 showContextMenu(event); 98} 99 100PassOwnPtr<ContextMenu> ContextMenuController::createContextMenu(Event* event) 101{ 102 ASSERT(event); 103 104 if (!event->isMouseEvent()) 105 return nullptr; 106 107 MouseEvent* mouseEvent = toMouseEvent(event); 108 HitTestResult result(mouseEvent->absoluteLocation()); 109 110 if (LocalFrame* frame = event->target()->toNode()->document().frame()) 111 result = frame->eventHandler().hitTestResultAtPoint(mouseEvent->absoluteLocation(), HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::ConfusingAndOftenMisusedDisallowShadowContent); 112 113 if (!result.innerNonSharedNode()) 114 return nullptr; 115 116 m_hitTestResult = result; 117 118 return adoptPtr(new ContextMenu); 119} 120 121void ContextMenuController::showContextMenu(Event* event) 122{ 123 m_client->showContextMenu(m_contextMenu.get()); 124 event->setDefaultHandled(); 125} 126 127void ContextMenuController::contextMenuItemSelected(const ContextMenuItem* item) 128{ 129 ASSERT(item->type() == ActionType || item->type() == CheckableActionType); 130 131 if (item->action() < ContextMenuItemBaseCustomTag || item->action() > ContextMenuItemLastCustomTag) 132 return; 133 134 ASSERT(m_menuProvider); 135 m_menuProvider->contextMenuItemSelected(item); 136} 137 138} // namespace WebCore 139