277f16b6f475057b174637b367d3ca5a05a83cba
[WebKit-https.git] / Source / WebCore / inspector / InspectorController.cpp
1 /*
2  * Copyright (C) 2011 Google Inc. All rights reserved.
3  * Copyright (C) 2014 Apple Inc. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  *     * Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  *     * Redistributions in binary form must reproduce the above
12  * copyright notice, this list of conditions and the following disclaimer
13  * in the documentation and/or other materials provided with the
14  * distribution.
15  *     * Neither the name of Google Inc. nor the names of its
16  * contributors may be used to endorse or promote products derived from
17  * this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31
32 #include "config.h"
33 #include "InspectorController.h"
34
35 #include "CommandLineAPIHost.h"
36 #include "DOMWrapperWorld.h"
37 #include "GraphicsContext.h"
38 #include "InspectorApplicationCacheAgent.h"
39 #include "InspectorCSSAgent.h"
40 #include "InspectorClient.h"
41 #include "InspectorDOMAgent.h"
42 #include "InspectorDOMDebuggerAgent.h"
43 #include "InspectorDOMStorageAgent.h"
44 #include "InspectorDatabaseAgent.h"
45 #include "InspectorFrontendClient.h"
46 #include "InspectorIndexedDBAgent.h"
47 #include "InspectorInstrumentation.h"
48 #include "InspectorLayerTreeAgent.h"
49 #include "InspectorPageAgent.h"
50 #include "InspectorReplayAgent.h"
51 #include "InspectorResourceAgent.h"
52 #include "InspectorTimelineAgent.h"
53 #include "InspectorWorkerAgent.h"
54 #include "InstrumentingAgents.h"
55 #include "JSDOMWindow.h"
56 #include "JSDOMWindowCustom.h"
57 #include "JSMainThreadExecState.h"
58 #include "MainFrame.h"
59 #include "Page.h"
60 #include "PageConsoleAgent.h"
61 #include "PageDebuggerAgent.h"
62 #include "PageRuntimeAgent.h"
63 #include "PageScriptDebugServer.h"
64 #include "Settings.h"
65 #include "WebInjectedScriptHost.h"
66 #include "WebInjectedScriptManager.h"
67 #include <inspector/IdentifiersFactory.h>
68 #include <inspector/InspectorBackendDispatcher.h>
69 #include <inspector/InspectorBackendDispatchers.h>
70 #include <inspector/InspectorFrontendDispatchers.h>
71 #include <inspector/agents/InspectorAgent.h>
72 #include <profiler/LegacyProfiler.h>
73 #include <runtime/JSLock.h>
74 #include <wtf/Stopwatch.h>
75
76 #if ENABLE(REMOTE_INSPECTOR)
77 #include "PageDebuggable.h"
78 #endif
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<WebInjectedScriptManager>(*this, WebInjectedScriptHost::create()))
88     , m_overlay(std::make_unique<InspectorOverlay>(page, inspectorClient))
89     , m_executionStopwatch(Stopwatch::create())
90     , m_page(page)
91     , m_inspectorClient(inspectorClient)
92 {
93     ASSERT_ARG(inspectorClient, inspectorClient);
94
95     auto inspectorAgentPtr = std::make_unique<InspectorAgent>(*this);
96     m_inspectorAgent = inspectorAgentPtr.get();
97     m_instrumentingAgents->setInspectorAgent(m_inspectorAgent);
98     m_agents.append(WTF::move(inspectorAgentPtr));
99
100     auto pageAgentPtr = std::make_unique<InspectorPageAgent>(m_instrumentingAgents.get(), &page, inspectorClient, m_overlay.get());
101     InspectorPageAgent* pageAgent = pageAgentPtr.get();
102     m_pageAgent = pageAgentPtr.get();
103     m_agents.append(WTF::move(pageAgentPtr));
104
105     auto runtimeAgentPtr = std::make_unique<PageRuntimeAgent>(*m_injectedScriptManager, &page, pageAgent);
106     PageRuntimeAgent* runtimeAgent = runtimeAgentPtr.get();
107     m_instrumentingAgents->setPageRuntimeAgent(runtimeAgent);
108     m_agents.append(WTF::move(runtimeAgentPtr));
109
110     auto domAgentPtr = std::make_unique<InspectorDOMAgent>(m_instrumentingAgents.get(), pageAgent, *m_injectedScriptManager, m_overlay.get());
111     m_domAgent = domAgentPtr.get();
112     m_agents.append(WTF::move(domAgentPtr));
113
114     m_agents.append(std::make_unique<InspectorCSSAgent>(m_instrumentingAgents.get(), m_domAgent));
115
116     auto databaseAgentPtr = std::make_unique<InspectorDatabaseAgent>(m_instrumentingAgents.get());
117     InspectorDatabaseAgent* databaseAgent = databaseAgentPtr.get();
118     m_agents.append(WTF::move(databaseAgentPtr));
119
120 #if ENABLE(INDEXED_DATABASE)
121     m_agents.append(std::make_unique<InspectorIndexedDBAgent>(m_instrumentingAgents.get(), *m_injectedScriptManager, pageAgent));
122 #endif
123
124 #if ENABLE(WEB_REPLAY)
125     m_agents.append(std::make_unique<InspectorReplayAgent>(m_instrumentingAgents.get(), pageAgent));
126 #endif
127
128     auto domStorageAgentPtr = std::make_unique<InspectorDOMStorageAgent>(m_instrumentingAgents.get(), m_pageAgent);
129     InspectorDOMStorageAgent* domStorageAgent = domStorageAgentPtr.get();
130     m_agents.append(WTF::move(domStorageAgentPtr));
131
132     auto timelineAgentPtr = std::make_unique<InspectorTimelineAgent>(m_instrumentingAgents.get(), pageAgent, InspectorTimelineAgent::PageInspector, inspectorClient);
133     m_timelineAgent = timelineAgentPtr.get();
134     m_agents.append(WTF::move(timelineAgentPtr));
135
136     auto resourceAgentPtr = std::make_unique<InspectorResourceAgent>(m_instrumentingAgents.get(), pageAgent, inspectorClient);
137     m_resourceAgent = resourceAgentPtr.get();
138     m_agents.append(WTF::move(resourceAgentPtr));
139
140     auto consoleAgentPtr = std::make_unique<PageConsoleAgent>(*m_injectedScriptManager, m_domAgent);
141     WebConsoleAgent* consoleAgent = consoleAgentPtr.get();
142     m_instrumentingAgents->setWebConsoleAgent(consoleAgentPtr.get());
143     m_agents.append(WTF::move(consoleAgentPtr));
144
145     auto debuggerAgentPtr = std::make_unique<PageDebuggerAgent>(*m_injectedScriptManager, m_instrumentingAgents.get(), pageAgent, m_overlay.get());
146     m_debuggerAgent = debuggerAgentPtr.get();
147     m_agents.append(WTF::move(debuggerAgentPtr));
148
149     auto domDebuggerAgentPtr = std::make_unique<InspectorDOMDebuggerAgent>(m_instrumentingAgents.get(), m_domAgent, m_debuggerAgent);
150     m_domDebuggerAgent = domDebuggerAgentPtr.get();
151     m_agents.append(WTF::move(domDebuggerAgentPtr));
152
153     m_agents.append(std::make_unique<InspectorApplicationCacheAgent>(m_instrumentingAgents.get(), pageAgent));
154     m_agents.append(std::make_unique<InspectorWorkerAgent>(m_instrumentingAgents.get()));
155     m_agents.append(std::make_unique<InspectorLayerTreeAgent>(m_instrumentingAgents.get()));
156
157     ASSERT(m_injectedScriptManager->commandLineAPIHost());
158     if (CommandLineAPIHost* commandLineAPIHost = m_injectedScriptManager->commandLineAPIHost()) {
159         commandLineAPIHost->init(m_inspectorAgent
160             , consoleAgent
161             , m_domAgent
162             , domStorageAgent
163             , databaseAgent
164         );
165     }
166
167     runtimeAgent->setScriptDebugServer(&m_debuggerAgent->scriptDebugServer());
168     m_timelineAgent->setPageScriptDebugServer(&m_debuggerAgent->scriptDebugServer());
169 }
170
171 InspectorController::~InspectorController()
172 {
173     m_instrumentingAgents->reset();
174     m_agents.discardAgents();
175     ASSERT(!m_inspectorClient);
176 }
177
178 void InspectorController::inspectedPageDestroyed()
179 {
180     disconnectFrontend(DisconnectReason::InspectedTargetDestroyed);
181     m_injectedScriptManager->disconnect();
182     m_inspectorClient->inspectorDestroyed();
183     m_inspectorClient = nullptr;
184 }
185
186 void InspectorController::setInspectorFrontendClient(InspectorFrontendClient* inspectorFrontendClient)
187 {
188     m_inspectorFrontendClient = inspectorFrontendClient;
189 }
190
191 bool InspectorController::hasLocalFrontend() const
192 {
193     return m_frontendChannel && m_frontendChannel->connectionType() == FrontendChannel::ConnectionType::Local;
194 }
195
196 bool InspectorController::hasRemoteFrontend() const
197 {
198     return m_frontendChannel && m_frontendChannel->connectionType() == FrontendChannel::ConnectionType::Remote;
199 }
200
201 bool InspectorController::hasInspectorFrontendClient() const
202 {
203     return m_inspectorFrontendClient;
204 }
205
206 void InspectorController::didClearWindowObjectInWorld(Frame& frame, DOMWrapperWorld& world)
207 {
208     if (&world != &mainThreadNormalWorld())
209         return;
210
211     if (frame.isMainFrame())
212         m_injectedScriptManager->discardInjectedScripts();
213
214     // If the page is supposed to serve as InspectorFrontend notify inspector frontend
215     // client that it's cleared so that the client can expose inspector bindings.
216     if (m_inspectorFrontendClient && frame.isMainFrame())
217         m_inspectorFrontendClient->windowObjectCleared();
218 }
219
220 void InspectorController::connectFrontend(Inspector::FrontendChannel* frontendChannel, bool isAutomaticInspection)
221 {
222     ASSERT(frontendChannel);
223     ASSERT(m_inspectorClient);
224     ASSERT(!m_frontendChannel);
225     ASSERT(!m_backendDispatcher);
226
227     m_isAutomaticInspection = isAutomaticInspection;
228
229     m_frontendChannel = frontendChannel;
230     m_backendDispatcher = BackendDispatcher::create(frontendChannel);
231
232     m_agents.didCreateFrontendAndBackend(frontendChannel, m_backendDispatcher.get());
233
234     InspectorInstrumentation::registerInstrumentingAgents(m_instrumentingAgents.get());
235     InspectorInstrumentation::frontendCreated();
236
237 #if ENABLE(REMOTE_INSPECTOR)
238     if (!hasRemoteFrontend())
239         m_page.remoteInspectorInformationDidChange();
240 #endif
241 }
242
243 void InspectorController::disconnectFrontend(DisconnectReason reason)
244 {
245     if (!m_frontendChannel)
246         return;
247
248 #if ENABLE(REMOTE_INSPECTOR)
249     if (!hasRemoteFrontend())
250         m_page.remoteInspectorInformationDidChange();
251 #endif
252
253     m_agents.willDestroyFrontendAndBackend(reason);
254
255     m_backendDispatcher->clearFrontend();
256     m_backendDispatcher = nullptr;
257     m_frontendChannel = nullptr;
258
259     m_isAutomaticInspection = false;
260
261     // Release overlay page resources.
262     m_overlay->freePage();
263     InspectorInstrumentation::frontendDeleted();
264     InspectorInstrumentation::unregisterInstrumentingAgents(m_instrumentingAgents.get());
265 }
266
267 void InspectorController::show()
268 {
269     ASSERT(!hasRemoteFrontend());
270
271     if (!enabled())
272         return;
273
274     if (m_frontendChannel)
275         m_inspectorClient->bringFrontendToFront();
276     else {
277         if (Inspector::FrontendChannel* frontendChannel = m_inspectorClient->openInspectorFrontend(this)) {
278             bool isAutomaticInspection = false;
279             connectFrontend(frontendChannel, isAutomaticInspection);
280         }
281     }
282 }
283
284 void InspectorController::close()
285 {
286     if (!m_frontendChannel)
287         return;
288     disconnectFrontend(DisconnectReason::InspectorDestroyed);
289     m_inspectorClient->closeInspectorFrontend();
290 }
291
292 void InspectorController::setProcessId(long processId)
293 {
294     IdentifiersFactory::setProcessId(processId);
295 }
296
297 void InspectorController::evaluateForTestInFrontend(const String& script)
298 {
299     m_inspectorAgent->evaluateForTestInFrontend(script);
300 }
301
302 void InspectorController::drawHighlight(GraphicsContext& context) const
303 {
304     m_overlay->paint(context);
305 }
306
307 void InspectorController::getHighlight(Highlight& highlight, InspectorOverlay::CoordinateSystem coordinateSystem) const
308 {
309     m_overlay->getHighlight(highlight, coordinateSystem);
310 }
311
312 Ref<Inspector::Protocol::Array<Inspector::Protocol::OverlayTypes::NodeHighlightData>> InspectorController::buildObjectForHighlightedNodes() const
313 {
314     return m_overlay->buildObjectForHighlightedNodes();
315 }
316
317 void InspectorController::inspect(Node* node)
318 {
319     if (!enabled())
320         return;
321
322     if (!hasRemoteFrontend())
323         show();
324
325     m_domAgent->inspect(node);
326 }
327
328 bool InspectorController::enabled() const
329 {
330     return developerExtrasEnabled();
331 }
332
333 Page& InspectorController::inspectedPage() const
334 {
335     return m_page;
336 }
337
338 void InspectorController::dispatchMessageFromFrontend(const String& message)
339 {
340     if (m_backendDispatcher)
341         m_backendDispatcher->dispatch(message);
342 }
343
344 void InspectorController::hideHighlight()
345 {
346     ErrorString unused;
347     m_domAgent->hideHighlight(unused);
348 }
349
350 Node* InspectorController::highlightedNode() const
351 {
352     return m_overlay->highlightedNode();
353 }
354
355 void InspectorController::setIndicating(bool indicating)
356 {
357 #if !PLATFORM(IOS)
358     m_overlay->setIndicating(indicating);
359 #else
360     if (indicating)
361         m_inspectorClient->showInspectorIndication();
362     else
363         m_inspectorClient->hideInspectorIndication();
364 #endif
365 }
366
367 bool InspectorController::profilerEnabled() const
368 {
369     return m_instrumentingAgents->persistentInspectorTimelineAgent();
370 }
371
372 void InspectorController::setProfilerEnabled(bool enable)
373 {
374     ErrorString unused;
375
376     if (enable) {
377         m_instrumentingAgents->setPersistentInspectorTimelineAgent(m_timelineAgent);
378         m_timelineAgent->start(unused);
379     } else {
380         m_instrumentingAgents->setPersistentInspectorTimelineAgent(nullptr);
381         m_timelineAgent->stop(unused);
382     }
383 }
384
385 void InspectorController::resume()
386 {
387     if (m_debuggerAgent) {
388         ErrorString unused;
389         m_debuggerAgent->resume(unused);
390     }
391 }
392
393 bool InspectorController::developerExtrasEnabled() const
394 {
395     return m_page.settings().developerExtrasEnabled();
396 }
397
398 bool InspectorController::canAccessInspectedScriptState(JSC::ExecState* scriptState) const
399 {
400     JSLockHolder lock(scriptState);
401     JSDOMWindow* inspectedWindow = toJSDOMWindow(scriptState->lexicalGlobalObject());
402     if (!inspectedWindow)
403         return false;
404
405     return BindingSecurity::shouldAllowAccessToDOMWindow(scriptState, inspectedWindow->impl(), DoNotReportSecurityError);
406 }
407
408 InspectorFunctionCallHandler InspectorController::functionCallHandler() const
409 {
410     return WebCore::functionCallHandlerFromAnyThread;
411 }
412
413 InspectorEvaluateHandler InspectorController::evaluateHandler() const
414 {
415     return WebCore::evaluateHandlerFromAnyThread;
416 }
417
418 void InspectorController::willCallInjectedScriptFunction(JSC::ExecState* scriptState, const String&, int)
419 {
420     LegacyProfiler::profiler()->suspendProfiling(scriptState);
421 }
422
423 void InspectorController::didCallInjectedScriptFunction(JSC::ExecState* scriptState)
424 {
425     LegacyProfiler::profiler()->unsuspendProfiling(scriptState);
426 }
427
428 void InspectorController::frontendInitialized()
429 {
430 #if ENABLE(REMOTE_INSPECTOR)
431     if (m_isAutomaticInspection)
432         m_page.inspectorDebuggable().unpauseForInitializedInspector();
433 #endif
434 }
435
436 Ref<Stopwatch> InspectorController::executionStopwatch()
437 {
438     return m_executionStopwatch.copyRef();
439 }
440
441 void InspectorController::didComposite(Frame& frame)
442 {
443     InspectorInstrumentation::didComposite(frame);
444 }
445
446 } // namespace WebCore