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 "core/inspector/InspectorFrontendHost.h" 32 33 #include "bindings/v8/ScriptFunctionCall.h" 34 #include "core/dom/UserGestureIndicator.h" 35 #include "core/inspector/InspectorController.h" 36 #include "core/inspector/InspectorFrontendClient.h" 37 #include "core/loader/FrameLoader.h" 38 #include "core/loader/TextResourceDecoder.h" 39 #include "core/page/ContextMenuController.h" 40 #include "core/page/ContextMenuProvider.h" 41 #include "core/page/Frame.h" 42 #include "core/page/Page.h" 43 #include "core/platform/ContextMenu.h" 44 #include "core/platform/ContextMenuItem.h" 45 #include "core/platform/Pasteboard.h" 46 #include "core/platform/network/ResourceError.h" 47 #include "core/platform/network/ResourceRequest.h" 48 #include "core/platform/network/ResourceResponse.h" 49 #include "core/rendering/RenderTheme.h" 50 #include "modules/filesystem/DOMFileSystem.h" 51 52 namespace WebCore { 53 54 class FrontendMenuProvider : public ContextMenuProvider { 55 public: 56 static PassRefPtr<FrontendMenuProvider> create(InspectorFrontendHost* frontendHost, ScriptObject frontendApiObject, const Vector<ContextMenuItem>& items) 57 { 58 return adoptRef(new FrontendMenuProvider(frontendHost, frontendApiObject, items)); 59 } 60 61 void disconnect() 62 { 63 m_frontendApiObject = ScriptObject(); 64 m_frontendHost = 0; 65 } 66 67 private: 68 FrontendMenuProvider(InspectorFrontendHost* frontendHost, ScriptObject frontendApiObject, const Vector<ContextMenuItem>& items) 69 : m_frontendHost(frontendHost) 70 , m_frontendApiObject(frontendApiObject) 71 , m_items(items) 72 { 73 } 74 75 virtual ~FrontendMenuProvider() 76 { 77 contextMenuCleared(); 78 } 79 80 virtual void populateContextMenu(ContextMenu* menu) 81 { 82 for (size_t i = 0; i < m_items.size(); ++i) 83 menu->appendItem(m_items[i]); 84 } 85 86 virtual void contextMenuItemSelected(const ContextMenuItem* item) 87 { 88 if (m_frontendHost) { 89 UserGestureIndicator gestureIndicator(DefinitelyProcessingNewUserGesture); 90 int itemNumber = item->action() - ContextMenuItemBaseCustomTag; 91 92 ScriptFunctionCall function(m_frontendApiObject, "contextMenuItemSelected"); 93 function.appendArgument(itemNumber); 94 function.call(); 95 } 96 } 97 98 virtual void contextMenuCleared() 99 { 100 if (m_frontendHost) { 101 ScriptFunctionCall function(m_frontendApiObject, "contextMenuCleared"); 102 function.call(); 103 104 m_frontendHost->m_menuProvider = 0; 105 } 106 m_items.clear(); 107 } 108 109 InspectorFrontendHost* m_frontendHost; 110 ScriptObject m_frontendApiObject; 111 Vector<ContextMenuItem> m_items; 112 }; 113 114 InspectorFrontendHost::InspectorFrontendHost(InspectorFrontendClient* client, Page* frontendPage) 115 : m_client(client) 116 , m_frontendPage(frontendPage) 117 , m_menuProvider(0) 118 { 119 ScriptWrappable::init(this); 120 } 121 122 InspectorFrontendHost::~InspectorFrontendHost() 123 { 124 ASSERT(!m_client); 125 } 126 127 void InspectorFrontendHost::disconnectClient() 128 { 129 m_client = 0; 130 if (m_menuProvider) 131 m_menuProvider->disconnect(); 132 m_frontendPage = 0; 133 } 134 135 void InspectorFrontendHost::loaded() 136 { 137 } 138 139 void InspectorFrontendHost::requestSetDockSide(const String& side) 140 { 141 if (!m_client) 142 return; 143 if (side == "undocked") 144 m_client->requestSetDockSide(InspectorFrontendClient::Undocked); 145 else if (side == "right") 146 m_client->requestSetDockSide(InspectorFrontendClient::DockedToRight); 147 else if (side == "bottom") 148 m_client->requestSetDockSide(InspectorFrontendClient::DockedToBottom); 149 } 150 151 void InspectorFrontendHost::closeWindow() 152 { 153 if (m_client) { 154 m_client->closeWindow(); 155 disconnectClient(); // Disconnect from client. 156 } 157 } 158 159 void InspectorFrontendHost::bringToFront() 160 { 161 if (m_client) 162 m_client->bringToFront(); 163 } 164 165 void InspectorFrontendHost::setZoomFactor(float zoom) 166 { 167 m_frontendPage->mainFrame()->setPageAndTextZoomFactors(zoom, 1); 168 } 169 170 void InspectorFrontendHost::inspectedURLChanged(const String& newURL) 171 { 172 if (m_client) 173 m_client->inspectedURLChanged(newURL); 174 } 175 176 void InspectorFrontendHost::setAttachedWindowHeight(unsigned height) 177 { 178 if (m_client) 179 m_client->changeAttachedWindowHeight(height); 180 } 181 182 void InspectorFrontendHost::moveWindowBy(float x, float y) const 183 { 184 if (m_client) 185 m_client->moveWindowBy(x, y); 186 } 187 188 void InspectorFrontendHost::setInjectedScriptForOrigin(const String& origin, const String& script) 189 { 190 ASSERT(m_frontendPage->inspectorController()); 191 m_frontendPage->inspectorController()->setInjectedScriptForOrigin(origin, script); 192 } 193 194 String InspectorFrontendHost::localizedStringsURL() 195 { 196 return ""; 197 } 198 199 void InspectorFrontendHost::copyText(const String& text) 200 { 201 Pasteboard::generalPasteboard()->writePlainText(text, Pasteboard::CannotSmartReplace); 202 } 203 204 void InspectorFrontendHost::openInNewTab(const String& url) 205 { 206 if (m_client) 207 m_client->openInNewTab(url); 208 } 209 210 bool InspectorFrontendHost::canSave() 211 { 212 return true; 213 } 214 215 void InspectorFrontendHost::save(const String& url, const String& content, bool forceSaveAs) 216 { 217 if (m_client) 218 m_client->save(url, content, forceSaveAs); 219 } 220 221 void InspectorFrontendHost::append(const String& url, const String& content) 222 { 223 if (m_client) 224 m_client->append(url, content); 225 } 226 227 void InspectorFrontendHost::close(const String&) 228 { 229 } 230 231 void InspectorFrontendHost::sendMessageToBackend(const String& message) 232 { 233 if (m_client) 234 m_client->sendMessageToBackend(message); 235 } 236 237 void InspectorFrontendHost::showContextMenu(Event* event, const Vector<ContextMenuItem>& items) 238 { 239 if (!event) 240 return; 241 242 ASSERT(m_frontendPage); 243 ScriptState* frontendScriptState = mainWorldScriptState(m_frontendPage->mainFrame()); 244 ScriptObject frontendApiObject; 245 if (!ScriptGlobalObject::get(frontendScriptState, "InspectorFrontendAPI", frontendApiObject)) { 246 ASSERT_NOT_REACHED(); 247 return; 248 } 249 RefPtr<FrontendMenuProvider> menuProvider = FrontendMenuProvider::create(this, frontendApiObject, items); 250 ContextMenuController* menuController = m_frontendPage->contextMenuController(); 251 menuController->showContextMenu(event, menuProvider); 252 m_menuProvider = menuProvider.get(); 253 } 254 255 String InspectorFrontendHost::loadResourceSynchronously(const String& url) 256 { 257 ResourceRequest request(url); 258 request.setHTTPMethod("GET"); 259 260 Vector<char> data; 261 ResourceError error; 262 ResourceResponse response; 263 m_frontendPage->mainFrame()->loader()->loadResourceSynchronously(request, DoNotAllowStoredCredentials, error, response, data); 264 WTF::TextEncoding textEncoding(response.textEncodingName()); 265 bool useDetector = false; 266 if (!textEncoding.isValid()) { 267 textEncoding = UTF8Encoding(); 268 useDetector = true; 269 } 270 RefPtr<TextResourceDecoder> decoder = TextResourceDecoder::create("text/plain", textEncoding, useDetector); 271 return decoder->decode(data.data(), data.size()) + decoder->flush(); 272 } 273 274 String InspectorFrontendHost::getSelectionBackgroundColor() 275 { 276 Color color = m_frontendPage->theme()->activeSelectionBackgroundColor(); 277 return color != Color::transparent ? color.serialized() : ""; 278 } 279 280 String InspectorFrontendHost::getSelectionForegroundColor() 281 { 282 Color color = m_frontendPage->theme()->activeSelectionForegroundColor(); 283 return color != Color::transparent ? color.serialized() : ""; 284 } 285 286 bool InspectorFrontendHost::supportsFileSystems() 287 { 288 return true; 289 } 290 291 void InspectorFrontendHost::requestFileSystems() 292 { 293 if (m_client) 294 m_client->requestFileSystems(); 295 } 296 297 void InspectorFrontendHost::addFileSystem() 298 { 299 if (m_client) 300 m_client->addFileSystem(); 301 } 302 303 void InspectorFrontendHost::removeFileSystem(const String& fileSystemPath) 304 { 305 if (m_client) 306 m_client->removeFileSystem(fileSystemPath); 307 } 308 309 PassRefPtr<DOMFileSystem> InspectorFrontendHost::isolatedFileSystem(const String& fileSystemName, const String& rootURL) 310 { 311 ScriptExecutionContext* context = m_frontendPage->mainFrame()->document(); 312 return DOMFileSystem::create(context, fileSystemName, FileSystemTypeIsolated, KURL(ParsedURLString, rootURL), AsyncFileSystem::create()); 313 } 314 315 void InspectorFrontendHost::indexPath(int requestId, const String& fileSystemPath) 316 { 317 if (m_client) 318 m_client->indexPath(requestId, fileSystemPath); 319 } 320 321 void InspectorFrontendHost::stopIndexing(int requestId) 322 { 323 if (m_client) 324 m_client->stopIndexing(requestId); 325 } 326 327 void InspectorFrontendHost::searchInPath(int requestId, const String& fileSystemPath, const String& query) 328 { 329 if (m_client) 330 m_client->searchInPath(requestId, fileSystemPath, query); 331 } 332 333 bool InspectorFrontendHost::isUnderTest() 334 { 335 return m_client && m_client->isUnderTest(); 336 } 337 338 bool InspectorFrontendHost::canSaveAs() 339 { 340 return false; 341 } 342 343 bool InspectorFrontendHost::canInspectWorkers() 344 { 345 return false; 346 } 347 348 String InspectorFrontendHost::hiddenPanels() 349 { 350 return ""; 351 } 352 353 } // namespace WebCore 354