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