1 /* 2 * Copyright (C) 2011 Google Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are 6 * met: 7 * 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above 11 * copyright notice, this list of conditions and the following disclaimer 12 * in the documentation and/or other materials provided with the 13 * distribution. 14 * * Neither the name of Google Inc. nor the names of its 15 * contributors may be used to endorse or promote products derived from 16 * this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 #include "config.h" 32 #include "InspectorController.h" 33 34 #if ENABLE(INSPECTOR) 35 36 #include "Frame.h" 37 #include "GraphicsContext.h" 38 #include "InjectedScriptHost.h" 39 #include "InjectedScriptManager.h" 40 #include "InspectorAgent.h" 41 #include "InspectorBackendDispatcher.h" 42 #include "InspectorBrowserDebuggerAgent.h" 43 #include "InspectorDebuggerAgent.h" 44 #include "InspectorClient.h" 45 #include "InspectorDOMAgent.h" 46 #include "InspectorFrontend.h" 47 #include "InspectorFrontendClient.h" 48 #include "InspectorInstrumentation.h" 49 #include "InspectorProfilerAgent.h" 50 #include "InspectorTimelineAgent.h" 51 #include "Page.h" 52 #include "ScriptObject.h" 53 #include "Settings.h" 54 55 namespace WebCore { 56 57 InspectorController::InspectorController(Page* page, InspectorClient* inspectorClient) 58 : m_injectedScriptManager(InjectedScriptManager::createForPage()) 59 , m_inspectorAgent(new InspectorAgent(page, inspectorClient, m_injectedScriptManager.get())) 60 , m_inspectorClient(inspectorClient) 61 , m_openingFrontend(false) 62 , m_startUserInitiatedDebuggingWhenFrontedIsConnected(false) 63 { 64 } 65 66 InspectorController::~InspectorController() 67 { 68 } 69 70 void InspectorController::setInspectorFrontendClient(PassOwnPtr<InspectorFrontendClient> inspectorFrontendClient) 71 { 72 m_inspectorFrontendClient = inspectorFrontendClient; 73 } 74 75 bool InspectorController::hasInspectorFrontendClient() const 76 { 77 return m_inspectorFrontendClient; 78 } 79 80 void InspectorController::didClearWindowObjectInWorld(Frame* frame, DOMWrapperWorld* world) 81 { 82 if (world != mainThreadNormalWorld()) 83 return; 84 85 // If the page is supposed to serve as InspectorFrontend notify inspector frontend 86 // client that it's cleared so that the client can expose inspector bindings. 87 if (m_inspectorFrontendClient && frame == m_inspectorAgent->inspectedPage()->mainFrame()) 88 m_inspectorFrontendClient->windowObjectCleared(); 89 } 90 91 void InspectorController::startTimelineProfiler() 92 { 93 ErrorString error; 94 m_inspectorAgent->timelineAgent()->start(&error); 95 } 96 97 void InspectorController::stopTimelineProfiler() 98 { 99 ErrorString error; 100 m_inspectorAgent->timelineAgent()->stop(&error); 101 } 102 103 void InspectorController::connectFrontend() 104 { 105 m_openingFrontend = false; 106 m_inspectorFrontend = new InspectorFrontend(m_inspectorClient); 107 m_injectedScriptManager->injectedScriptHost()->setFrontend(m_inspectorFrontend.get()); 108 m_inspectorAgent->setFrontend(m_inspectorFrontend.get()); 109 110 if (!InspectorInstrumentation::hasFrontends()) 111 ScriptController::setCaptureCallStackForUncaughtExceptions(true); 112 InspectorInstrumentation::frontendCreated(); 113 114 ASSERT(m_inspectorClient); 115 m_inspectorBackendDispatcher = adoptRef(new InspectorBackendDispatcher( 116 m_inspectorClient, 117 #if ENABLE(OFFLINE_WEB_APPLICATIONS) 118 m_inspectorAgent->applicationCacheAgent(), 119 #endif 120 #if ENABLE(JAVASCRIPT_DEBUGGER) 121 m_inspectorAgent->browserDebuggerAgent(), 122 #endif 123 m_inspectorAgent->cssAgent(), 124 m_inspectorAgent->consoleAgent(), 125 m_inspectorAgent->domAgent(), 126 #if ENABLE(DOM_STORAGE) 127 m_inspectorAgent->domStorageAgent(), 128 #endif 129 #if ENABLE(DATABASE) 130 m_inspectorAgent->databaseAgent(), 131 #endif 132 #if ENABLE(JAVASCRIPT_DEBUGGER) 133 m_inspectorAgent->debuggerAgent(), 134 #endif 135 m_inspectorAgent->resourceAgent(), 136 m_inspectorAgent->pageAgent(), 137 #if ENABLE(JAVASCRIPT_DEBUGGER) 138 m_inspectorAgent->profilerAgent(), 139 #endif 140 m_inspectorAgent->runtimeAgent(), 141 m_inspectorAgent->timelineAgent())); 142 143 if (m_startUserInitiatedDebuggingWhenFrontedIsConnected) { 144 m_inspectorFrontend->inspector()->startUserInitiatedDebugging(); 145 m_startUserInitiatedDebuggingWhenFrontedIsConnected = false; 146 } 147 } 148 149 void InspectorController::disconnectFrontend() 150 { 151 if (!m_inspectorFrontend) 152 return; 153 m_inspectorBackendDispatcher->clearFrontend(); 154 m_inspectorBackendDispatcher.clear(); 155 156 m_inspectorAgent->disconnectFrontend(); 157 m_injectedScriptManager->injectedScriptHost()->clearFrontend(); 158 159 m_inspectorFrontend.clear(); 160 161 InspectorInstrumentation::frontendDeleted(); 162 if (!InspectorInstrumentation::hasFrontends()) 163 ScriptController::setCaptureCallStackForUncaughtExceptions(false); 164 165 } 166 167 void InspectorController::show() 168 { 169 if (!enabled()) 170 return; 171 172 if (m_openingFrontend) 173 return; 174 175 if (m_inspectorFrontend) 176 m_inspectorFrontend->inspector()->bringToFront(); 177 else { 178 m_openingFrontend = true; 179 m_inspectorClient->openInspectorFrontend(this); 180 } 181 } 182 183 void InspectorController::close() 184 { 185 if (!m_inspectorFrontend) 186 return; 187 m_inspectorFrontend->inspector()->disconnectFromBackend(); 188 disconnectFrontend(); 189 } 190 191 void InspectorController::restoreInspectorStateFromCookie(const String& inspectorStateCookie) 192 { 193 ASSERT(!m_inspectorFrontend); 194 connectFrontend(); 195 m_inspectorAgent->restoreInspectorStateFromCookie(inspectorStateCookie); 196 } 197 198 void InspectorController::evaluateForTestInFrontend(long callId, const String& script) 199 { 200 m_inspectorAgent->evaluateForTestInFrontend(callId, script); 201 } 202 203 void InspectorController::drawNodeHighlight(GraphicsContext& context) const 204 { 205 m_inspectorAgent->domAgent()->drawNodeHighlight(context); 206 } 207 208 void InspectorController::showConsole() 209 { 210 if (!enabled()) 211 return; 212 show(); 213 m_inspectorAgent->showConsole(); 214 } 215 216 void InspectorController::inspect(Node* node) 217 { 218 if (!enabled()) 219 return; 220 221 show(); 222 223 m_inspectorAgent->domAgent()->inspect(node); 224 } 225 226 bool InspectorController::enabled() const 227 { 228 return m_inspectorAgent->enabled(); 229 } 230 231 Page* InspectorController::inspectedPage() const 232 { 233 return m_inspectorAgent->inspectedPage(); 234 } 235 236 bool InspectorController::timelineProfilerEnabled() 237 { 238 return m_inspectorAgent->timelineAgent()->started(); 239 } 240 241 void InspectorController::setInspectorExtensionAPI(const String& source) 242 { 243 m_inspectorAgent->setInspectorExtensionAPI(source); 244 } 245 246 void InspectorController::dispatchMessageFromFrontend(const String& message) 247 { 248 if (m_inspectorBackendDispatcher) 249 m_inspectorBackendDispatcher->dispatch(message); 250 } 251 252 void InspectorController::hideHighlight() 253 { 254 ErrorString error; 255 m_inspectorAgent->domAgent()->hideHighlight(&error); 256 } 257 258 Node* InspectorController::highlightedNode() const 259 { 260 return m_inspectorAgent->domAgent()->highlightedNode(); 261 } 262 263 #if ENABLE(JAVASCRIPT_DEBUGGER) 264 void InspectorController::enableProfiler() 265 { 266 ErrorString error; 267 m_inspectorAgent->profilerAgent()->enable(&error); 268 } 269 270 void InspectorController::disableProfiler() 271 { 272 ErrorString error; 273 m_inspectorAgent->profilerAgent()->disable(&error); 274 } 275 276 bool InspectorController::profilerEnabled() 277 { 278 return m_inspectorAgent->profilerAgent()->enabled(); 279 } 280 281 bool InspectorController::debuggerEnabled() 282 { 283 return m_inspectorAgent->debuggerAgent()->enabled(); 284 } 285 286 void InspectorController::showAndEnableDebugger() 287 { 288 if (!enabled()) 289 return; 290 show(); 291 292 if (m_inspectorFrontend) 293 m_inspectorFrontend->inspector()->startUserInitiatedDebugging(); 294 else 295 m_startUserInitiatedDebuggingWhenFrontedIsConnected = true; 296 } 297 298 void InspectorController::disableDebugger() 299 { 300 m_inspectorAgent->debuggerAgent()->disable(); 301 } 302 303 void InspectorController::startUserInitiatedProfiling() 304 { 305 m_inspectorAgent->profilerAgent()->startUserInitiatedProfiling(); 306 } 307 308 void InspectorController::stopUserInitiatedProfiling() 309 { 310 if (!enabled()) 311 return; 312 show(); 313 m_inspectorAgent->profilerAgent()->stopUserInitiatedProfiling(); 314 m_inspectorAgent->showProfilesPanel(); 315 } 316 317 bool InspectorController::isRecordingUserInitiatedProfile() const 318 { 319 return m_inspectorAgent->profilerAgent()->isRecordingUserInitiatedProfile(); 320 } 321 322 void InspectorController::resume() 323 { 324 if (InspectorDebuggerAgent* debuggerAgent = m_inspectorAgent->debuggerAgent()) { 325 ErrorString error; 326 debuggerAgent->resume(&error); 327 } 328 } 329 330 #endif 331 332 } // namespace WebCore 333 334 #endif // ENABLE(INSPECTOR) 335