2011-03-29 Ilya Tikhonovsky <loislo@chromium.org>
[WebKit-https.git] / Source / WebCore / inspector / InspectorController.cpp
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::create())
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 = 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.get(),
136         m_inspectorAgent->resourceAgent(),
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.clear();
154
155     m_inspectorAgent->disconnectFrontend();
156     m_injectedScriptManager->injectedScriptHost()->clearFrontend();
157
158     m_inspectorFrontend.clear();
159
160     InspectorInstrumentation::frontendDeleted();
161     if (!InspectorInstrumentation::hasFrontends())
162         ScriptController::setCaptureCallStackForUncaughtExceptions(false);
163
164 }
165
166 void InspectorController::show()
167 {
168     if (!enabled())
169         return;
170
171     if (m_openingFrontend)
172         return;
173
174     if (m_inspectorFrontend)
175         m_inspectorFrontend->inspector()->bringToFront();
176     else {
177         m_openingFrontend = true;
178         m_inspectorClient->openInspectorFrontend(this);
179     }
180 }
181
182 void InspectorController::close()
183 {
184     if (!m_inspectorFrontend)
185         return;
186     m_inspectorFrontend->inspector()->disconnectFromBackend();
187     disconnectFrontend();
188 }
189
190 void InspectorController::restoreInspectorStateFromCookie(const String& inspectorStateCookie)
191 {
192     ASSERT(!m_inspectorFrontend);
193     connectFrontend();
194     m_inspectorAgent->restoreInspectorStateFromCookie(inspectorStateCookie);
195 }
196
197 void InspectorController::evaluateForTestInFrontend(long callId, const String& script)
198 {
199     m_inspectorAgent->evaluateForTestInFrontend(callId, script);
200 }
201
202 void InspectorController::drawNodeHighlight(GraphicsContext& context) const
203 {
204     m_inspectorAgent->domAgent()->drawNodeHighlight(context);
205 }
206
207 void InspectorController::showConsole()
208 {
209     if (!enabled())
210         return;
211     show();
212     m_inspectorAgent->showConsole();
213 }
214
215 void InspectorController::inspect(Node* node)
216 {
217     if (!enabled())
218         return;
219
220     show();
221
222     m_inspectorAgent->domAgent()->inspect(node);
223 }
224
225 bool InspectorController::enabled() const
226 {
227     return m_inspectorAgent->enabled();
228 }
229
230 Page* InspectorController::inspectedPage() const
231 {
232     return m_inspectorAgent->inspectedPage();
233 }
234
235 bool InspectorController::timelineProfilerEnabled()
236 {
237     return m_inspectorAgent->timelineAgent()->started();
238 }
239
240 void InspectorController::setInspectorExtensionAPI(const String& source)
241 {
242     m_inspectorAgent->setInspectorExtensionAPI(source);
243 }
244
245 void InspectorController::dispatchMessageFromFrontend(const String& message)
246 {
247     if (m_inspectorBackendDispatcher)
248         m_inspectorBackendDispatcher->dispatch(message);
249 }
250
251 void InspectorController::hideHighlight()
252 {
253     ErrorString error;
254     m_inspectorAgent->domAgent()->hideHighlight(&error);
255 }
256
257 #if ENABLE(JAVASCRIPT_DEBUGGER)
258 void InspectorController::enableProfiler()
259 {
260     ErrorString error;
261     m_inspectorAgent->profilerAgent()->enable(&error);
262 }
263
264 void InspectorController::disableProfiler()
265 {
266     ErrorString error;
267     m_inspectorAgent->profilerAgent()->disable(&error);
268 }
269
270 bool InspectorController::profilerEnabled()
271 {
272     return m_inspectorAgent->profilerAgent()->enabled();
273 }
274
275 bool InspectorController::debuggerEnabled()
276 {
277     return m_inspectorAgent->debuggerAgent()->enabled();
278 }
279
280 void InspectorController::showAndEnableDebugger()
281 {
282     if (!enabled())
283         return;
284     show();
285
286     if (m_inspectorFrontend)
287         m_inspectorFrontend->inspector()->startUserInitiatedDebugging();
288     else
289         m_startUserInitiatedDebuggingWhenFrontedIsConnected = true;
290 }
291
292 void InspectorController::disableDebugger()
293 {
294     m_inspectorAgent->debuggerAgent()->disable();
295 }
296
297 void InspectorController::startUserInitiatedProfiling()
298 {
299     m_inspectorAgent->profilerAgent()->startUserInitiatedProfiling();
300 }
301
302 void InspectorController::stopUserInitiatedProfiling()
303 {
304     if (!enabled())
305         return;
306     show();
307     m_inspectorAgent->profilerAgent()->stopUserInitiatedProfiling();
308     m_inspectorAgent->showProfilesPanel();
309 }
310
311 bool InspectorController::isRecordingUserInitiatedProfile() const
312 {
313     return m_inspectorAgent->profilerAgent()->isRecordingUserInitiatedProfile();
314 }
315
316 void InspectorController::resume()
317 {
318     if (InspectorDebuggerAgent* debuggerAgent = m_inspectorAgent->debuggerAgent()) {
319         ErrorString error;
320         debuggerAgent->resume(&error);
321     }
322 }
323
324 #endif
325
326 } // namespace WebCore
327
328 #endif // ENABLE(INSPECTOR)