Web Inspector: get rid of InspectorInstrumentation::inspectorAgents() map
[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 "IdentifiersFactory.h"
39 #include "InjectedScriptHost.h"
40 #include "InjectedScriptManager.h"
41 #include "InspectorAgent.h"
42 #include "InspectorApplicationCacheAgent.h"
43 #include "InspectorBackendDispatcher.h"
44 #include "InspectorCSSAgent.h"
45 #include "InspectorClient.h"
46 #include "InspectorConsoleAgent.h"
47 #include "InspectorDOMAgent.h"
48 #include "InspectorDOMDebuggerAgent.h"
49 #include "InspectorDOMStorageAgent.h"
50 #include "InspectorDatabaseAgent.h"
51 #include "InspectorDebuggerAgent.h"
52 #include "InspectorFrontend.h"
53 #include "InspectorFrontendClient.h"
54 #include "InspectorInstrumentation.h"
55 #include "InspectorPageAgent.h"
56 #include "InspectorProfilerAgent.h"
57 #include "InspectorResourceAgent.h"
58 #include "InspectorRuntimeAgent.h"
59 #include "InspectorState.h"
60 #include "InspectorTimelineAgent.h"
61 #include "InspectorWorkerAgent.h"
62 #include "InstrumentingAgents.h"
63 #include "PageDebuggerAgent.h"
64 #include "Page.h"
65 #include "ScriptObject.h"
66 #include "Settings.h"
67 #include <wtf/UnusedParam.h>
68
69 namespace WebCore {
70
71 namespace {
72
73 class PageRuntimeAgent : public InspectorRuntimeAgent {
74 public:
75     PageRuntimeAgent(InjectedScriptManager* injectedScriptManager, Page* page, InspectorPageAgent* pageAgent)
76         : InspectorRuntimeAgent(injectedScriptManager)
77         , m_inspectedPage(page)
78         , m_pageAgent(pageAgent) { }
79     virtual ~PageRuntimeAgent() { }
80
81 private:
82     virtual ScriptState* scriptStateForFrameId(const String& frameId)
83     {
84         Frame* frame = m_pageAgent->frameForId(frameId);
85         if (!frame)
86             return 0;
87         return mainWorldScriptState(frame);
88     }
89     virtual ScriptState* getDefaultInspectedState() { return mainWorldScriptState(m_inspectedPage->mainFrame()); }
90     Page* m_inspectedPage;
91     InspectorPageAgent* m_pageAgent;
92 };
93
94 }
95
96 InspectorController::InspectorController(Page* page, InspectorClient* inspectorClient)
97     : m_instrumentingAgents(adoptPtr(new InstrumentingAgents()))
98     , m_injectedScriptManager(InjectedScriptManager::createForPage())
99     , m_state(adoptPtr(new InspectorState(inspectorClient)))
100     , m_inspectorAgent(adoptPtr(new InspectorAgent(page, m_injectedScriptManager.get(), m_instrumentingAgents.get())))
101     , m_pageAgent(InspectorPageAgent::create(m_instrumentingAgents.get(), page, m_injectedScriptManager.get()))
102     , m_domAgent(InspectorDOMAgent::create(m_instrumentingAgents.get(), m_pageAgent.get(), inspectorClient, m_state.get(), m_injectedScriptManager.get()))
103     , m_cssAgent(adoptPtr(new InspectorCSSAgent(m_instrumentingAgents.get(), m_domAgent.get())))
104 #if ENABLE(DATABASE)
105     , m_databaseAgent(InspectorDatabaseAgent::create(m_instrumentingAgents.get(), m_state.get()))
106 #endif
107 #if ENABLE(DOM_STORAGE)
108     , m_domStorageAgent(InspectorDOMStorageAgent::create(m_instrumentingAgents.get(), m_state.get()))
109 #endif
110     , m_timelineAgent(InspectorTimelineAgent::create(m_instrumentingAgents.get(), m_state.get()))
111 #if ENABLE(OFFLINE_WEB_APPLICATIONS)
112     , m_applicationCacheAgent(adoptPtr(new InspectorApplicationCacheAgent(m_instrumentingAgents.get(), page)))
113 #endif
114     , m_resourceAgent(InspectorResourceAgent::create(m_instrumentingAgents.get(), m_pageAgent.get(), inspectorClient, m_state.get()))
115     , m_runtimeAgent(adoptPtr(new PageRuntimeAgent(m_injectedScriptManager.get(), page, m_pageAgent.get())))
116     , m_consoleAgent(adoptPtr(new InspectorConsoleAgent(m_instrumentingAgents.get(), m_inspectorAgent.get(), m_state.get(), m_injectedScriptManager.get(), m_domAgent.get())))
117 #if ENABLE(JAVASCRIPT_DEBUGGER)
118     , m_debuggerAgent(PageDebuggerAgent::create(m_instrumentingAgents.get(), m_state.get(), page, m_injectedScriptManager.get()))
119     , m_domDebuggerAgent(InspectorDOMDebuggerAgent::create(m_instrumentingAgents.get(), m_state.get(), m_domAgent.get(), m_debuggerAgent.get(), m_inspectorAgent.get()))
120     , m_profilerAgent(InspectorProfilerAgent::create(m_instrumentingAgents.get(), m_consoleAgent.get(), page, m_state.get()))
121 #endif
122 #if ENABLE(WORKERS)
123     , m_workerAgent(InspectorWorkerAgent::create(m_instrumentingAgents.get(), m_state.get()))
124 #endif
125     , m_page(page)
126     , m_inspectorClient(inspectorClient)
127     , m_openingFrontend(false)
128     , m_startUserInitiatedDebuggingWhenFrontedIsConnected(false)
129 {
130     ASSERT_ARG(inspectorClient, inspectorClient);
131     m_injectedScriptManager->injectedScriptHost()->init(m_inspectorAgent.get()
132         , m_consoleAgent.get()
133 #if ENABLE(DATABASE)
134         , m_databaseAgent.get()
135 #endif
136 #if ENABLE(DOM_STORAGE)
137         , m_domStorageAgent.get()
138 #endif
139     );
140
141 #if ENABLE(JAVASCRIPT_DEBUGGER)
142     m_runtimeAgent->setScriptDebugServer(&m_debuggerAgent->scriptDebugServer());
143 #endif
144 }
145
146 InspectorController::~InspectorController()
147 {
148     ASSERT(!m_inspectorClient);
149 }
150
151 void InspectorController::inspectedPageDestroyed()
152 {
153     disconnectFrontend();
154 #if ENABLE(JAVASCRIPT_DEBUGGER)
155     m_domDebuggerAgent.clear();
156     m_debuggerAgent.clear();
157 #endif
158     m_injectedScriptManager->disconnect();
159     m_inspectorClient->inspectorDestroyed();
160     m_inspectorClient = 0;
161     m_page = 0;
162 }
163
164 void InspectorController::setInspectorFrontendClient(PassOwnPtr<InspectorFrontendClient> inspectorFrontendClient)
165 {
166     m_inspectorFrontendClient = inspectorFrontendClient;
167 }
168
169 bool InspectorController::hasInspectorFrontendClient() const
170 {
171     return m_inspectorFrontendClient;
172 }
173
174 void InspectorController::didClearWindowObjectInWorld(Frame* frame, DOMWrapperWorld* world)
175 {
176     if (world != mainThreadNormalWorld())
177         return;
178
179     // If the page is supposed to serve as InspectorFrontend notify inspector frontend
180     // client that it's cleared so that the client can expose inspector bindings.
181     if (m_inspectorFrontendClient && frame == m_page->mainFrame())
182         m_inspectorFrontendClient->windowObjectCleared();
183 }
184
185 void InspectorController::startTimelineProfiler()
186 {
187     ErrorString error;
188     m_timelineAgent->start(&error, 0);
189 }
190
191 void InspectorController::stopTimelineProfiler()
192 {
193     ErrorString error;
194     m_timelineAgent->stop(&error);
195 }
196
197 void InspectorController::connectFrontend()
198 {
199     m_openingFrontend = false;
200     m_inspectorFrontend = adoptPtr(new InspectorFrontend(m_inspectorClient));
201     m_injectedScriptManager->injectedScriptHost()->setFrontend(m_inspectorFrontend.get());
202     // We can reconnect to existing front-end -> unmute state.
203     m_state->unmute();
204
205 #if ENABLE(OFFLINE_WEB_APPLICATIONS)
206     m_applicationCacheAgent->setFrontend(m_inspectorFrontend.get());
207 #endif
208     m_pageAgent->setFrontend(m_inspectorFrontend.get());
209     m_domAgent->setFrontend(m_inspectorFrontend.get());
210     m_consoleAgent->setFrontend(m_inspectorFrontend.get());
211     m_timelineAgent->setFrontend(m_inspectorFrontend.get());
212     m_resourceAgent->setFrontend(m_inspectorFrontend.get());
213 #if ENABLE(JAVASCRIPT_DEBUGGER)
214     m_debuggerAgent->setFrontend(m_inspectorFrontend.get());
215     m_profilerAgent->setFrontend(m_inspectorFrontend.get());
216 #endif
217 #if ENABLE(DATABASE)
218     m_databaseAgent->setFrontend(m_inspectorFrontend.get());
219 #endif
220 #if ENABLE(DOM_STORAGE)
221     m_domStorageAgent->setFrontend(m_inspectorFrontend.get());
222 #endif
223 #if ENABLE(WORKERS)
224     m_workerAgent->setFrontend(m_inspectorFrontend.get());
225 #endif
226     m_inspectorAgent->setFrontend(m_inspectorFrontend.get());
227
228     if (!InspectorInstrumentation::hasFrontends())
229         ScriptController::setCaptureCallStackForUncaughtExceptions(true);
230     InspectorInstrumentation::frontendCreated();
231
232     ASSERT(m_inspectorClient);
233     m_inspectorBackendDispatcher = adoptRef(new InspectorBackendDispatcher(
234         m_inspectorClient,
235 #if ENABLE(OFFLINE_WEB_APPLICATIONS)
236         m_applicationCacheAgent.get(),
237 #endif
238         m_cssAgent.get(),
239         m_consoleAgent.get(),
240         m_domAgent.get(),
241 #if ENABLE(JAVASCRIPT_DEBUGGER)
242         m_domDebuggerAgent.get(),
243 #endif
244 #if ENABLE(DOM_STORAGE)
245         m_domStorageAgent.get(),
246 #endif
247 #if ENABLE(DATABASE)
248         m_databaseAgent.get(),
249 #endif
250 #if ENABLE(JAVASCRIPT_DEBUGGER)
251         m_debuggerAgent.get(),
252 #endif
253         m_resourceAgent.get(),
254         m_pageAgent.get(),
255 #if ENABLE(JAVASCRIPT_DEBUGGER)
256         m_profilerAgent.get(),
257 #endif
258         m_runtimeAgent.get(),
259         m_timelineAgent.get()
260 #if ENABLE(WORKERS)
261         , m_workerAgent.get()
262 #endif
263     ));
264
265     if (m_startUserInitiatedDebuggingWhenFrontedIsConnected) {
266         m_inspectorFrontend->inspector()->startUserInitiatedDebugging();
267         m_startUserInitiatedDebuggingWhenFrontedIsConnected = false;
268     }
269 }
270
271 void InspectorController::disconnectFrontend()
272 {
273     if (!m_inspectorFrontend)
274         return;
275     m_inspectorBackendDispatcher->clearFrontend();
276     m_inspectorBackendDispatcher.clear();
277
278     // Destroying agents would change the state, but we don't want that.
279     // Pre-disconnect state will be used to restore inspector agents.
280     m_state->mute();
281
282     m_inspectorAgent->clearFrontend();
283 #if ENABLE(JAVASCRIPT_DEBUGGER)
284     m_debuggerAgent->clearFrontend();
285     m_domDebuggerAgent->clearFrontend();
286     m_profilerAgent->clearFrontend();
287 #endif
288 #if ENABLE(OFFLINE_WEB_APPLICATIONS)
289     m_applicationCacheAgent->clearFrontend();
290 #endif
291     m_consoleAgent->clearFrontend();
292     m_domAgent->clearFrontend();
293     m_timelineAgent->clearFrontend();
294     m_resourceAgent->clearFrontend();
295 #if ENABLE(DATABASE)
296     m_databaseAgent->clearFrontend();
297 #endif
298 #if ENABLE(DOM_STORAGE)
299     m_domStorageAgent->clearFrontend();
300 #endif
301     m_pageAgent->clearFrontend();
302 #if ENABLE(WORKERS)
303     m_workerAgent->clearFrontend();
304 #endif
305     m_injectedScriptManager->injectedScriptHost()->clearFrontend();
306
307     m_inspectorFrontend.clear();
308
309     InspectorInstrumentation::frontendDeleted();
310     if (!InspectorInstrumentation::hasFrontends())
311         ScriptController::setCaptureCallStackForUncaughtExceptions(false);
312 }
313
314 void InspectorController::show()
315 {
316     if (!enabled())
317         return;
318
319     if (m_openingFrontend)
320         return;
321
322     if (m_inspectorFrontend)
323         m_inspectorFrontend->inspector()->bringToFront();
324     else {
325         m_openingFrontend = true;
326         m_inspectorClient->openInspectorFrontend(this);
327     }
328 }
329
330 void InspectorController::close()
331 {
332     if (!m_inspectorFrontend)
333         return;
334     m_inspectorFrontend->inspector()->disconnectFromBackend();
335     disconnectFrontend();
336 }
337
338 void InspectorController::restoreInspectorStateFromCookie(const String& inspectorStateCookie)
339 {
340     ASSERT(!m_inspectorFrontend);
341     connectFrontend();
342     m_state->loadFromCookie(inspectorStateCookie);
343
344     m_domAgent->restore();
345     m_resourceAgent->restore();
346     m_timelineAgent->restore();
347     m_consoleAgent->restore();
348 #if ENABLE(DATABASE)
349     m_databaseAgent->restore();
350 #endif
351 #if ENABLE(DOM_STORAGE)
352     m_domStorageAgent->restore();
353 #endif
354 #if ENABLE(WORKERS)
355     m_workerAgent->restore();
356 #endif
357 #if ENABLE(JAVASCRIPT_DEBUGGER)
358     m_debuggerAgent->restore();
359     m_profilerAgent->restore();
360 #endif
361     m_inspectorAgent->restore();
362 }
363
364 void InspectorController::setProcessId(long processId)
365 {
366     IdentifiersFactory::setProcessId(processId);
367 }
368
369 void InspectorController::evaluateForTestInFrontend(long callId, const String& script)
370 {
371     m_inspectorAgent->evaluateForTestInFrontend(callId, script);
372 }
373
374 void InspectorController::drawHighlight(GraphicsContext& context) const
375 {
376     m_domAgent->drawHighlight(context);
377 }
378
379 void InspectorController::showConsole()
380 {
381     if (!enabled())
382         return;
383     show();
384     m_inspectorAgent->showConsole();
385 }
386
387 void InspectorController::inspect(Node* node)
388 {
389     if (!enabled())
390         return;
391
392     show();
393
394     m_domAgent->inspect(node);
395 }
396
397 bool InspectorController::enabled() const
398 {
399     return m_inspectorAgent->enabled();
400 }
401
402 Page* InspectorController::inspectedPage() const
403 {
404     return m_page;
405 }
406
407 bool InspectorController::timelineProfilerEnabled()
408 {
409     return m_timelineAgent->started();
410 }
411
412 void InspectorController::setInspectorExtensionAPI(const String& source)
413 {
414     m_inspectorAgent->setInspectorExtensionAPI(source);
415 }
416
417 void InspectorController::dispatchMessageFromFrontend(const String& message)
418 {
419     if (m_inspectorBackendDispatcher)
420         m_inspectorBackendDispatcher->dispatch(message);
421 }
422
423 void InspectorController::hideHighlight()
424 {
425     ErrorString error;
426     m_domAgent->hideHighlight(&error);
427 }
428
429 Node* InspectorController::highlightedNode() const
430 {
431     return m_domAgent->highlightedNode();
432 }
433
434 #if ENABLE(JAVASCRIPT_DEBUGGER)
435 void InspectorController::enableProfiler()
436 {
437     ErrorString error;
438     m_profilerAgent->enable(&error);
439 }
440
441 void InspectorController::disableProfiler()
442 {
443     ErrorString error;
444     m_profilerAgent->disable(&error);
445 }
446
447 bool InspectorController::profilerEnabled()
448 {
449     return m_profilerAgent->enabled();
450 }
451
452 bool InspectorController::debuggerEnabled()
453 {
454     return m_debuggerAgent->enabled();
455 }
456
457 void InspectorController::showAndEnableDebugger()
458 {
459     if (!enabled())
460         return;
461     show();
462
463     if (m_inspectorFrontend)
464         m_inspectorFrontend->inspector()->startUserInitiatedDebugging();
465     else
466         m_startUserInitiatedDebuggingWhenFrontedIsConnected = true;
467 }
468
469 void InspectorController::disableDebugger()
470 {
471     ErrorString error;
472     m_debuggerAgent->disable(&error);
473 }
474
475 void InspectorController::startUserInitiatedProfiling()
476 {
477     m_profilerAgent->startUserInitiatedProfiling();
478 }
479
480 void InspectorController::stopUserInitiatedProfiling()
481 {
482     if (!enabled())
483         return;
484     show();
485     m_profilerAgent->stopUserInitiatedProfiling();
486     m_inspectorAgent->showProfilesPanel();
487 }
488
489 bool InspectorController::isRecordingUserInitiatedProfile() const
490 {
491     return m_profilerAgent->isRecordingUserInitiatedProfile();
492 }
493
494 void InspectorController::resume()
495 {
496     if (m_debuggerAgent) {
497         ErrorString error;
498         m_debuggerAgent->resume(&error);
499     }
500 }
501
502 #endif
503
504 void InspectorController::setResourcesDataSizeLimitsFromInternals(int maximumResourcesContentSize, int maximumSingleResourceContentSize)
505 {
506     m_resourceAgent->setResourcesDataSizeLimitsFromInternals(maximumResourcesContentSize, maximumSingleResourceContentSize);
507 }
508
509 } // namespace WebCore
510
511 #endif // ENABLE(INSPECTOR)