Web Inspector: REGRESSION(r238378): reloading WebInspector after a settings change...
[WebKit-https.git] / Source / WebKit / WebProcess / WebPage / WebInspectorUI.cpp
1 /*
2  * Copyright (C) 2014-2018 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 "WebCoreArgumentCoders.h"
30 #include "WebInspectorMessages.h"
31 #include "WebInspectorProxyMessages.h"
32 #include "WebPage.h"
33 #include "WebProcess.h"
34 #include <WebCore/CertificateInfo.h>
35 #include <WebCore/Chrome.h>
36 #include <WebCore/DOMWrapperWorld.h>
37 #include <WebCore/InspectorController.h>
38 #include <WebCore/NotImplemented.h>
39 #include <WebCore/RuntimeEnabledFeatures.h>
40
41 namespace WebKit {
42 using namespace WebCore;
43
44 Ref<WebInspectorUI> WebInspectorUI::create(WebPage& page)
45 {
46     return adoptRef(*new WebInspectorUI(page));
47 }
48
49 WebInspectorUI::WebInspectorUI(WebPage& page)
50     : m_page(page)
51     , m_frontendAPIDispatcher(page)
52 {
53     RuntimeEnabledFeatures::sharedFeatures().setInspectorAdditionsEnabled(true);
54     RuntimeEnabledFeatures::sharedFeatures().setImageBitmapOffscreenCanvasEnabled(true);
55 }
56
57 void WebInspectorUI::establishConnection(uint64_t inspectedPageIdentifier, bool underTest, unsigned inspectionLevel)
58 {
59     m_inspectedPageIdentifier = inspectedPageIdentifier;
60     m_frontendAPIDispatcher.reset();
61     m_underTest = underTest;
62     m_inspectionLevel = inspectionLevel;
63
64     m_frontendController = &m_page.corePage()->inspectorController();
65     m_frontendController->setInspectorFrontendClient(this);
66
67     updateConnection();
68 }
69
70 void WebInspectorUI::updateConnection()
71 {
72     if (m_backendConnection) {
73         m_backendConnection->invalidate();
74         m_backendConnection = nullptr;
75     }
76
77 #if USE(UNIX_DOMAIN_SOCKETS)
78     IPC::Connection::SocketPair socketPair = IPC::Connection::createPlatformConnection();
79     IPC::Connection::Identifier connectionIdentifier(socketPair.server);
80     IPC::Attachment connectionClientPort(socketPair.client);
81 #elif OS(DARWIN)
82     mach_port_t listeningPort = MACH_PORT_NULL;
83     if (mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &listeningPort) != KERN_SUCCESS)
84         CRASH();
85
86     if (mach_port_insert_right(mach_task_self(), listeningPort, listeningPort, MACH_MSG_TYPE_MAKE_SEND) != KERN_SUCCESS)
87         CRASH();
88
89     IPC::Connection::Identifier connectionIdentifier(listeningPort);
90     IPC::Attachment connectionClientPort(listeningPort, MACH_MSG_TYPE_MOVE_SEND);
91 #elif PLATFORM(WIN)
92     IPC::Connection::Identifier connectionIdentifier, connClient;
93     IPC::Connection::createServerAndClientIdentifiers(connectionIdentifier, connClient);
94     IPC::Attachment connectionClientPort(connClient);
95 #else
96     notImplemented();
97     return;
98 #endif
99
100 #if USE(UNIX_DOMAIN_SOCKETS) || OS(DARWIN) || PLATFORM(WIN)
101     m_backendConnection = IPC::Connection::createServerConnection(connectionIdentifier, *this);
102     m_backendConnection->open();
103 #endif
104
105     WebProcess::singleton().parentProcessConnection()->send(Messages::WebInspectorProxy::SetFrontendConnection(connectionClientPort), m_inspectedPageIdentifier);
106 }
107
108 void WebInspectorUI::windowObjectCleared()
109 {
110     if (m_frontendHost)
111         m_frontendHost->disconnectClient();
112
113     m_frontendHost = InspectorFrontendHost::create(this, m_page.corePage());
114     m_frontendHost->addSelfToGlobalObjectInWorld(mainThreadNormalWorld());
115 }
116
117 void WebInspectorUI::frontendLoaded()
118 {
119     m_frontendAPIDispatcher.frontendLoaded();
120
121     // Tell the new frontend about the current dock state. If the window object
122     // cleared due to a reload, the dock state won't be resent from UIProcess.
123     setDockingUnavailable(m_dockingUnavailable);
124     setDockSide(m_dockSide);
125     setIsVisible(m_isVisible);
126
127     WebProcess::singleton().parentProcessConnection()->send(Messages::WebInspectorProxy::FrontendLoaded(), m_inspectedPageIdentifier);
128
129     bringToFront();
130 }
131
132 void WebInspectorUI::startWindowDrag()
133 {
134     WebProcess::singleton().parentProcessConnection()->send(Messages::WebInspectorProxy::StartWindowDrag(), m_inspectedPageIdentifier);
135 }
136
137 void WebInspectorUI::moveWindowBy(float x, float y)
138 {
139     FloatRect frameRect = m_page.corePage()->chrome().windowRect();
140     frameRect.move(x, y);
141     m_page.corePage()->chrome().setWindowRect(frameRect);
142 }
143
144 void WebInspectorUI::bringToFront()
145 {
146     WebProcess::singleton().parentProcessConnection()->send(Messages::WebInspectorProxy::BringToFront(), m_inspectedPageIdentifier);
147 }
148
149 void WebInspectorUI::closeWindow()
150 {
151     WebProcess::singleton().parentProcessConnection()->send(Messages::WebInspectorProxy::DidClose(), m_inspectedPageIdentifier);
152
153     if (m_backendConnection) {
154         m_backendConnection->invalidate();
155         m_backendConnection = nullptr;
156     }
157
158     if (m_frontendController) {
159         m_frontendController->setInspectorFrontendClient(nullptr);
160         m_frontendController = nullptr;
161     }
162
163     if (m_frontendHost)
164         m_frontendHost->disconnectClient();
165
166     m_inspectedPageIdentifier = 0;
167     m_underTest = false;
168 }
169
170 void WebInspectorUI::reopen()
171 {
172     WebProcess::singleton().parentProcessConnection()->send(Messages::WebInspectorProxy::Reopen(), m_inspectedPageIdentifier);
173 }
174
175 WebCore::UserInterfaceLayoutDirection WebInspectorUI::userInterfaceLayoutDirection() const
176 {
177     return m_page.corePage()->userInterfaceLayoutDirection();
178 }
179
180 void WebInspectorUI::requestSetDockSide(DockSide side)
181 {
182     auto& webProcess = WebProcess::singleton();
183     switch (side) {
184     case DockSide::Undocked:
185         webProcess.parentProcessConnection()->send(Messages::WebInspectorProxy::Detach(), m_inspectedPageIdentifier);
186         break;
187     case DockSide::Right:
188         webProcess.parentProcessConnection()->send(Messages::WebInspectorProxy::AttachRight(), m_inspectedPageIdentifier);
189         break;
190     case DockSide::Left:
191         webProcess.parentProcessConnection()->send(Messages::WebInspectorProxy::AttachLeft(), m_inspectedPageIdentifier);
192         break;
193     case DockSide::Bottom:
194         webProcess.parentProcessConnection()->send(Messages::WebInspectorProxy::AttachBottom(), m_inspectedPageIdentifier);
195         break;
196     }
197 }
198
199 void WebInspectorUI::setDockSide(DockSide side)
200 {
201     ASCIILiteral sideString { ASCIILiteral::null() };
202
203     switch (side) {
204     case DockSide::Undocked:
205         sideString = "undocked"_s;
206         break;
207
208     case DockSide::Right:
209         sideString = "right"_s;
210         break;
211
212     case DockSide::Left:
213         sideString = "left"_s;
214         break;
215
216     case DockSide::Bottom:
217         sideString = "bottom"_s;
218         break;
219     }
220
221     m_dockSide = side;
222
223     m_frontendAPIDispatcher.dispatchCommand("setDockSide"_s, String(sideString));
224 }
225
226 void WebInspectorUI::setDockingUnavailable(bool unavailable)
227 {
228     m_dockingUnavailable = unavailable;
229
230     m_frontendAPIDispatcher.dispatchCommand("setDockingUnavailable"_s, unavailable);
231 }
232
233 void WebInspectorUI::setIsVisible(bool visible)
234 {
235     m_isVisible = visible;
236
237     m_frontendAPIDispatcher.dispatchCommand("setIsVisible"_s, visible);
238 }
239
240 void WebInspectorUI::changeAttachedWindowHeight(unsigned height)
241 {
242     WebProcess::singleton().parentProcessConnection()->send(Messages::WebInspectorProxy::SetAttachedWindowHeight(height), m_inspectedPageIdentifier);
243 }
244
245 void WebInspectorUI::changeAttachedWindowWidth(unsigned width)
246 {
247     WebProcess::singleton().parentProcessConnection()->send(Messages::WebInspectorProxy::SetAttachedWindowWidth(width), m_inspectedPageIdentifier);
248 }
249
250 void WebInspectorUI::openInNewTab(const String& url)
251 {
252     if (m_backendConnection)
253         m_backendConnection->send(Messages::WebInspector::OpenInNewTab(url), 0);
254 }
255
256 void WebInspectorUI::save(const WTF::String& filename, const WTF::String& content, bool base64Encoded, bool forceSaveAs)
257 {
258     WebProcess::singleton().parentProcessConnection()->send(Messages::WebInspectorProxy::Save(filename, content, base64Encoded, forceSaveAs), m_inspectedPageIdentifier);
259 }
260
261 void WebInspectorUI::append(const WTF::String& filename, const WTF::String& content)
262 {
263     WebProcess::singleton().parentProcessConnection()->send(Messages::WebInspectorProxy::Append(filename, content), m_inspectedPageIdentifier);
264 }
265
266 void WebInspectorUI::inspectedURLChanged(const String& urlString)
267 {
268     WebProcess::singleton().parentProcessConnection()->send(Messages::WebInspectorProxy::InspectedURLChanged(urlString), m_inspectedPageIdentifier);
269 }
270
271 void WebInspectorUI::showCertificate(const CertificateInfo& certificateInfo)
272 {
273     WebProcess::singleton().parentProcessConnection()->send(Messages::WebInspectorProxy::ShowCertificate(certificateInfo), m_inspectedPageIdentifier);
274 }
275
276 void WebInspectorUI::showConsole()
277 {
278     m_frontendAPIDispatcher.dispatchCommand("showConsole"_s);
279 }
280
281 void WebInspectorUI::showResources()
282 {
283     m_frontendAPIDispatcher.dispatchCommand("showResources"_s);
284 }
285
286 void WebInspectorUI::showTimelines()
287 {
288     m_frontendAPIDispatcher.dispatchCommand("showTimelines"_s);
289 }
290
291 void WebInspectorUI::showMainResourceForFrame(const String& frameIdentifier)
292 {
293     m_frontendAPIDispatcher.dispatchCommand("showMainResourceForFrame"_s, frameIdentifier);
294 }
295
296 void WebInspectorUI::startPageProfiling()
297 {
298     m_frontendAPIDispatcher.dispatchCommand("setTimelineProfilingEnabled"_s, true);
299 }
300
301 void WebInspectorUI::stopPageProfiling()
302 {
303     m_frontendAPIDispatcher.dispatchCommand("setTimelineProfilingEnabled"_s, false);
304 }
305
306 void WebInspectorUI::startElementSelection()
307 {
308     m_frontendAPIDispatcher.dispatchCommand("setElementSelectionEnabled"_s, true);
309 }
310
311 void WebInspectorUI::stopElementSelection()
312 {
313     m_frontendAPIDispatcher.dispatchCommand("setElementSelectionEnabled"_s, false);
314 }
315
316 void WebInspectorUI::didSave(const String& url)
317 {
318     m_frontendAPIDispatcher.dispatchCommand("savedURL"_s, url);
319 }
320
321 void WebInspectorUI::didAppend(const String& url)
322 {
323     m_frontendAPIDispatcher.dispatchCommand("appendedToURL"_s, url);
324 }
325
326 void WebInspectorUI::sendMessageToFrontend(const String& message)
327 {
328     m_frontendAPIDispatcher.dispatchMessageAsync(message);
329 }
330
331 void WebInspectorUI::pagePaused()
332 {
333     m_frontendAPIDispatcher.suspend();
334 }
335
336 void WebInspectorUI::pageUnpaused()
337 {
338     m_frontendAPIDispatcher.unsuspend();
339 }
340
341 void WebInspectorUI::sendMessageToBackend(const String& message)
342 {
343     WebProcess::singleton().parentProcessConnection()->send(Messages::WebInspectorProxy::SendMessageToBackend(message), m_inspectedPageIdentifier);
344 }
345
346 } // namespace WebKit