Web Inspector: Page: don't allow the domain to be disabled
[WebKit-https.git] / Source / WebCore / inspector / agents / page / PageRuntimeAgent.cpp
1 /*
2  * Copyright (C) 2011 Google Inc. All rights reserved.
3  * Copyright (C) 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 "PageRuntimeAgent.h"
34
35 #include "Chrome.h"
36 #include "ChromeClient.h"
37 #include "Document.h"
38 #include "Frame.h"
39 #include "InspectorPageAgent.h"
40 #include "InstrumentingAgents.h"
41 #include "JSDOMWindowBase.h"
42 #include "Page.h"
43 #include "PageConsoleClient.h"
44 #include "ScriptController.h"
45 #include "ScriptState.h"
46 #include "SecurityOrigin.h"
47 #include "UserGestureIndicator.h"
48 #include <JavaScriptCore/InjectedScript.h>
49 #include <JavaScriptCore/InjectedScriptManager.h>
50
51 using Inspector::Protocol::Runtime::ExecutionContextDescription;
52
53
54 namespace WebCore {
55
56 using namespace Inspector;
57
58 PageRuntimeAgent::PageRuntimeAgent(PageAgentContext& context)
59     : InspectorRuntimeAgent(context)
60     , m_frontendDispatcher(std::make_unique<Inspector::RuntimeFrontendDispatcher>(context.frontendRouter))
61     , m_backendDispatcher(Inspector::RuntimeBackendDispatcher::create(context.backendDispatcher, this))
62     , m_instrumentingAgents(context.instrumentingAgents)
63     , m_inspectedPage(context.inspectedPage)
64 {
65 }
66
67 void PageRuntimeAgent::enable(ErrorString& errorString)
68 {
69     bool enabled = m_instrumentingAgents.pageRuntimeAgent() == this;
70
71     InspectorRuntimeAgent::enable(errorString);
72
73     m_instrumentingAgents.setPageRuntimeAgent(this);
74
75     if (!enabled)
76         reportExecutionContextCreation();
77 }
78
79 void PageRuntimeAgent::disable(ErrorString& errorString)
80 {
81     m_instrumentingAgents.setPageRuntimeAgent(nullptr);
82
83     InspectorRuntimeAgent::disable(errorString);
84 }
85
86 void PageRuntimeAgent::didCreateMainWorldContext(Frame& frame)
87 {
88     auto frameId = m_instrumentingAgents.inspectorPageAgent()->frameId(&frame);
89     auto* scriptState = mainWorldExecState(&frame);
90     notifyContextCreated(frameId, scriptState, nullptr, true);
91 }
92
93 InjectedScript PageRuntimeAgent::injectedScriptForEval(ErrorString& errorString, const int* executionContextId)
94 {
95     if (!executionContextId) {
96         JSC::ExecState* scriptState = mainWorldExecState(&m_inspectedPage.mainFrame());
97         InjectedScript result = injectedScriptManager().injectedScriptFor(scriptState);
98         if (result.hasNoValue())
99             errorString = "Internal error: main world execution context not found."_s;
100         return result;
101     }
102
103     InjectedScript injectedScript = injectedScriptManager().injectedScriptForId(*executionContextId);
104     if (injectedScript.hasNoValue())
105         errorString = "Execution context with given id not found."_s;
106     return injectedScript;
107 }
108
109 void PageRuntimeAgent::muteConsole()
110 {
111     PageConsoleClient::mute();
112 }
113
114 void PageRuntimeAgent::unmuteConsole()
115 {
116     PageConsoleClient::unmute();
117 }
118
119 void PageRuntimeAgent::reportExecutionContextCreation()
120 {
121     Vector<std::pair<JSC::ExecState*, SecurityOrigin*>> isolatedContexts;
122     for (Frame* frame = &m_inspectedPage.mainFrame(); frame; frame = frame->tree().traverseNext()) {
123         if (!frame->script().canExecuteScripts(NotAboutToExecuteScript))
124             continue;
125         String frameId = m_instrumentingAgents.inspectorPageAgent()->frameId(frame);
126
127         JSC::ExecState* scriptState = mainWorldExecState(frame);
128         notifyContextCreated(frameId, scriptState, nullptr, true);
129         frame->script().collectIsolatedContexts(isolatedContexts);
130         if (isolatedContexts.isEmpty())
131             continue;
132         for (auto& context : isolatedContexts)
133             notifyContextCreated(frameId, context.first, context.second, false);
134         isolatedContexts.clear();
135     }
136 }
137
138 void PageRuntimeAgent::notifyContextCreated(const String& frameId, JSC::ExecState* scriptState, SecurityOrigin* securityOrigin, bool isPageContext)
139 {
140     ASSERT(securityOrigin || isPageContext);
141
142     InjectedScript result = injectedScriptManager().injectedScriptFor(scriptState);
143     if (result.hasNoValue())
144         return;
145
146     int executionContextId = injectedScriptManager().injectedScriptIdFor(scriptState);
147     String name = securityOrigin ? securityOrigin->toRawString() : String();
148     m_frontendDispatcher->executionContextCreated(ExecutionContextDescription::create()
149         .setId(executionContextId)
150         .setIsPageContext(isPageContext)
151         .setName(name)
152         .setFrameId(frameId)
153         .release());
154 }
155
156 void PageRuntimeAgent::evaluate(ErrorString& errorString, const String& expression, const String* objectGroup, const bool* includeCommandLineAPI, const bool* doNotPauseOnExceptionsAndMuteConsole, const int* executionContextId, const bool* returnByValue, const bool* generatePreview, const bool* saveResult, const bool* emulateUserGesture, RefPtr<Inspector::Protocol::Runtime::RemoteObject>& result, Optional<bool>& wasThrown, Optional<int>& savedResultIndex)
157 {
158     auto& pageChromeClient = m_inspectedPage.chrome().client();
159
160     auto shouldEmulateUserGesture = emulateUserGesture && *emulateUserGesture;
161
162     Optional<ProcessingUserGestureState> userGestureState = shouldEmulateUserGesture ? Optional<ProcessingUserGestureState>(ProcessingUserGesture) : WTF::nullopt;
163     UserGestureIndicator gestureIndicator(userGestureState);
164
165     bool userWasInteracting = false;
166     if (shouldEmulateUserGesture) {
167         userWasInteracting = pageChromeClient.userIsInteracting();
168         if (!userWasInteracting)
169             pageChromeClient.setUserIsInteracting(true);
170     }
171
172     InspectorRuntimeAgent::evaluate(errorString, expression, objectGroup, includeCommandLineAPI, doNotPauseOnExceptionsAndMuteConsole, executionContextId, returnByValue, generatePreview, saveResult, emulateUserGesture, result, wasThrown, savedResultIndex);
173
174     if (shouldEmulateUserGesture && !userWasInteracting && pageChromeClient.userIsInteracting())
175         pageChromeClient.setUserIsInteracting(false);
176 }
177
178 } // namespace WebCore