0ffedd23806914af129e086804168b879ced8419
[WebKit-https.git] / Source / WebKit2 / WebProcess / WebPage / WebInspectorUI.cpp
1 /*
2  * Copyright (C) 2014 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "WebInspectorUI.h"
28
29 #include "WebInspectorMessages.h"
30 #include "WebInspectorProxyMessages.h"
31 #include "WebPage.h"
32 #include "WebProcess.h"
33 #include <JavaScriptCore/ScriptValue.h>
34 #include <WebCore/Chrome.h>
35 #include <WebCore/DOMWrapperWorld.h>
36 #include <WebCore/InspectorController.h>
37 #include <WebCore/MainFrame.h>
38 #include <WebCore/NotImplemented.h>
39 #include <WebCore/ScriptController.h>
40 #include <WebCore/ScriptGlobalObject.h>
41 #include <WebCore/ScriptState.h>
42
43 using namespace WebCore;
44
45 namespace WebKit {
46
47 PassRefPtr<WebInspectorUI> WebInspectorUI::create(WebPage* page)
48 {
49     return adoptRef(new WebInspectorUI(page));
50 }
51
52 WebInspectorUI::WebInspectorUI(WebPage* page)
53     : m_page(page)
54     , m_inspectedPageIdentifier(0)
55     , m_underTest(false)
56     , m_frontendLoaded(false)
57     , m_dockSide(DockSide::Undocked)
58 #if PLATFORM(COCOA)
59     , m_hasLocalizedStringsURL(false)
60 #endif
61 {
62 }
63
64 void WebInspectorUI::establishConnection(IPC::Attachment encodedConnectionIdentifier, uint64_t inspectedPageIdentifier, bool underTest)
65 {
66 #if OS(DARWIN)
67     IPC::Connection::Identifier connectionIdentifier(encodedConnectionIdentifier.port());
68 #elif USE(UNIX_DOMAIN_SOCKETS)
69     IPC::Connection::Identifier connectionIdentifier(encodedConnectionIdentifier.releaseFileDescriptor());
70 #else
71     notImplemented();
72     return;
73 #endif
74
75     if (IPC::Connection::identifierIsNull(connectionIdentifier))
76         return;
77
78     m_inspectedPageIdentifier = inspectedPageIdentifier;
79     m_frontendLoaded = false;
80     m_underTest = underTest;
81
82     m_page->corePage()->inspectorController().setInspectorFrontendClient(this);
83
84     m_backendConnection = IPC::Connection::createClientConnection(connectionIdentifier, *this, RunLoop::main());
85     m_backendConnection->open();
86 }
87
88 void WebInspectorUI::windowObjectCleared()
89 {
90     if (m_frontendHost)
91         m_frontendHost->disconnectClient();
92
93     m_frontendHost = InspectorFrontendHost::create(this, m_page->corePage());
94     ScriptGlobalObject::set(execStateFromPage(mainThreadNormalWorld(), m_page->corePage()), ASCIILiteral("InspectorFrontendHost"), m_frontendHost.get());
95 }
96
97 void WebInspectorUI::frontendLoaded()
98 {
99     m_frontendLoaded = true;
100
101     evaluatePendingExpressions();
102     bringToFront();
103 }
104
105 void WebInspectorUI::moveWindowBy(float x, float y)
106 {
107     FloatRect frameRect = m_page->corePage()->chrome().windowRect();
108     frameRect.move(x, y);
109     m_page->corePage()->chrome().setWindowRect(frameRect);
110 }
111
112 void WebInspectorUI::bringToFront()
113 {
114     WebProcess::singleton().parentProcessConnection()->send(Messages::WebInspectorProxy::BringToFront(), m_inspectedPageIdentifier);
115 }
116
117 void WebInspectorUI::closeWindow()
118 {
119     WebProcess::singleton().parentProcessConnection()->send(Messages::WebInspectorProxy::DidClose(), m_inspectedPageIdentifier);
120
121     m_backendConnection->invalidate();
122     m_backendConnection = nullptr;
123
124     m_inspectedPageIdentifier = 0;
125     m_underTest = false;
126 }
127
128 void WebInspectorUI::requestSetDockSide(DockSide side)
129 {
130     auto& webProcess = WebProcess::singleton();
131     switch (side) {
132     case DockSide::Undocked:
133         webProcess.parentProcessConnection()->send(Messages::WebInspectorProxy::Detach(), m_inspectedPageIdentifier);
134         break;
135     case DockSide::Right:
136         webProcess.parentProcessConnection()->send(Messages::WebInspectorProxy::AttachRight(), m_inspectedPageIdentifier);
137         break;
138     case DockSide::Bottom:
139         webProcess.parentProcessConnection()->send(Messages::WebInspectorProxy::AttachBottom(), m_inspectedPageIdentifier);
140         break;
141     }
142 }
143
144 void WebInspectorUI::setDockSide(DockSide side)
145 {
146     const char* sideString;
147
148     switch (side) {
149     case DockSide::Undocked:
150         sideString = "undocked";
151         break;
152
153     case DockSide::Right:
154         sideString = "right";
155         break;
156
157     case DockSide::Bottom:
158         sideString = "bottom";
159         break;
160     }
161
162     m_dockSide = side;
163
164     evaluateCommandOnLoad(ASCIILiteral("setDockSide"), ASCIILiteral(sideString));
165 }
166
167 void WebInspectorUI::setDockingUnavailable(bool unavailable)
168 {
169     evaluateCommandOnLoad(ASCIILiteral("setDockingUnavailable"), unavailable);
170 }
171
172 void WebInspectorUI::changeAttachedWindowHeight(unsigned height)
173 {
174     WebProcess::singleton().parentProcessConnection()->send(Messages::WebInspectorProxy::SetAttachedWindowHeight(height), m_inspectedPageIdentifier);
175 }
176
177 void WebInspectorUI::changeAttachedWindowWidth(unsigned width)
178 {
179     WebProcess::singleton().parentProcessConnection()->send(Messages::WebInspectorProxy::SetAttachedWindowWidth(width), m_inspectedPageIdentifier);
180 }
181
182 void WebInspectorUI::setToolbarHeight(unsigned height)
183 {
184     WebProcess::singleton().parentProcessConnection()->send(Messages::WebInspectorProxy::SetToolbarHeight(height), m_inspectedPageIdentifier);
185 }
186
187 void WebInspectorUI::openInNewTab(const String& url)
188 {
189     if (m_backendConnection)
190         m_backendConnection->send(Messages::WebInspector::OpenInNewTab(url), 0);
191 }
192
193 void WebInspectorUI::save(const WTF::String& filename, const WTF::String& content, bool base64Encoded, bool forceSaveAs)
194 {
195     WebProcess::singleton().parentProcessConnection()->send(Messages::WebInspectorProxy::Save(filename, content, base64Encoded, forceSaveAs), m_inspectedPageIdentifier);
196 }
197
198 void WebInspectorUI::append(const WTF::String& filename, const WTF::String& content)
199 {
200     WebProcess::singleton().parentProcessConnection()->send(Messages::WebInspectorProxy::Append(filename, content), m_inspectedPageIdentifier);
201 }
202
203 void WebInspectorUI::inspectedURLChanged(const String& urlString)
204 {
205     WebProcess::singleton().parentProcessConnection()->send(Messages::WebInspectorProxy::InspectedURLChanged(urlString), m_inspectedPageIdentifier);
206 }
207
208 void WebInspectorUI::showConsole()
209 {
210     evaluateCommandOnLoad(ASCIILiteral("showConsole"));
211 }
212
213 void WebInspectorUI::showResources()
214 {
215     evaluateCommandOnLoad(ASCIILiteral("showResources"));
216 }
217
218 void WebInspectorUI::showMainResourceForFrame(String frameIdentifier)
219 {
220     evaluateCommandOnLoad(ASCIILiteral("showMainResourceForFrame"), frameIdentifier);
221 }
222
223 void WebInspectorUI::startPageProfiling()
224 {
225     evaluateCommandOnLoad(ASCIILiteral("setTimelineProfilingEnabled"), true);
226 }
227
228 void WebInspectorUI::stopPageProfiling()
229 {
230     evaluateCommandOnLoad(ASCIILiteral("setTimelineProfilingEnabled"), false);
231 }
232
233 void WebInspectorUI::didSave(const String& url)
234 {
235     evaluateCommandOnLoad(ASCIILiteral("savedURL"), url);
236 }
237
238 void WebInspectorUI::didAppend(const String& url)
239 {
240     evaluateCommandOnLoad(ASCIILiteral("appendedToURL"), url);
241 }
242
243 void WebInspectorUI::sendMessageToFrontend(const String& message)
244 {
245     evaluateExpressionOnLoad(makeString("InspectorFrontendAPI.dispatchMessageAsync(", message, ")"));
246 }
247
248 void WebInspectorUI::sendMessageToBackend(const String& message)
249 {
250     if (m_backendConnection)
251         m_backendConnection->send(Messages::WebInspector::SendMessageToBackend(message), 0);
252 }
253
254 void WebInspectorUI::evaluateCommandOnLoad(const String& command, const String& argument)
255 {
256     if (argument.isNull())
257         evaluateExpressionOnLoad(makeString("InspectorFrontendAPI.dispatch([\"", command, "\"])"));
258     else
259         evaluateExpressionOnLoad(makeString("InspectorFrontendAPI.dispatch([\"", command, "\", \"", argument, "\"])"));
260 }
261
262 void WebInspectorUI::evaluateCommandOnLoad(const String& command, bool argument)
263 {
264     evaluateExpressionOnLoad(makeString("InspectorFrontendAPI.dispatch([\"", command, "\", ", ASCIILiteral(argument ? "true" : "false"), "])"));
265 }
266
267 void WebInspectorUI::evaluateExpressionOnLoad(const String& expression)
268 {
269     if (m_frontendLoaded) {
270         ASSERT(m_queue.isEmpty());
271         m_page->corePage()->mainFrame().script().executeScript(expression);
272         return;
273     }
274
275     m_queue.append(expression);
276 }
277
278 void WebInspectorUI::evaluatePendingExpressions()
279 {
280     ASSERT(m_frontendLoaded);
281
282     for (const String& expression : m_queue)
283         m_page->corePage()->mainFrame().script().executeScript(expression);
284
285     m_queue.clear();
286 }
287
288 } // namespace WebKit