1 /* 2 * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. 3 * Copyright (C) 2008 Matt Lilek <webkit (at) 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 Computer, 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 #include "InspectorFrontendHost.h" 32 33 #if ENABLE(INSPECTOR) 34 35 #include "ContextMenu.h" 36 #include "ContextMenuItem.h" 37 #include "ContextMenuController.h" 38 #include "ContextMenuProvider.h" 39 #include "Element.h" 40 #include "Frame.h" 41 #include "FrameLoader.h" 42 #include "HitTestResult.h" 43 #include "HTMLFrameOwnerElement.h" 44 #include "InspectorAgent.h" 45 #include "InspectorController.h" 46 #include "InspectorFrontendClient.h" 47 #include "Page.h" 48 #include "Pasteboard.h" 49 #include "ScriptFunctionCall.h" 50 51 #include <wtf/RefPtr.h> 52 #include <wtf/StdLibExtras.h> 53 54 using namespace std; 55 56 namespace WebCore { 57 58 #if ENABLE(CONTEXT_MENUS) 59 class FrontendMenuProvider : public ContextMenuProvider { 60 public: 61 static PassRefPtr<FrontendMenuProvider> create(InspectorFrontendHost* frontendHost, ScriptObject webInspector, const Vector<ContextMenuItem*>& items) 62 { 63 return adoptRef(new FrontendMenuProvider(frontendHost, webInspector, items)); 64 } 65 66 void disconnect() 67 { 68 m_webInspector = ScriptObject(); 69 m_frontendHost = 0; 70 } 71 72 private: 73 FrontendMenuProvider(InspectorFrontendHost* frontendHost, ScriptObject webInspector, const Vector<ContextMenuItem*>& items) 74 : m_frontendHost(frontendHost) 75 , m_webInspector(webInspector) 76 , m_items(items) 77 { 78 } 79 80 virtual ~FrontendMenuProvider() 81 { 82 contextMenuCleared(); 83 } 84 85 virtual void populateContextMenu(ContextMenu* menu) 86 { 87 for (size_t i = 0; i < m_items.size(); ++i) 88 menu->appendItem(*m_items[i]); 89 } 90 91 virtual void contextMenuItemSelected(ContextMenuItem* item) 92 { 93 if (m_frontendHost) { 94 int itemNumber = item->action() - ContextMenuItemBaseCustomTag; 95 96 ScriptFunctionCall function(m_webInspector, "contextMenuItemSelected"); 97 function.appendArgument(itemNumber); 98 function.call(); 99 } 100 } 101 102 virtual void contextMenuCleared() 103 { 104 if (m_frontendHost) { 105 ScriptFunctionCall function(m_webInspector, "contextMenuCleared"); 106 function.call(); 107 108 m_frontendHost->m_menuProvider = 0; 109 } 110 deleteAllValues(m_items); 111 m_items.clear(); 112 } 113 114 InspectorFrontendHost* m_frontendHost; 115 ScriptObject m_webInspector; 116 Vector<ContextMenuItem*> m_items; 117 }; 118 #endif 119 120 InspectorFrontendHost::InspectorFrontendHost(InspectorFrontendClient* client, Page* frontendPage) 121 : m_client(client) 122 , m_frontendPage(frontendPage) 123 #if ENABLE(CONTEXT_MENUS) 124 , m_menuProvider(0) 125 #endif 126 { 127 } 128 129 InspectorFrontendHost::~InspectorFrontendHost() 130 { 131 ASSERT(!m_client); 132 } 133 134 void InspectorFrontendHost::disconnectClient() 135 { 136 m_client = 0; 137 #if ENABLE(CONTEXT_MENUS) 138 if (m_menuProvider) 139 m_menuProvider->disconnect(); 140 #endif 141 m_frontendPage = 0; 142 } 143 144 void InspectorFrontendHost::loaded() 145 { 146 if (m_client) 147 m_client->frontendLoaded(); 148 } 149 150 void InspectorFrontendHost::requestAttachWindow() 151 { 152 if (m_client) 153 m_client->requestAttachWindow(); 154 } 155 156 void InspectorFrontendHost::requestDetachWindow() 157 { 158 if (m_client) 159 m_client->requestDetachWindow(); 160 } 161 162 void InspectorFrontendHost::closeWindow() 163 { 164 if (m_client) { 165 m_client->closeWindow(); 166 disconnectClient(); // Disconnect from client. 167 } 168 } 169 170 void InspectorFrontendHost::disconnectFromBackend() 171 { 172 if (m_client) { 173 m_client->disconnectFromBackend(); 174 disconnectClient(); // Disconnect from client. 175 } 176 } 177 178 void InspectorFrontendHost::bringToFront() 179 { 180 if (m_client) 181 m_client->bringToFront(); 182 } 183 184 void InspectorFrontendHost::inspectedURLChanged(const String& newURL) 185 { 186 if (m_client) 187 m_client->inspectedURLChanged(newURL); 188 } 189 190 void InspectorFrontendHost::setAttachedWindowHeight(unsigned height) 191 { 192 if (m_client) 193 m_client->changeAttachedWindowHeight(height); 194 } 195 196 void InspectorFrontendHost::moveWindowBy(float x, float y) const 197 { 198 if (m_client) 199 m_client->moveWindowBy(x, y); 200 } 201 202 void InspectorFrontendHost::setExtensionAPI(const String& script) 203 { 204 ASSERT(m_frontendPage->inspectorController()); 205 m_frontendPage->inspectorController()->setInspectorExtensionAPI(script); 206 } 207 208 String InspectorFrontendHost::localizedStringsURL() 209 { 210 return m_client->localizedStringsURL(); 211 } 212 213 String InspectorFrontendHost::hiddenPanels() 214 { 215 return m_client->hiddenPanels(); 216 } 217 218 void InspectorFrontendHost::copyText(const String& text) 219 { 220 Pasteboard::generalPasteboard()->writePlainText(text); 221 } 222 223 void InspectorFrontendHost::saveSessionSetting(const String& key, const String& value) 224 { 225 if (m_client) 226 m_client->saveSessionSetting(key, value); 227 } 228 229 String InspectorFrontendHost::loadSessionSetting(const String& key) 230 { 231 String value; 232 if (m_client) 233 m_client->loadSessionSetting(key, &value); 234 return value; 235 } 236 237 void InspectorFrontendHost::sendMessageToBackend(const String& message) 238 { 239 if (m_client) 240 m_client->sendMessageToBackend(message); 241 } 242 243 #if ENABLE(CONTEXT_MENUS) 244 void InspectorFrontendHost::showContextMenu(Event* event, const Vector<ContextMenuItem*>& items) 245 { 246 ASSERT(m_frontendPage); 247 ScriptState* frontendScriptState = scriptStateFromPage(debuggerWorld(), m_frontendPage); 248 ScriptObject webInspectorObj; 249 if (!ScriptGlobalObject::get(frontendScriptState, "WebInspector", webInspectorObj)) { 250 ASSERT_NOT_REACHED(); 251 return; 252 } 253 RefPtr<FrontendMenuProvider> menuProvider = FrontendMenuProvider::create(this, webInspectorObj, items); 254 ContextMenuController* menuController = m_frontendPage->contextMenuController(); 255 menuController->showContextMenu(event, menuProvider); 256 m_menuProvider = menuProvider.get(); 257 } 258 #endif 259 260 } // namespace WebCore 261 262 #endif // ENABLE(INSPECTOR) 263