bc80bca29c9514777da04dc1cae1b751cf9ff8af
[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_frontendChannel(nullptr)
90     , m_executionStopwatch(Stopwatch::create())
91     , m_page(page)
92     , m_inspectorClient(inspectorClient)
93     , m_inspectorFrontendClient(nullptr)
94     , m_isUnderTest(false)
95     , m_isAutomaticInspection(false)
96 #if ENABLE(REMOTE_INSPECTOR)
97     , m_hasRemoteFrontend(false)
98 #endif
99 {
100     ASSERT_ARG(inspectorClient, inspectorClient);
101
102     auto inspectorAgentPtr = std::make_unique<InspectorAgent>(*this);
103     m_inspectorAgent = inspectorAgentPtr.get();
104     m_instrumentingAgents->setInspectorAgent(m_inspectorAgent);
105     m_agents.append(WTF::move(inspectorAgentPtr));
106
107     auto pageAgentPtr = std::make_unique<InspectorPageAgent>(m_instrumentingAgents.get(), &page, inspectorClient, m_overlay.get());
108     InspectorPageAgent* pageAgent = pageAgentPtr.get();
109     m_pageAgent = pageAgentPtr.get();
110     m_agents.append(WTF::move(pageAgentPtr));
111
112     auto runtimeAgentPtr = std::make_unique<PageRuntimeAgent>(m_injectedScriptManager.get(), &page, pageAgent);
113     PageRuntimeAgent* runtimeAgent = runtimeAgentPtr.get();
114     m_instrumentingAgents->setPageRuntimeAgent(runtimeAgent);
115     m_agents.append(WTF::move(runtimeAgentPtr));
116
117     auto domAgentPtr = std::make_unique<InspectorDOMAgent>(m_instrumentingAgents.get(), pageAgent, m_injectedScriptManager.get(), m_overlay.get());
118     m_domAgent = domAgentPtr.get();
119     m_agents.append(WTF::move(domAgentPtr));
120
121     m_agents.append(std::make_unique<InspectorCSSAgent>(m_instrumentingAgents.get(), m_domAgent));
122
123     auto databaseAgentPtr = std::make_unique<InspectorDatabaseAgent>(m_instrumentingAgents.get());
124     InspectorDatabaseAgent* databaseAgent = databaseAgentPtr.get();
125     m_agents.append(WTF::move(databaseAgentPtr));
126
127 #if ENABLE(INDEXED_DATABASE)
128     m_agents.append(std::make_unique<InspectorIndexedDBAgent>(m_instrumentingAgents.get(), m_injectedScriptManager.get(), pageAgent));
129 #endif
130
131 #if ENABLE(WEB_REPLAY)
132     m_agents.append(std::make_unique<InspectorReplayAgent>(m_instrumentingAgents.get(), pageAgent));
133 #endif
134
135     auto domStorageAgentPtr = std::make_unique<InspectorDOMStorageAgent>(m_instrumentingAgents.get(), m_pageAgent);
136     InspectorDOMStorageAgent* domStorageAgent = domStorageAgentPtr.get();
137     m_agents.append(WTF::move(domStorageAgentPtr));
138
139     auto timelineAgentPtr = std::make_unique<InspectorTimelineAgent>(m_instrumentingAgents.get(), pageAgent, InspectorTimelineAgent::PageInspector, inspectorClient);
140     m_timelineAgent = timelineAgentPtr.get();
141     m_agents.append(WTF::move(timelineAgentPtr));
142
143     auto resourceAgentPtr = std::make_unique<InspectorResourceAgent>(m_instrumentingAgents.get(), pageAgent, inspectorClient);
144     m_resourceAgent = resourceAgentPtr.get();
145     m_agents.append(WTF::move(resourceAgentPtr));
146
147     auto consoleAgentPtr = std::make_unique<PageConsoleAgent>(m_injectedScriptManager.get(), m_domAgent);
148     WebConsoleAgent* consoleAgent = consoleAgentPtr.get();
149     m_instrumentingAgents->setWebConsoleAgent(consoleAgentPtr.get());
150     m_agents.append(WTF::move(consoleAgentPtr));
151
152     auto debuggerAgentPtr = std::make_unique<PageDebuggerAgent>(m_injectedScriptManager.get(), m_instrumentingAgents.get(), pageAgent, m_overlay.get());
153     m_debuggerAgent = debuggerAgentPtr.get();
154     m_agents.append(WTF::move(debuggerAgentPtr));
155
156     auto domDebuggerAgentPtr = std::make_unique<InspectorDOMDebuggerAgent>(m_instrumentingAgents.get(), m_domAgent, m_debuggerAgent);
157     m_domDebuggerAgent = domDebuggerAgentPtr.get();
158     m_agents.append(WTF::move(domDebuggerAgentPtr));
159
160     m_agents.append(std::make_unique<InspectorApplicationCacheAgent>(m_instrumentingAgents.get(), pageAgent));
161     m_agents.append(std::make_unique<InspectorWorkerAgent>(m_instrumentingAgents.get()));
162     m_agents.append(std::make_unique<InspectorLayerTreeAgent>(m_instrumentingAgents.get()));
163
164     ASSERT(m_injectedScriptManager->commandLineAPIHost());
165     if (CommandLineAPIHost* commandLineAPIHost = m_injectedScriptManager->commandLineAPIHost()) {
166         commandLineAPIHost->init(m_inspectorAgent
167             , consoleAgent
168             , m_domAgent
169             , domStorageAgent
170             , databaseAgent
171         );
172     }
173
174     runtimeAgent->setScriptDebugServer(&m_debuggerAgent->scriptDebugServer());
175     m_timelineAgent->setPageScriptDebugServer(&m_debuggerAgent->scriptDebugServer());
176 }
177
178 InspectorController::~InspectorController()
179 {
180     m_instrumentingAgents->reset();
181     m_agents.discardAgents();
182     ASSERT(!m_inspectorClient);
183 }
184
185 void InspectorController::inspectedPageDestroyed()
186 {
187     disconnectFrontend(DisconnectReason::InspectedTargetDestroyed);
188     m_injectedScriptManager->disconnect();
189     m_inspectorClient->inspectorDestroyed();
190     m_inspectorClient = nullptr;
191 }
192
193 void InspectorController::setInspectorFrontendClient(InspectorFrontendClient* inspectorFrontendClient)
194 {
195     m_inspectorFrontendClient = inspectorFrontendClient;
196 }
197
198 bool InspectorController::hasLocalFrontend() const
199 {
200 #if ENABLE(REMOTE_INSPECTOR)
201     return hasFrontend() && !m_hasRemoteFrontend;
202 #else
203     return hasFrontend();
204 #endif
205 }
206
207 bool InspectorController::hasRemoteFrontend() const
208 {
209 #if ENABLE(REMOTE_INSPECTOR)
210     return m_hasRemoteFrontend;
211 #else
212     return false;
213 #endif
214 }
215
216 bool InspectorController::hasInspectorFrontendClient() const
217 {
218     return m_inspectorFrontendClient;
219 }
220
221 void InspectorController::didClearWindowObjectInWorld(Frame& frame, DOMWrapperWorld& world)
222 {
223     if (&world != &mainThreadNormalWorld())
224         return;
225
226     if (frame.isMainFrame())
227         m_injectedScriptManager->discardInjectedScripts();
228
229     // If the page is supposed to serve as InspectorFrontend notify inspector frontend
230     // client that it's cleared so that the client can expose inspector bindings.
231     if (m_inspectorFrontendClient && frame.isMainFrame())
232         m_inspectorFrontendClient->windowObjectCleared();
233 }
234
235 void InspectorController::connectFrontend(Inspector::FrontendChannel* frontendChannel, bool isAutomaticInspection)
236 {
237     ASSERT(frontendChannel);
238     ASSERT(m_inspectorClient);
239     ASSERT(!m_frontendChannel);
240     ASSERT(!m_backendDispatcher);
241
242     m_isAutomaticInspection = isAutomaticInspection;
243
244     m_frontendChannel = frontendChannel;
245     m_backendDispatcher = BackendDispatcher::create(frontendChannel);
246
247     m_agents.didCreateFrontendAndBackend(frontendChannel, m_backendDispatcher.get());
248
249     InspectorInstrumentation::registerInstrumentingAgents(*m_instrumentingAgents);
250     InspectorInstrumentation::frontendCreated();
251
252 #if ENABLE(REMOTE_INSPECTOR)
253     if (!m_hasRemoteFrontend)
254         m_page.remoteInspectorInformationDidChange();
255 #endif
256 }
257
258 void InspectorController::disconnectFrontend(DisconnectReason reason)
259 {
260     if (!m_frontendChannel)
261         return;
262
263     m_agents.willDestroyFrontendAndBackend(reason);
264
265     m_backendDispatcher->clearFrontend();
266     m_backendDispatcher = nullptr;
267     m_frontendChannel = nullptr;
268
269     m_isAutomaticInspection = false;
270
271     // Release overlay page resources.
272     m_overlay->freePage();
273     InspectorInstrumentation::frontendDeleted();
274     InspectorInstrumentation::unregisterInstrumentingAgents(*m_instrumentingAgents);
275
276 #if ENABLE(REMOTE_INSPECTOR)
277     if (!m_hasRemoteFrontend)
278         m_page.remoteInspectorInformationDidChange();
279 #endif
280 }
281
282 void InspectorController::show()
283 {
284     ASSERT(!hasRemoteFrontend());
285
286     if (!enabled())
287         return;
288
289     if (m_frontendChannel)
290         m_inspectorClient->bringFrontendToFront();
291     else {
292         if (Inspector::FrontendChannel* frontendChannel = m_inspectorClient->openInspectorFrontend(this)) {
293             bool isAutomaticInspection = false;
294             connectFrontend(frontendChannel, isAutomaticInspection);
295         }
296     }
297 }
298
299 void InspectorController::close()
300 {
301     if (!m_frontendChannel)
302         return;
303     disconnectFrontend(DisconnectReason::InspectorDestroyed);
304     m_inspectorClient->closeInspectorFrontend();
305 }
306
307 void InspectorController::setProcessId(long processId)
308 {
309     IdentifiersFactory::setProcessId(processId);
310 }
311
312 void InspectorController::evaluateForTestInFrontend(const String& script)
313 {
314     m_inspectorAgent->evaluateForTestInFrontend(script);
315 }
316
317 void InspectorController::drawHighlight(GraphicsContext& context) const
318 {
319     m_overlay->paint(context);
320 }
321
322 void InspectorController::getHighlight(Highlight& highlight, InspectorOverlay::CoordinateSystem coordinateSystem) const
323 {
324     m_overlay->getHighlight(highlight, coordinateSystem);
325 }
326
327 Ref<Inspector::Protocol::Array<Inspector::Protocol::OverlayTypes::NodeHighlightData>> InspectorController::buildObjectForHighlightedNodes() const
328 {
329     return m_overlay->buildObjectForHighlightedNodes();
330 }
331
332 void InspectorController::inspect(Node* node)
333 {
334     if (!enabled())
335         return;
336
337     if (!hasRemoteFrontend())
338         show();
339
340     m_domAgent->inspect(node);
341 }
342
343 bool InspectorController::enabled() const
344 {
345     return developerExtrasEnabled();
346 }
347
348 Page& InspectorController::inspectedPage() const
349 {
350     return m_page;
351 }
352
353 void InspectorController::dispatchMessageFromFrontend(const String& message)
354 {
355     if (m_backendDispatcher)
356         m_backendDispatcher->dispatch(message);
357 }
358
359 void InspectorController::hideHighlight()
360 {
361     ErrorString unused;
362     m_domAgent->hideHighlight(unused);
363 }
364
365 Node* InspectorController::highlightedNode() const
366 {
367     return m_overlay->highlightedNode();
368 }
369
370 void InspectorController::setIndicating(bool indicating)
371 {
372 #if !PLATFORM(IOS)
373     m_overlay->setIndicating(indicating);
374 #else
375     if (indicating)
376         m_inspectorClient->showInspectorIndication();
377     else
378         m_inspectorClient->hideInspectorIndication();
379 #endif
380 }
381
382 bool InspectorController::profilerEnabled() const
383 {
384     return m_instrumentingAgents->persistentInspectorTimelineAgent();
385 }
386
387 void InspectorController::setProfilerEnabled(bool enable)
388 {
389     ErrorString unused;
390
391     if (enable) {
392         m_instrumentingAgents->setPersistentInspectorTimelineAgent(m_timelineAgent);
393         m_timelineAgent->start(unused);
394     } else {
395         m_instrumentingAgents->setPersistentInspectorTimelineAgent(nullptr);
396         m_timelineAgent->stop(unused);
397     }
398 }
399
400 void InspectorController::resume()
401 {
402     if (m_debuggerAgent) {
403         ErrorString unused;
404         m_debuggerAgent->resume(unused);
405     }
406 }
407
408 bool InspectorController::developerExtrasEnabled() const
409 {
410     return m_page.settings().developerExtrasEnabled();
411 }
412
413 bool InspectorController::canAccessInspectedScriptState(JSC::ExecState* scriptState) const
414 {
415     JSLockHolder lock(scriptState);
416     JSDOMWindow* inspectedWindow = toJSDOMWindow(scriptState->lexicalGlobalObject());
417     if (!inspectedWindow)
418         return false;
419
420     return BindingSecurity::shouldAllowAccessToDOMWindow(scriptState, inspectedWindow->impl(), DoNotReportSecurityError);
421 }
422
423 InspectorFunctionCallHandler InspectorController::functionCallHandler() const
424 {
425     return WebCore::functionCallHandlerFromAnyThread;
426 }
427
428 InspectorEvaluateHandler InspectorController::evaluateHandler() const
429 {
430     return WebCore::evaluateHandlerFromAnyThread;
431 }
432
433 void InspectorController::willCallInjectedScriptFunction(JSC::ExecState* scriptState, const String&, int)
434 {
435     LegacyProfiler::profiler()->suspendProfiling(scriptState);
436 }
437
438 void InspectorController::didCallInjectedScriptFunction(JSC::ExecState* scriptState)
439 {
440     LegacyProfiler::profiler()->unsuspendProfiling(scriptState);
441 }
442
443 void InspectorController::frontendInitialized()
444 {
445 #if ENABLE(REMOTE_INSPECTOR)
446     if (m_isAutomaticInspection)
447         m_page.inspectorDebuggable().unpauseForInitializedInspector();
448 #endif
449 }
450
451 Ref<Stopwatch> InspectorController::executionStopwatch()
452 {
453     return m_executionStopwatch.copyRef();
454 }
455
456 void InspectorController::didComposite(Frame& frame)
457 {
458     InspectorInstrumentation::didComposite(frame);
459 }
460
461 } // namespace WebCore