5b6eb2535bebd084b537e222f164ca699bbe0cb1
[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 #if ENABLE(INSPECTOR)
36
37 #include "CommandLineAPIHost.h"
38 #include "DOMWrapperWorld.h"
39 #include "GraphicsContext.h"
40 #include "InspectorApplicationCacheAgent.h"
41 #include "InspectorCSSAgent.h"
42 #include "InspectorClient.h"
43 #include "InspectorDOMAgent.h"
44 #include "InspectorDOMDebuggerAgent.h"
45 #include "InspectorDOMStorageAgent.h"
46 #include "InspectorDatabaseAgent.h"
47 #include "InspectorFrontendClient.h"
48 #include "InspectorIndexedDBAgent.h"
49 #include "InspectorInstrumentation.h"
50 #include "InspectorLayerTreeAgent.h"
51 #include "InspectorOverlay.h"
52 #include "InspectorPageAgent.h"
53 #include "InspectorReplayAgent.h"
54 #include "InspectorResourceAgent.h"
55 #include "InspectorTimelineAgent.h"
56 #include "InspectorWebBackendDispatchers.h"
57 #include "InspectorWebFrontendDispatchers.h"
58 #include "InspectorWorkerAgent.h"
59 #include "InstrumentingAgents.h"
60 #include "JSDOMWindow.h"
61 #include "JSDOMWindowCustom.h"
62 #include "JSMainThreadExecState.h"
63 #include "MainFrame.h"
64 #include "Page.h"
65 #include "PageConsoleAgent.h"
66 #include "PageDebuggerAgent.h"
67 #include "PageRuntimeAgent.h"
68 #include "PageScriptDebugServer.h"
69 #include "Settings.h"
70 #include "WebInjectedScriptHost.h"
71 #include "WebInjectedScriptManager.h"
72 #include <inspector/IdentifiersFactory.h>
73 #include <inspector/InspectorBackendDispatcher.h>
74 #include <inspector/agents/InspectorAgent.h>
75 #include <runtime/JSLock.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_overlay(std::make_unique<InspectorOverlay>(page, inspectorClient))
90     , m_inspectorFrontendChannel(nullptr)
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 #if ENABLE(SQL_DATABASE)
124     auto databaseAgentPtr = std::make_unique<InspectorDatabaseAgent>(m_instrumentingAgents.get());
125     InspectorDatabaseAgent* databaseAgent = databaseAgentPtr.get();
126     m_agents.append(WTF::move(databaseAgentPtr));
127 #endif
128
129 #if ENABLE(INDEXED_DATABASE)
130     m_agents.append(std::make_unique<InspectorIndexedDBAgent>(m_instrumentingAgents.get(), m_injectedScriptManager.get(), pageAgent));
131 #endif
132
133 #if ENABLE(WEB_REPLAY)
134     m_agents.append(std::make_unique<InspectorReplayAgent>(m_instrumentingAgents.get(), pageAgent));
135 #endif
136
137     auto domStorageAgentPtr = std::make_unique<InspectorDOMStorageAgent>(m_instrumentingAgents.get(), m_pageAgent);
138     InspectorDOMStorageAgent* domStorageAgent = domStorageAgentPtr.get();
139     m_agents.append(WTF::move(domStorageAgentPtr));
140
141     auto timelineAgentPtr = std::make_unique<InspectorTimelineAgent>(m_instrumentingAgents.get(), pageAgent, InspectorTimelineAgent::PageInspector, inspectorClient);
142     m_timelineAgent = timelineAgentPtr.get();
143     m_agents.append(WTF::move(timelineAgentPtr));
144
145     auto resourceAgentPtr = std::make_unique<InspectorResourceAgent>(m_instrumentingAgents.get(), pageAgent, inspectorClient);
146     m_resourceAgent = resourceAgentPtr.get();
147     m_agents.append(WTF::move(resourceAgentPtr));
148
149     auto consoleAgentPtr = std::make_unique<PageConsoleAgent>(m_injectedScriptManager.get(), m_domAgent);
150     WebConsoleAgent* consoleAgent = consoleAgentPtr.get();
151     m_instrumentingAgents->setWebConsoleAgent(consoleAgentPtr.get());
152     m_agents.append(WTF::move(consoleAgentPtr));
153
154     auto debuggerAgentPtr = std::make_unique<PageDebuggerAgent>(m_injectedScriptManager.get(), m_instrumentingAgents.get(), pageAgent, m_overlay.get());
155     m_debuggerAgent = debuggerAgentPtr.get();
156     m_agents.append(WTF::move(debuggerAgentPtr));
157
158     auto domDebuggerAgentPtr = std::make_unique<InspectorDOMDebuggerAgent>(m_instrumentingAgents.get(), m_domAgent, m_debuggerAgent);
159     m_domDebuggerAgent = domDebuggerAgentPtr.get();
160     m_agents.append(WTF::move(domDebuggerAgentPtr));
161
162     m_agents.append(std::make_unique<InspectorApplicationCacheAgent>(m_instrumentingAgents.get(), pageAgent));
163     m_agents.append(std::make_unique<InspectorWorkerAgent>(m_instrumentingAgents.get()));
164     m_agents.append(std::make_unique<InspectorLayerTreeAgent>(m_instrumentingAgents.get()));
165
166     ASSERT(m_injectedScriptManager->commandLineAPIHost());
167     if (CommandLineAPIHost* commandLineAPIHost = m_injectedScriptManager->commandLineAPIHost()) {
168         commandLineAPIHost->init(m_inspectorAgent
169             , consoleAgent
170             , m_domAgent
171             , domStorageAgent
172 #if ENABLE(SQL_DATABASE)
173             , databaseAgent
174 #endif
175         );
176     }
177
178     runtimeAgent->setScriptDebugServer(&m_debuggerAgent->scriptDebugServer());
179     m_timelineAgent->setPageScriptDebugServer(&m_debuggerAgent->scriptDebugServer());
180 }
181
182 InspectorController::~InspectorController()
183 {
184     m_instrumentingAgents->reset();
185     m_agents.discardAgents();
186     ASSERT(!m_inspectorClient);
187 }
188
189 void InspectorController::inspectedPageDestroyed()
190 {
191     disconnectFrontend(InspectorDisconnectReason::InspectedTargetDestroyed);
192     m_injectedScriptManager->disconnect();
193     m_inspectorClient->inspectorDestroyed();
194     m_inspectorClient = nullptr;
195 }
196
197 void InspectorController::setInspectorFrontendClient(InspectorFrontendClient* inspectorFrontendClient)
198 {
199     m_inspectorFrontendClient = inspectorFrontendClient;
200 }
201
202 bool InspectorController::hasLocalFrontend() const
203 {
204 #if ENABLE(REMOTE_INSPECTOR)
205     return hasFrontend() && !m_hasRemoteFrontend;
206 #else
207     return hasFrontend();
208 #endif
209 }
210
211 bool InspectorController::hasRemoteFrontend() const
212 {
213 #if ENABLE(REMOTE_INSPECTOR)
214     return m_hasRemoteFrontend;
215 #else
216     return false;
217 #endif
218 }
219
220 bool InspectorController::hasInspectorFrontendClient() const
221 {
222     return m_inspectorFrontendClient;
223 }
224
225 void InspectorController::didClearWindowObjectInWorld(Frame* frame, DOMWrapperWorld& world)
226 {
227     if (&world != &mainThreadNormalWorld())
228         return;
229
230     if (frame->isMainFrame())
231         m_injectedScriptManager->discardInjectedScripts();
232
233     // If the page is supposed to serve as InspectorFrontend notify inspector frontend
234     // client that it's cleared so that the client can expose inspector bindings.
235     if (m_inspectorFrontendClient && frame->isMainFrame())
236         m_inspectorFrontendClient->windowObjectCleared();
237 }
238
239 void InspectorController::connectFrontend(InspectorFrontendChannel* frontendChannel, bool isAutomaticInspection)
240 {
241     ASSERT(frontendChannel);
242     ASSERT(m_inspectorClient);
243     ASSERT(!m_inspectorFrontendChannel);
244     ASSERT(!m_inspectorBackendDispatcher);
245
246     m_isAutomaticInspection = isAutomaticInspection;
247
248     m_inspectorFrontendChannel = frontendChannel;
249     m_inspectorBackendDispatcher = InspectorBackendDispatcher::create(frontendChannel);
250
251     m_agents.didCreateFrontendAndBackend(frontendChannel, m_inspectorBackendDispatcher.get());
252
253     InspectorInstrumentation::registerInstrumentingAgents(m_instrumentingAgents.get());
254     InspectorInstrumentation::frontendCreated();
255
256 #if ENABLE(REMOTE_INSPECTOR)
257     if (!m_hasRemoteFrontend)
258         m_page.remoteInspectorInformationDidChange();
259 #endif
260 }
261
262 void InspectorController::disconnectFrontend(InspectorDisconnectReason reason)
263 {
264     if (!m_inspectorFrontendChannel)
265         return;
266
267     m_agents.willDestroyFrontendAndBackend(reason);
268
269     m_inspectorBackendDispatcher->clearFrontend();
270     m_inspectorBackendDispatcher.clear();
271     m_inspectorFrontendChannel = nullptr;
272
273     m_isAutomaticInspection = false;
274
275     // Release overlay page resources.
276     m_overlay->freePage();
277     InspectorInstrumentation::frontendDeleted();
278     InspectorInstrumentation::unregisterInstrumentingAgents(m_instrumentingAgents.get());
279
280 #if ENABLE(REMOTE_INSPECTOR)
281     if (!m_hasRemoteFrontend)
282         m_page.remoteInspectorInformationDidChange();
283 #endif
284 }
285
286 void InspectorController::show()
287 {
288     ASSERT(!hasRemoteFrontend());
289
290     if (!enabled())
291         return;
292
293     if (m_inspectorFrontendChannel)
294         m_inspectorClient->bringFrontendToFront();
295     else {
296         if (InspectorFrontendChannel* frontendChannel = m_inspectorClient->openInspectorFrontend(this)) {
297             bool isAutomaticInspection = false;
298             connectFrontend(frontendChannel, isAutomaticInspection);
299         }
300     }
301 }
302
303 void InspectorController::close()
304 {
305     if (!m_inspectorFrontendChannel)
306         return;
307     disconnectFrontend(InspectorDisconnectReason::InspectorDestroyed);
308     m_inspectorClient->closeInspectorFrontend();
309 }
310
311 void InspectorController::setProcessId(long processId)
312 {
313     IdentifiersFactory::setProcessId(processId);
314 }
315
316 void InspectorController::evaluateForTestInFrontend(const String& script)
317 {
318     m_inspectorAgent->evaluateForTestInFrontend(script);
319 }
320
321 void InspectorController::drawHighlight(GraphicsContext& context) const
322 {
323     m_overlay->paint(context);
324 }
325
326 void InspectorController::getHighlight(Highlight* highlight, InspectorOverlay::CoordinateSystem coordinateSystem) const
327 {
328     m_overlay->getHighlight(highlight, coordinateSystem);
329 }
330
331 PassRefPtr<InspectorObject> InspectorController::buildObjectForHighlightedNode() const
332 {
333     return m_overlay->buildObjectForHighlightedNode();
334 }
335
336 void InspectorController::inspect(Node* node)
337 {
338     if (!enabled())
339         return;
340
341     if (!hasRemoteFrontend())
342         show();
343
344     m_domAgent->inspect(node);
345 }
346
347 bool InspectorController::enabled() const
348 {
349     return developerExtrasEnabled();
350 }
351
352 Page& InspectorController::inspectedPage() const
353 {
354     return m_page;
355 }
356
357 void InspectorController::dispatchMessageFromFrontend(const String& message)
358 {
359     if (m_inspectorBackendDispatcher)
360         m_inspectorBackendDispatcher->dispatch(message);
361 }
362
363 void InspectorController::hideHighlight()
364 {
365     ErrorString error;
366     m_domAgent->hideHighlight(&error);
367 }
368
369 Node* InspectorController::highlightedNode() const
370 {
371     return m_overlay->highlightedNode();
372 }
373
374 void InspectorController::setIndicating(bool indicating)
375 {
376 #if !PLATFORM(IOS)
377     m_overlay->setIndicating(indicating);
378 #else
379     if (indicating)
380         m_inspectorClient->showInspectorIndication();
381     else
382         m_inspectorClient->hideInspectorIndication();
383 #endif
384 }
385
386 bool InspectorController::profilerEnabled() const
387 {
388     return m_instrumentingAgents->persistentInspectorTimelineAgent();
389 }
390
391 void InspectorController::setProfilerEnabled(bool enable)
392 {
393     if (enable) {
394         m_instrumentingAgents->setPersistentInspectorTimelineAgent(m_timelineAgent);
395         m_timelineAgent->start();
396     } else {
397         m_instrumentingAgents->setPersistentInspectorTimelineAgent(nullptr);
398         m_timelineAgent->stop();
399     }
400 }
401
402 void InspectorController::resume()
403 {
404     if (m_debuggerAgent) {
405         ErrorString error;
406         m_debuggerAgent->resume(&error);
407     }
408 }
409
410 bool InspectorController::developerExtrasEnabled() const
411 {
412     return m_page.settings().developerExtrasEnabled();
413 }
414
415 bool InspectorController::canAccessInspectedScriptState(JSC::ExecState* scriptState) const
416 {
417     JSLockHolder lock(scriptState);
418     JSDOMWindow* inspectedWindow = toJSDOMWindow(scriptState->lexicalGlobalObject());
419     if (!inspectedWindow)
420         return false;
421
422     return BindingSecurity::shouldAllowAccessToDOMWindow(scriptState, inspectedWindow->impl(), DoNotReportSecurityError);
423 }
424
425 InspectorFunctionCallHandler InspectorController::functionCallHandler() const
426 {
427     return WebCore::functionCallHandlerFromAnyThread;
428 }
429
430 InspectorEvaluateHandler InspectorController::evaluateHandler() const
431 {
432     return WebCore::evaluateHandlerFromAnyThread;
433 }
434
435 void InspectorController::willCallInjectedScriptFunction(JSC::ExecState* scriptState, const String& scriptName, int scriptLine)
436 {
437     ScriptExecutionContext* scriptExecutionContext = scriptExecutionContextFromExecState(scriptState);
438     InspectorInstrumentationCookie cookie = InspectorInstrumentation::willCallFunction(scriptExecutionContext, scriptName, scriptLine);
439     m_injectedScriptInstrumentationCookies.append(cookie);
440 }
441
442 void InspectorController::didCallInjectedScriptFunction(JSC::ExecState* scriptState)
443 {
444     ASSERT(!m_injectedScriptInstrumentationCookies.isEmpty());
445     ScriptExecutionContext* scriptExecutionContext = scriptExecutionContextFromExecState(scriptState);
446     InspectorInstrumentationCookie cookie = m_injectedScriptInstrumentationCookies.takeLast();
447     InspectorInstrumentation::didCallFunction(cookie, scriptExecutionContext);
448 }
449
450 void InspectorController::frontendInitialized()
451 {
452 #if ENABLE(REMOTE_INSPECTOR)
453     if (m_isAutomaticInspection)
454         m_page.inspectorDebuggable().unpauseForInitializedInspector();
455 #endif
456 }
457
458 } // namespace WebCore
459
460 #endif // ENABLE(INSPECTOR)