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