431baade524fa7ca14e59f9cba2c665bbf113d4c
[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 "CommandLineAPIHost.h"
37 #include "DOMWrapperWorld.h"
38 #include "GraphicsContext.h"
39 #include "IdentifiersFactory.h"
40 #include "InspectorApplicationCacheAgent.h"
41 #include "InspectorCSSAgent.h"
42 #include "InspectorCanvasAgent.h"
43 #include "InspectorClient.h"
44 #include "InspectorDOMAgent.h"
45 #include "InspectorDOMDebuggerAgent.h"
46 #include "InspectorDOMStorageAgent.h"
47 #include "InspectorDatabaseAgent.h"
48 #include "InspectorFrontendClient.h"
49 #include "InspectorHeapProfilerAgent.h"
50 #include "InspectorIndexedDBAgent.h"
51 #include "InspectorInputAgent.h"
52 #include "InspectorInstrumentation.h"
53 #include "InspectorLayerTreeAgent.h"
54 #include "InspectorMemoryAgent.h"
55 #include "InspectorOverlay.h"
56 #include "InspectorPageAgent.h"
57 #include "InspectorProfilerAgent.h"
58 #include "InspectorResourceAgent.h"
59 #include "InspectorTimelineAgent.h"
60 #include "InspectorWebBackendDispatchers.h"
61 #include "InspectorWebFrontendDispatchers.h"
62 #include "InspectorWorkerAgent.h"
63 #include "InstrumentingAgents.h"
64 #include "JSDOMWindow.h"
65 #include "JSDOMWindowCustom.h"
66 #include "JSMainThreadExecState.h"
67 #include "MainFrame.h"
68 #include "Page.h"
69 #include "PageConsoleAgent.h"
70 #include "PageDebuggerAgent.h"
71 #include "PageInjectedScriptHost.h"
72 #include "PageInjectedScriptManager.h"
73 #include "PageRuntimeAgent.h"
74 #include "Settings.h"
75 #include <inspector/InspectorBackendDispatcher.h>
76 #include <inspector/agents/InspectorAgent.h>
77 #include <runtime/JSLock.h>
78
79 using namespace JSC;
80 using namespace Inspector;
81
82 namespace WebCore {
83
84 InspectorController::InspectorController(Page& page, InspectorClient* inspectorClient)
85     : m_instrumentingAgents(InstrumentingAgents::create(*this))
86     , m_injectedScriptManager(std::make_unique<PageInjectedScriptManager>(*this, PageInjectedScriptHost::create()))
87     , m_overlay(std::make_unique<InspectorOverlay>(page, inspectorClient))
88     , m_inspectorFrontendChannel(nullptr)
89     , m_page(page)
90     , m_inspectorClient(inspectorClient)
91     , m_isUnderTest(false)
92 #if ENABLE(REMOTE_INSPECTOR)
93     , m_hasRemoteFrontend(false)
94 #endif
95 {
96     ASSERT_ARG(inspectorClient, inspectorClient);
97
98     auto inspectorAgentPtr = std::make_unique<InspectorAgent>();
99     m_inspectorAgent = inspectorAgentPtr.get();
100     m_instrumentingAgents->setInspectorAgent(m_inspectorAgent);
101     m_agents.append(std::move(inspectorAgentPtr));
102
103     auto pageAgentPtr = std::make_unique<InspectorPageAgent>(m_instrumentingAgents.get(), &page, inspectorClient, m_overlay.get());
104     InspectorPageAgent* pageAgent = pageAgentPtr.get();
105     m_pageAgent = pageAgentPtr.get();
106     m_agents.append(std::move(pageAgentPtr));
107
108     auto runtimeAgentPtr = std::make_unique<PageRuntimeAgent>(m_injectedScriptManager.get(), &page, pageAgent);
109     PageRuntimeAgent* runtimeAgent = runtimeAgentPtr.get();
110     m_instrumentingAgents->setPageRuntimeAgent(runtimeAgent);
111     m_agents.append(std::move(runtimeAgentPtr));
112
113     auto domAgentPtr = std::make_unique<InspectorDOMAgent>(m_instrumentingAgents.get(), pageAgent, m_injectedScriptManager.get(), m_overlay.get());
114     m_domAgent = domAgentPtr.get();
115     m_agents.append(std::move(domAgentPtr));
116
117     m_agents.append(std::make_unique<InspectorCSSAgent>(m_instrumentingAgents.get(), m_domAgent));
118
119 #if ENABLE(SQL_DATABASE)
120     auto databaseAgentPtr = std::make_unique<InspectorDatabaseAgent>(m_instrumentingAgents.get());
121     InspectorDatabaseAgent* databaseAgent = databaseAgentPtr.get();
122     m_agents.append(std::move(databaseAgentPtr));
123 #endif
124
125 #if ENABLE(INDEXED_DATABASE)
126     m_agents.append(std::make_unique<InspectorIndexedDBAgent>(m_instrumentingAgents.get(), m_injectedScriptManager.get(), pageAgent));
127 #endif
128
129     auto domStorageAgentPtr = std::make_unique<InspectorDOMStorageAgent>(m_instrumentingAgents.get(), m_pageAgent);
130     InspectorDOMStorageAgent* domStorageAgent = domStorageAgentPtr.get();
131     m_agents.append(std::move(domStorageAgentPtr));
132
133     auto memoryAgentPtr = std::make_unique<InspectorMemoryAgent>(m_instrumentingAgents.get());
134     m_memoryAgent = memoryAgentPtr.get();
135     m_agents.append(std::move(memoryAgentPtr));
136
137     m_agents.append(std::make_unique<InspectorTimelineAgent>(m_instrumentingAgents.get(), pageAgent, m_memoryAgent, InspectorTimelineAgent::PageInspector, inspectorClient));
138     m_agents.append(std::make_unique<InspectorApplicationCacheAgent>(m_instrumentingAgents.get(), pageAgent));
139
140     auto resourceAgentPtr = std::make_unique<InspectorResourceAgent>(m_instrumentingAgents.get(), pageAgent, inspectorClient);
141     m_resourceAgent = resourceAgentPtr.get();
142     m_agents.append(std::move(resourceAgentPtr));
143
144     auto consoleAgentPtr = std::make_unique<PageConsoleAgent>(m_instrumentingAgents.get(), m_injectedScriptManager.get(), m_domAgent);
145     InspectorConsoleAgent* consoleAgent = consoleAgentPtr.get();
146     m_agents.append(std::move(consoleAgentPtr));
147
148 #if ENABLE(JAVASCRIPT_DEBUGGER)
149     auto debuggerAgentPtr = std::make_unique<PageDebuggerAgent>(m_injectedScriptManager.get(), m_instrumentingAgents.get(), pageAgent, m_overlay.get());
150     m_debuggerAgent = debuggerAgentPtr.get();
151     m_agents.append(std::move(debuggerAgentPtr));
152
153     auto domDebuggerAgentPtr = std::make_unique<InspectorDOMDebuggerAgent>(m_instrumentingAgents.get(), m_domAgent, m_debuggerAgent);
154     m_domDebuggerAgent = domDebuggerAgentPtr.get();
155     m_agents.append(std::move(domDebuggerAgentPtr));
156
157     auto profilerAgentPtr = InspectorProfilerAgent::create(m_instrumentingAgents.get(), consoleAgent, &page, m_injectedScriptManager.get());
158     m_profilerAgent = profilerAgentPtr.get();
159     m_agents.append(std::move(profilerAgentPtr));
160
161     m_agents.append(std::make_unique<InspectorHeapProfilerAgent>(m_instrumentingAgents.get(), m_injectedScriptManager.get()));
162 #endif
163
164     m_agents.append(std::make_unique<InspectorWorkerAgent>(m_instrumentingAgents.get()));
165
166     m_agents.append(std::make_unique<InspectorCanvasAgent>(m_instrumentingAgents.get(), pageAgent, m_injectedScriptManager.get()));
167
168     m_agents.append(std::make_unique<InspectorInputAgent>(m_instrumentingAgents.get(), &page));
169
170 #if USE(ACCELERATED_COMPOSITING)
171     m_agents.append(std::make_unique<InspectorLayerTreeAgent>(m_instrumentingAgents.get()));
172 #endif
173
174     ASSERT(m_injectedScriptManager->commandLineAPIHost());
175     if (CommandLineAPIHost* commandLineAPIHost = m_injectedScriptManager->commandLineAPIHost()) {
176         commandLineAPIHost->init(m_inspectorAgent
177             , consoleAgent
178             , m_domAgent
179             , domStorageAgent
180 #if ENABLE(SQL_DATABASE)
181             , databaseAgent
182 #endif
183         );
184     }
185
186 #if ENABLE(JAVASCRIPT_DEBUGGER)
187     runtimeAgent->setScriptDebugServer(&m_debuggerAgent->scriptDebugServer());
188 #endif
189 }
190
191 InspectorController::~InspectorController()
192 {
193     m_instrumentingAgents->reset();
194     m_agents.discardAgents();
195     ASSERT(!m_inspectorClient);
196 }
197
198 void InspectorController::inspectedPageDestroyed()
199 {
200     disconnectFrontend(InspectorDisconnectReason::InspectedTargetDestroyed);
201     m_injectedScriptManager->disconnect();
202     m_inspectorClient->inspectorDestroyed();
203     m_inspectorClient = nullptr;
204 }
205
206 void InspectorController::setInspectorFrontendClient(std::unique_ptr<InspectorFrontendClient> inspectorFrontendClient)
207 {
208     m_inspectorFrontendClient = std::move(inspectorFrontendClient);
209 }
210
211 bool InspectorController::hasLocalFrontend() const
212 {
213 #if ENABLE(REMOTE_INSPECTOR)
214     return hasFrontend() && !m_hasRemoteFrontend;
215 #else
216     return hasFrontend();
217 #endif
218 }
219
220 bool InspectorController::hasRemoteFrontend() const
221 {
222 #if ENABLE(REMOTE_INSPECTOR)
223     return m_hasRemoteFrontend;
224 #else
225     return false;
226 #endif
227 }
228
229 bool InspectorController::hasInspectorFrontendClient() const
230 {
231     return m_inspectorFrontendClient.get();
232 }
233
234 void InspectorController::didClearWindowObjectInWorld(Frame* frame, DOMWrapperWorld& world)
235 {
236     if (&world != &mainThreadNormalWorld())
237         return;
238
239     if (frame->isMainFrame())
240         m_injectedScriptManager->discardInjectedScripts();
241
242     // If the page is supposed to serve as InspectorFrontend notify inspector frontend
243     // client that it's cleared so that the client can expose inspector bindings.
244     if (m_inspectorFrontendClient && frame->isMainFrame())
245         m_inspectorFrontendClient->windowObjectCleared();
246 }
247
248 void InspectorController::connectFrontend(InspectorFrontendChannel* frontendChannel)
249 {
250     ASSERT(frontendChannel);
251     ASSERT(m_inspectorClient);
252     ASSERT(!m_inspectorFrontendChannel);
253     ASSERT(!m_inspectorBackendDispatcher);
254
255     m_inspectorFrontendChannel = frontendChannel;
256     m_inspectorBackendDispatcher = InspectorBackendDispatcher::create(frontendChannel);
257
258     m_agents.didCreateFrontendAndBackend(frontendChannel, m_inspectorBackendDispatcher.get());
259
260     InspectorInstrumentation::registerInstrumentingAgents(m_instrumentingAgents.get());
261     InspectorInstrumentation::frontendCreated();
262
263 #if ENABLE(REMOTE_INSPECTOR)
264     if (!m_hasRemoteFrontend)
265         m_page.remoteInspectorInformationDidChange();
266 #endif
267 }
268
269 void InspectorController::disconnectFrontend(InspectorDisconnectReason reason)
270 {
271     if (!m_inspectorFrontendChannel)
272         return;
273
274     m_agents.willDestroyFrontendAndBackend(reason);
275
276     m_inspectorBackendDispatcher->clearFrontend();
277     m_inspectorBackendDispatcher.clear();
278     m_inspectorFrontendChannel = nullptr;
279
280     // relese overlay page resources
281     m_overlay->freePage();
282     InspectorInstrumentation::frontendDeleted();
283     InspectorInstrumentation::unregisterInstrumentingAgents(m_instrumentingAgents.get());
284
285 #if ENABLE(REMOTE_INSPECTOR)
286     if (!m_hasRemoteFrontend)
287         m_page.remoteInspectorInformationDidChange();
288 #endif
289 }
290
291 void InspectorController::show()
292 {
293     ASSERT(!hasRemoteFrontend());
294
295     if (!enabled())
296         return;
297
298     if (m_inspectorFrontendChannel)
299         m_inspectorClient->bringFrontendToFront();
300     else {
301         InspectorFrontendChannel* frontendChannel = m_inspectorClient->openInspectorFrontend(this);
302         if (frontendChannel)
303             connectFrontend(frontendChannel);
304     }
305 }
306
307 void InspectorController::close()
308 {
309     if (!m_inspectorFrontendChannel)
310         return;
311     disconnectFrontend(InspectorDisconnectReason::InspectorDestroyed);
312     m_inspectorClient->closeInspectorFrontend();
313 }
314
315 void InspectorController::setProcessId(long processId)
316 {
317     IdentifiersFactory::setProcessId(processId);
318 }
319
320 bool InspectorController::isUnderTest()
321 {
322     return m_isUnderTest;
323 }
324
325 void InspectorController::evaluateForTestInFrontend(long callId, const String& script)
326 {
327     m_isUnderTest = true;
328     m_inspectorAgent->evaluateForTestInFrontend(callId, script);
329 }
330
331 void InspectorController::drawHighlight(GraphicsContext& context) const
332 {
333     m_overlay->paint(context);
334 }
335
336 void InspectorController::getHighlight(Highlight* highlight) const
337 {
338     m_overlay->getHighlight(highlight);
339 }
340
341 PassRefPtr<InspectorObject> InspectorController::buildObjectForHighlightedNode() const
342 {
343     return m_overlay->buildObjectForHighlightedNode();
344 }
345
346 void InspectorController::inspect(Node* node)
347 {
348     if (!enabled())
349         return;
350
351     if (!hasRemoteFrontend())
352         show();
353
354     m_domAgent->inspect(node);
355 }
356
357 bool InspectorController::enabled() const
358 {
359     return developerExtrasEnabled();
360 }
361
362 Page& InspectorController::inspectedPage() const
363 {
364     return m_page;
365 }
366
367 void InspectorController::dispatchMessageFromFrontend(const String& message)
368 {
369     if (m_inspectorBackendDispatcher)
370         m_inspectorBackendDispatcher->dispatch(message);
371 }
372
373 void InspectorController::hideHighlight()
374 {
375     ErrorString error;
376     m_domAgent->hideHighlight(&error);
377 }
378
379 Node* InspectorController::highlightedNode() const
380 {
381     return m_overlay->highlightedNode();
382 }
383
384 void InspectorController::setIndicating(bool indicating)
385 {
386     // FIXME: For non-iOS clients, we should have InspectorOverlay do something here.
387     if (indicating)
388         m_inspectorClient->indicate();
389     else
390         m_inspectorClient->hideIndication();
391 }
392
393 #if ENABLE(JAVASCRIPT_DEBUGGER)
394 bool InspectorController::profilerEnabled() const
395 {
396     return m_profilerAgent->enabled();
397 }
398
399 void InspectorController::setProfilerEnabled(bool enable)
400 {
401     ErrorString error;
402     if (enable)
403         m_profilerAgent->enable(&error);
404     else
405         m_profilerAgent->disable(&error);
406 }
407
408 void InspectorController::resume()
409 {
410     if (m_debuggerAgent) {
411         ErrorString error;
412         m_debuggerAgent->resume(&error);
413     }
414 }
415 #endif
416
417 void InspectorController::setResourcesDataSizeLimitsFromInternals(int maximumResourcesContentSize, int maximumSingleResourceContentSize)
418 {
419     m_resourceAgent->setResourcesDataSizeLimitsFromInternals(maximumResourcesContentSize, maximumSingleResourceContentSize);
420 }
421
422 void InspectorController::didBeginFrame()
423 {
424     if (InspectorTimelineAgent* timelineAgent = m_instrumentingAgents->inspectorTimelineAgent())
425         timelineAgent->didBeginFrame();
426     if (InspectorCanvasAgent* canvasAgent = m_instrumentingAgents->inspectorCanvasAgent())
427         canvasAgent->didBeginFrame();
428 }
429
430 void InspectorController::didCancelFrame()
431 {
432     if (InspectorTimelineAgent* timelineAgent = m_instrumentingAgents->inspectorTimelineAgent())
433         timelineAgent->didCancelFrame();
434 }
435
436 void InspectorController::willComposite()
437 {
438     if (InspectorTimelineAgent* timelineAgent = m_instrumentingAgents->inspectorTimelineAgent())
439         timelineAgent->willComposite();
440 }
441
442 void InspectorController::didComposite()
443 {
444     if (InspectorTimelineAgent* timelineAgent = m_instrumentingAgents->inspectorTimelineAgent())
445         timelineAgent->didComposite();
446 }
447
448 bool InspectorController::developerExtrasEnabled() const
449 {
450     return m_page.settings().developerExtrasEnabled();
451 }
452
453 bool InspectorController::canAccessInspectedScriptState(JSC::ExecState* scriptState) const
454 {
455     JSLockHolder lock(scriptState);
456     JSDOMWindow* inspectedWindow = toJSDOMWindow(scriptState->lexicalGlobalObject());
457     if (!inspectedWindow)
458         return false;
459
460     return BindingSecurity::shouldAllowAccessToDOMWindow(scriptState, inspectedWindow->impl(), DoNotReportSecurityError);
461 }
462
463 InspectorFunctionCallHandler InspectorController::functionCallHandler() const
464 {
465     return WebCore::functionCallHandlerFromAnyThread;
466 }
467
468 InspectorEvaluateHandler InspectorController::evaluateHandler() const
469 {
470     return WebCore::evaluateHandlerFromAnyThread;
471 }
472
473 void InspectorController::willCallInjectedScriptFunction(JSC::ExecState* scriptState, const String& scriptName, int scriptLine)
474 {
475     ScriptExecutionContext* scriptExecutionContext = scriptExecutionContextFromExecState(scriptState);
476     InspectorInstrumentationCookie cookie = InspectorInstrumentation::willCallFunction(scriptExecutionContext, scriptName, scriptLine);
477     m_injectedScriptInstrumentationCookies.append(cookie);
478 }
479
480 void InspectorController::didCallInjectedScriptFunction()
481 {
482     ASSERT(!m_injectedScriptInstrumentationCookies.isEmpty());
483     InspectorInstrumentationCookie cookie = m_injectedScriptInstrumentationCookies.takeLast();
484     InspectorInstrumentation::didCallFunction(cookie);
485 }
486
487 } // namespace WebCore
488
489 #endif // ENABLE(INSPECTOR)