1/* 2 * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. 3 * Copyright (C) 2008 Matt Lilek <webkit@mattlilek.com> 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 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. Neither the name of Apple Inc. ("Apple") nor the names of 15 * its contributors may be used to endorse or promote products derived 16 * from this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 19 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 22 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30#include "config.h" 31 32#if ENABLE(INSPECTOR) 33 34#include "InspectorFrontendHost.h" 35 36#include "ContextMenu.h" 37#include "ContextMenuController.h" 38#include "ContextMenuItem.h" 39#include "ContextMenuProvider.h" 40#include "DOMWrapperWorld.h" 41#include "Document.h" 42#include "Event.h" 43#include "HitTestResult.h" 44#include "InspectorFrontendClient.h" 45#include "JSMainThreadExecState.h" 46#include "MainFrame.h" 47#include "MouseEvent.h" 48#include "Node.h" 49#include "Page.h" 50#include "Pasteboard.h" 51#include "ScriptGlobalObject.h" 52#include "ScriptState.h" 53#include "Sound.h" 54#include "UserGestureIndicator.h" 55#include <bindings/ScriptFunctionCall.h> 56#include <wtf/StdLibExtras.h> 57 58using namespace Inspector; 59 60namespace WebCore { 61 62#if ENABLE(CONTEXT_MENUS) 63class FrontendMenuProvider : public ContextMenuProvider { 64public: 65 static PassRefPtr<FrontendMenuProvider> create(InspectorFrontendHost* frontendHost, Deprecated::ScriptObject frontendApiObject, const Vector<ContextMenuItem>& items) 66 { 67 return adoptRef(new FrontendMenuProvider(frontendHost, frontendApiObject, items)); 68 } 69 70 void disconnect() 71 { 72 m_frontendApiObject = Deprecated::ScriptObject(); 73 m_frontendHost = nullptr; 74 } 75 76private: 77 FrontendMenuProvider(InspectorFrontendHost* frontendHost, Deprecated::ScriptObject frontendApiObject, const Vector<ContextMenuItem>& items) 78 : m_frontendHost(frontendHost) 79 , m_frontendApiObject(frontendApiObject) 80 , m_items(items) 81 { 82 } 83 84 virtual ~FrontendMenuProvider() 85 { 86 contextMenuCleared(); 87 } 88 89 virtual void populateContextMenu(ContextMenu* menu) override 90 { 91 for (size_t i = 0; i < m_items.size(); ++i) 92 menu->appendItem(m_items[i]); 93 } 94 95 virtual void contextMenuItemSelected(ContextMenuItem* item) override 96 { 97 if (m_frontendHost) { 98 UserGestureIndicator gestureIndicator(DefinitelyProcessingUserGesture); 99 int itemNumber = item->action() - ContextMenuItemBaseCustomTag; 100 101 Deprecated::ScriptFunctionCall function(m_frontendApiObject, "contextMenuItemSelected", WebCore::functionCallHandlerFromAnyThread); 102 function.appendArgument(itemNumber); 103 function.call(); 104 } 105 } 106 107 virtual void contextMenuCleared() override 108 { 109 if (m_frontendHost) { 110 Deprecated::ScriptFunctionCall function(m_frontendApiObject, "contextMenuCleared", WebCore::functionCallHandlerFromAnyThread); 111 function.call(); 112 113 m_frontendHost->m_menuProvider = nullptr; 114 } 115 m_items.clear(); 116 } 117 118 InspectorFrontendHost* m_frontendHost; 119 Deprecated::ScriptObject m_frontendApiObject; 120 Vector<ContextMenuItem> m_items; 121}; 122#endif 123 124InspectorFrontendHost::InspectorFrontendHost(InspectorFrontendClient* client, Page* frontendPage) 125 : m_client(client) 126 , m_frontendPage(frontendPage) 127#if ENABLE(CONTEXT_MENUS) 128 , m_menuProvider(nullptr) 129#endif 130{ 131} 132 133InspectorFrontendHost::~InspectorFrontendHost() 134{ 135 ASSERT(!m_client); 136} 137 138void InspectorFrontendHost::disconnectClient() 139{ 140 m_client = nullptr; 141#if ENABLE(CONTEXT_MENUS) 142 if (m_menuProvider) 143 m_menuProvider->disconnect(); 144#endif 145 m_frontendPage = nullptr; 146} 147 148void InspectorFrontendHost::loaded() 149{ 150 if (m_client) 151 m_client->frontendLoaded(); 152} 153 154void InspectorFrontendHost::requestSetDockSide(const String& side) 155{ 156 if (!m_client) 157 return; 158 if (side == "undocked") 159 m_client->requestSetDockSide(InspectorFrontendClient::UNDOCKED); 160 else if (side == "right") 161 m_client->requestSetDockSide(InspectorFrontendClient::DOCKED_TO_RIGHT); 162 else if (side == "bottom") 163 m_client->requestSetDockSide(InspectorFrontendClient::DOCKED_TO_BOTTOM); 164} 165 166void InspectorFrontendHost::closeWindow() 167{ 168 if (m_client) { 169 m_client->closeWindow(); 170 disconnectClient(); // Disconnect from client. 171 } 172} 173 174void InspectorFrontendHost::bringToFront() 175{ 176 if (m_client) 177 m_client->bringToFront(); 178} 179 180void InspectorFrontendHost::setZoomFactor(float zoom) 181{ 182 m_frontendPage->mainFrame().setPageAndTextZoomFactors(zoom, 1); 183} 184 185void InspectorFrontendHost::inspectedURLChanged(const String& newURL) 186{ 187 if (m_client) 188 m_client->inspectedURLChanged(newURL); 189} 190 191void InspectorFrontendHost::setAttachedWindowHeight(unsigned height) 192{ 193 if (m_client) 194 m_client->changeAttachedWindowHeight(height); 195} 196 197void InspectorFrontendHost::setAttachedWindowWidth(unsigned width) 198{ 199 if (m_client) 200 m_client->changeAttachedWindowWidth(width); 201} 202 203void InspectorFrontendHost::setToolbarHeight(unsigned height) 204{ 205 if (m_client) 206 m_client->setToolbarHeight(height); 207} 208 209void InspectorFrontendHost::moveWindowBy(float x, float y) const 210{ 211 if (m_client) 212 m_client->moveWindowBy(x, y); 213} 214 215String InspectorFrontendHost::localizedStringsURL() 216{ 217 return m_client ? m_client->localizedStringsURL() : ""; 218} 219 220String InspectorFrontendHost::debuggableType() 221{ 222 return ASCIILiteral("web"); 223} 224 225void InspectorFrontendHost::copyText(const String& text) 226{ 227 Pasteboard::createForCopyAndPaste()->writePlainText(text, Pasteboard::CannotSmartReplace); 228} 229 230void InspectorFrontendHost::openInNewTab(const String& url) 231{ 232 if (m_client) 233 m_client->openInNewTab(url); 234} 235 236bool InspectorFrontendHost::canSave() 237{ 238 if (m_client) 239 return m_client->canSave(); 240 return false; 241} 242 243void InspectorFrontendHost::save(const String& url, const String& content, bool base64Encoded, bool forceSaveAs) 244{ 245 if (m_client) 246 m_client->save(url, content, base64Encoded, forceSaveAs); 247} 248 249void InspectorFrontendHost::append(const String& url, const String& content) 250{ 251 if (m_client) 252 m_client->append(url, content); 253} 254 255void InspectorFrontendHost::close(const String&) 256{ 257} 258 259void InspectorFrontendHost::sendMessageToBackend(const String& message) 260{ 261 if (m_client) 262 m_client->sendMessageToBackend(message); 263} 264 265#if ENABLE(CONTEXT_MENUS) 266void InspectorFrontendHost::showContextMenu(Event* event, const Vector<ContextMenuItem>& items) 267{ 268 if (!event) 269 return; 270 271 ASSERT(m_frontendPage); 272 JSC::ExecState* frontendExecState = execStateFromPage(debuggerWorld(), m_frontendPage); 273 Deprecated::ScriptObject frontendApiObject; 274 if (!ScriptGlobalObject::get(frontendExecState, "InspectorFrontendAPI", frontendApiObject)) { 275 ASSERT_NOT_REACHED(); 276 return; 277 } 278 RefPtr<FrontendMenuProvider> menuProvider = FrontendMenuProvider::create(this, frontendApiObject, items); 279 m_frontendPage->contextMenuController().showContextMenu(event, menuProvider); 280 m_menuProvider = menuProvider.get(); 281} 282#endif 283 284void InspectorFrontendHost::dispatchEventAsContextMenuEvent(Event* event) 285{ 286#if ENABLE(CONTEXT_MENUS) && USE(ACCESSIBILITY_CONTEXT_MENUS) 287 if (!event || !event->isMouseEvent()) 288 return; 289 290 Frame* frame = event->target()->toNode()->document().frame(); 291 MouseEvent* mouseEvent = toMouseEvent(event); 292 IntPoint mousePoint = IntPoint(mouseEvent->clientX(), mouseEvent->clientY()); 293 294 m_frontendPage->contextMenuController().showContextMenuAt(frame, mousePoint); 295#else 296 UNUSED_PARAM(event); 297#endif 298} 299 300bool InspectorFrontendHost::isUnderTest() 301{ 302 return m_client && m_client->isUnderTest(); 303} 304 305void InspectorFrontendHost::beep() 306{ 307 systemBeep(); 308} 309 310bool InspectorFrontendHost::canSaveAs() 311{ 312 return false; 313} 314 315bool InspectorFrontendHost::canInspectWorkers() 316{ 317 return false; 318} 319 320} // namespace WebCore 321 322#endif // ENABLE(INSPECTOR) 323