Web Inspector: REGRESSION(r238378): reloading WebInspector after a settings change...
[WebKit-https.git] / Source / WebKit / WebProcess / WebPage / WebInspector.cpp
1 /*
2  * Copyright (C) 2010, 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 "WebInspector.h"
28
29 #include "WebFrame.h"
30 #include "WebInspectorMessages.h"
31 #include "WebInspectorProxyMessages.h"
32 #include "WebInspectorUIMessages.h"
33 #include "WebPage.h"
34 #include "WebProcess.h"
35 #include <WebCore/Chrome.h>
36 #include <WebCore/Document.h>
37 #include <WebCore/Frame.h>
38 #include <WebCore/FrameLoadRequest.h>
39 #include <WebCore/FrameLoader.h>
40 #include <WebCore/FrameView.h>
41 #include <WebCore/InspectorController.h>
42 #include <WebCore/InspectorFrontendClient.h>
43 #include <WebCore/InspectorPageAgent.h>
44 #include <WebCore/NavigationAction.h>
45 #include <WebCore/NotImplemented.h>
46 #include <WebCore/Page.h>
47 #include <WebCore/ScriptController.h>
48 #include <WebCore/WindowFeatures.h>
49
50 static const float minimumAttachedHeight = 250;
51 static const float maximumAttachedHeightRatio = 0.75;
52 static const float minimumAttachedWidth = 500;
53
54 namespace WebKit {
55 using namespace WebCore;
56
57 Ref<WebInspector> WebInspector::create(WebPage* page)
58 {
59     return adoptRef(*new WebInspector(page));
60 }
61
62 WebInspector::WebInspector(WebPage* page)
63     : m_page(page)
64 {
65 }
66
67 WebInspector::~WebInspector()
68 {
69     if (m_frontendConnection)
70         m_frontendConnection->invalidate();
71 }
72
73 void WebInspector::openLocalInspectorFrontend(bool underTest)
74 {
75     WebProcess::singleton().parentProcessConnection()->send(Messages::WebInspectorProxy::OpenLocalInspectorFrontend(canAttachWindow(), underTest), m_page->pageID());
76 }
77
78 void WebInspector::setFrontendConnection(IPC::Attachment encodedConnectionIdentifier)
79 {
80     // We might receive multiple updates if this web process got swapped into a WebPageProxy
81     // shortly after another process established the connection.
82     if (m_frontendConnection) {
83         m_frontendConnection->invalidate();
84         m_frontendConnection = nullptr;
85     }
86
87 #if USE(UNIX_DOMAIN_SOCKETS)
88     IPC::Connection::Identifier connectionIdentifier(encodedConnectionIdentifier.releaseFileDescriptor());
89 #elif OS(DARWIN)
90     IPC::Connection::Identifier connectionIdentifier(encodedConnectionIdentifier.port());
91 #elif OS(WINDOWS)
92     IPC::Connection::Identifier connectionIdentifier(encodedConnectionIdentifier.handle());
93 #else
94     notImplemented();
95     return;
96 #endif
97
98     if (!IPC::Connection::identifierIsValid(connectionIdentifier))
99         return;
100
101     m_frontendConnection = IPC::Connection::createClientConnection(connectionIdentifier, *this);
102     m_frontendConnection->open();
103 }
104
105 void WebInspector::closeFrontendConnection()
106 {
107     WebProcess::singleton().parentProcessConnection()->send(Messages::WebInspectorProxy::DidClose(), m_page->pageID());
108
109     // If we tried to close the frontend before it was created, then no connection exists yet.
110     if (m_frontendConnection) {
111         m_frontendConnection->invalidate();
112         m_frontendConnection = nullptr;
113     }
114
115     m_attached = false;
116     m_previousCanAttach = false;
117 }
118
119 void WebInspector::bringToFront()
120 {
121     WebProcess::singleton().parentProcessConnection()->send(Messages::WebInspectorProxy::BringToFront(), m_page->pageID());
122 }
123
124 // Called by WebInspector messages
125 void WebInspector::show()
126 {
127     if (!m_page->corePage())
128         return;
129
130     m_page->corePage()->inspectorController().show();
131 }
132
133 void WebInspector::close()
134 {
135     if (!m_page->corePage())
136         return;
137
138     // Close could be called multiple times during teardown.
139     if (!m_frontendConnection)
140         return;
141
142     closeFrontendConnection();
143 }
144
145 void WebInspector::openInNewTab(const String& urlString)
146 {
147     UserGestureIndicator indicator { ProcessingUserGesture };
148
149     Page* inspectedPage = m_page->corePage();
150     if (!inspectedPage)
151         return;
152
153     Frame& inspectedMainFrame = inspectedPage->mainFrame();
154     FrameLoadRequest frameLoadRequest { *inspectedMainFrame.document(), inspectedMainFrame.document()->securityOrigin(), { urlString }, "_blank"_s, LockHistory::No, LockBackForwardList::No, MaybeSendReferrer, AllowNavigationToInvalidURL::Yes, NewFrameOpenerPolicy::Allow, ShouldOpenExternalURLsPolicy::ShouldNotAllow, InitiatedByMainFrame::Unknown };
155
156     NavigationAction action { *inspectedMainFrame.document(), frameLoadRequest.resourceRequest(), frameLoadRequest.initiatedByMainFrame(), NavigationType::LinkClicked };
157     Page* newPage = inspectedPage->chrome().createWindow(inspectedMainFrame, frameLoadRequest, { }, action);
158     if (!newPage)
159         return;
160
161     newPage->mainFrame().loader().load(WTFMove(frameLoadRequest));
162 }
163
164 void WebInspector::evaluateScriptForTest(const String& script)
165 {
166     if (!m_page->corePage())
167         return;
168
169     m_page->corePage()->inspectorController().evaluateForTestInFrontend(script);
170 }
171
172 void WebInspector::showConsole()
173 {
174     if (!m_page->corePage())
175         return;
176
177     m_page->corePage()->inspectorController().show();
178     m_frontendConnection->send(Messages::WebInspectorUI::ShowConsole(), 0);
179 }
180
181 void WebInspector::showResources()
182 {
183     if (!m_page->corePage())
184         return;
185
186     m_page->corePage()->inspectorController().show();
187     m_frontendConnection->send(Messages::WebInspectorUI::ShowResources(), 0);
188 }
189
190 void WebInspector::showTimelines()
191 {
192     if (!m_page->corePage())
193         return;
194
195     m_page->corePage()->inspectorController().show();
196     m_frontendConnection->send(Messages::WebInspectorUI::ShowTimelines(), 0);
197 }
198
199 void WebInspector::showMainResourceForFrame(uint64_t frameIdentifier)
200 {
201     WebFrame* frame = WebProcess::singleton().webFrame(frameIdentifier);
202     if (!frame)
203         return;
204
205     if (!m_page->corePage())
206         return;
207
208     m_page->corePage()->inspectorController().show();
209
210     String inspectorFrameIdentifier = m_page->corePage()->inspectorController().pageAgent()->frameId(frame->coreFrame());
211     m_frontendConnection->send(Messages::WebInspectorUI::ShowMainResourceForFrame(inspectorFrameIdentifier), 0);
212 }
213
214 void WebInspector::startPageProfiling()
215 {
216     if (!m_page->corePage())
217         return;
218
219     m_frontendConnection->send(Messages::WebInspectorUI::StartPageProfiling(), 0);
220 }
221
222 void WebInspector::stopPageProfiling()
223 {
224     if (!m_page->corePage())
225         return;
226
227     m_frontendConnection->send(Messages::WebInspectorUI::StopPageProfiling(), 0);
228 }
229
230 void WebInspector::startElementSelection()
231 {
232     if (!m_page->corePage())
233         return;
234
235     m_frontendConnection->send(Messages::WebInspectorUI::StartElementSelection(), 0);
236 }
237
238 void WebInspector::stopElementSelection()
239 {
240     if (!m_page->corePage())
241         return;
242
243     m_frontendConnection->send(Messages::WebInspectorUI::StopElementSelection(), 0);
244 }
245
246 void WebInspector::elementSelectionChanged(bool active)
247 {
248     WebProcess::singleton().parentProcessConnection()->send(Messages::WebInspectorProxy::ElementSelectionChanged(active), m_page->pageID());
249 }
250
251 bool WebInspector::canAttachWindow()
252 {
253     if (!m_page->corePage())
254         return false;
255
256     // Don't allow attaching to another inspector -- two inspectors in one window is too much!
257     if (m_page->isInspectorPage())
258         return false;
259
260     // If we are already attached, allow attaching again to allow switching sides.
261     if (m_attached)
262         return true;
263
264     // Don't allow the attach if the window would be too small to accommodate the minimum inspector size.
265     unsigned inspectedPageHeight = m_page->corePage()->mainFrame().view()->visibleHeight();
266     unsigned inspectedPageWidth = m_page->corePage()->mainFrame().view()->visibleWidth();
267     unsigned maximumAttachedHeight = inspectedPageHeight * maximumAttachedHeightRatio;
268     return minimumAttachedHeight <= maximumAttachedHeight && minimumAttachedWidth <= inspectedPageWidth;
269 }
270
271 void WebInspector::updateDockingAvailability()
272 {
273     if (m_attached)
274         return;
275
276     bool canAttachWindow = this->canAttachWindow();
277     if (m_previousCanAttach == canAttachWindow)
278         return;
279
280     m_previousCanAttach = canAttachWindow;
281
282     WebProcess::singleton().parentProcessConnection()->send(Messages::WebInspectorProxy::AttachAvailabilityChanged(canAttachWindow), m_page->pageID());
283 }
284
285 } // namespace WebKit