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