Web Inspector: Network: add button to show system certificate dialog
[WebKit-https.git] / Source / WebKit / UIProcess / win / WebInspectorProxyWin.cpp
1 /*
2  * Copyright (C) 2010 Apple Inc. All rights reserved.
3  * Copyright (C) 2017 Sony Interactive Entertainment Inc.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
15  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
16  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
18  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
24  * THE POSSIBILITY OF SUCH DAMAGE.
25  */
26
27 #include "config.h"
28 #include "WebInspectorProxy.h"
29
30 #include "APINavigation.h"
31 #include "APINavigationAction.h"
32 #include "APIPageConfiguration.h"
33 #include "CFURLExtras.h"
34 #include "PageClientImpl.h"
35 #include "WebFramePolicyListenerProxy.h"
36 #include "WebPageGroup.h"
37 #include "WebPageProxy.h"
38 #include "WebPreferences.h"
39 #include "WebProcessPool.h"
40 #include "WebView.h"
41 #include <WebCore/CertificateInfo.h>
42 #include <WebCore/InspectorFrontendClientLocal.h>
43 #include <WebCore/NotImplemented.h>
44 #include <WebCore/WebCoreBundleWin.h>
45 #include <WebCore/WebCoreInstanceHandle.h>
46 #include <WebCore/WindowMessageBroadcaster.h>
47 #include <WebKit/WKPage.h>
48
49 namespace WebKit {
50
51 static const LPCWSTR WebInspectorProxyPointerProp = L"WebInspectorProxyPointer";
52 static const LPCWSTR WebInspectorProxyClassName = L"WebInspectorProxyClass";
53
54 struct InspectedWindowInfo {
55     int left;
56     int top;
57     int viewWidth;
58     int viewHeight;
59     int parentWidth;
60     int parentHeight;
61 };
62
63 static InspectedWindowInfo getInspectedWindowInfo(HWND inspectedWindow, HWND parentWindow)
64 {
65     RECT rect;
66     ::GetClientRect(inspectedWindow, &rect);
67     ::MapWindowPoints(inspectedWindow, parentWindow, (LPPOINT)&rect, 2);
68
69     RECT parentRect;
70     ::GetClientRect(parentWindow, &parentRect);
71     return { rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, parentRect.right - parentRect.left, parentRect.bottom - parentRect.top };
72 }
73
74 void WebInspectorProxy::windowReceivedMessage(HWND hwnd, UINT msg, WPARAM, LPARAM lParam)
75 {
76     switch (msg) {
77     case WM_WINDOWPOSCHANGING: {
78         if (!m_isAttached)
79             return;
80
81         auto windowPos = reinterpret_cast<WINDOWPOS*>(lParam);
82
83         if (windowPos->flags & SWP_NOSIZE)
84             return;
85
86         HWND parent = GetParent(hwnd);
87         RECT parentRect;
88         GetClientRect(parent, &parentRect);
89
90         RECT inspectorRect;
91         GetClientRect(m_inspectorViewWindow, &inspectorRect);
92
93         switch (m_attachmentSide) {
94         case AttachmentSide::Bottom: {
95             unsigned inspectorHeight = WebCore::InspectorFrontendClientLocal::constrainedAttachedWindowHeight(inspectorRect.bottom - inspectorRect.top, windowPos->cy);
96             windowPos->cy -= inspectorHeight;
97             ::SetWindowPos(m_inspectorViewWindow, 0, windowPos->x, windowPos->y + windowPos->cy, windowPos->cx, inspectorHeight, SWP_NOZORDER);
98             break;
99         }
100         case AttachmentSide::Left:
101         case AttachmentSide::Right: {
102             unsigned inspectorWidth = WebCore::InspectorFrontendClientLocal::constrainedAttachedWindowWidth(inspectorRect.right - inspectorRect.left, windowPos->cx);
103             windowPos->cx -= inspectorWidth;
104             ::SetWindowPos(m_inspectorViewWindow, 0, windowPos->x + windowPos->cx, windowPos->y, inspectorWidth, windowPos->cy, SWP_NOZORDER);
105             break;
106         }
107         default:
108             break;
109         }
110         break;
111     }
112     default:
113         break;
114     }
115 }
116
117 LRESULT CALLBACK WebInspectorProxy::wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
118 {
119     WebInspectorProxy* client = reinterpret_cast<WebInspectorProxy*>(::GetProp(hwnd, WebInspectorProxyPointerProp));
120     switch (msg) {
121     case WM_SIZE:
122         ::SetWindowPos(client->m_inspectorViewWindow, 0, 0, 0, LOWORD(lParam), HIWORD(lParam), SWP_NOZORDER);
123         return 0;
124     case WM_CLOSE:
125         client->close();
126         return 0;
127     default:
128         break;
129     }
130     return ::DefWindowProc(hwnd, msg, wParam, lParam);
131 }
132
133 bool WebInspectorProxy::registerWindowClass()
134 {
135     static bool haveRegisteredWindowClass = false;
136
137     if (haveRegisteredWindowClass)
138         return true;
139     haveRegisteredWindowClass = true;
140
141     WNDCLASSEX wcex;
142     wcex.cbSize = sizeof(WNDCLASSEX);
143     wcex.style = 0;
144     wcex.lpfnWndProc = wndProc;
145     wcex.cbClsExtra = 0;
146     wcex.cbWndExtra = 0;
147     wcex.hInstance = WebCore::instanceHandle();
148     wcex.hIcon = 0;
149     wcex.hCursor = LoadCursor(0, IDC_ARROW);
150     wcex.hbrBackground = 0;
151     wcex.lpszMenuName = 0;
152     wcex.lpszClassName = WebInspectorProxyClassName;
153     wcex.hIconSm = 0;
154     return ::RegisterClassEx(&wcex);
155 }
156
157 static void decidePolicyForNavigationAction(WKPageRef pageRef, WKNavigationActionRef navigationActionRef, WKFramePolicyListenerRef listenerRef, WKTypeRef, const void* clientInfo)
158 {
159     // Allow non-main frames to navigate anywhere.
160     API::FrameInfo* sourceFrame = toImpl(navigationActionRef)->sourceFrame();
161     if (sourceFrame && !sourceFrame->isMainFrame()) {
162         toImpl(listenerRef)->use({ });
163         return;
164     }
165
166     const WebInspectorProxy* webInspectorProxy = static_cast<const WebInspectorProxy*>(clientInfo);
167     ASSERT(webInspectorProxy);
168
169     WebCore::ResourceRequest request = toImpl(navigationActionRef)->request();
170
171     // Allow loading of the main inspector file.
172     if (WebInspectorProxy::isMainOrTestInspectorPage(request.url())) {
173         toImpl(listenerRef)->use({ });
174         return;
175     }
176
177     // Prevent everything else from loading in the inspector's page.
178     toImpl(listenerRef)->ignore();
179
180     // And instead load it in the inspected page.
181     webInspectorProxy->inspectedPage()->loadRequest(WTFMove(request));
182 }
183
184 static void webProcessDidCrash(WKPageRef, const void* clientInfo)
185 {
186     WebInspectorProxy* webInspectorProxy = static_cast<WebInspectorProxy*>(const_cast<void*>(clientInfo));
187     ASSERT(webInspectorProxy);
188     webInspectorProxy->closeForCrash();
189 }
190
191 WebPageProxy* WebInspectorProxy::platformCreateFrontendPage()
192 {
193     ASSERT(inspectedPage());
194
195     RefPtr<WebPreferences> preferences = WebPreferences::create(String(), "WebKit2.", "WebKit2.");
196 #if ENABLE(DEVELOPER_MODE)
197     // Allow developers to inspect the Web Inspector in debug builds without changing settings.
198     preferences->setDeveloperExtrasEnabled(true);
199     preferences->setLogsPageMessagesToSystemConsoleEnabled(true);
200 #endif
201     preferences->setAllowFileAccessFromFileURLs(true);
202     preferences->setJavaScriptRuntimeFlags({ });
203     RefPtr<WebPageGroup> pageGroup = WebPageGroup::create(inspectorPageGroupIdentifierForPage(inspectedPage()));
204     auto pageConfiguration = API::PageConfiguration::create();
205     pageConfiguration->setProcessPool(&inspectorProcessPool(inspectionLevel()));
206     pageConfiguration->setPreferences(preferences.get());
207     pageConfiguration->setPageGroup(pageGroup.get());
208
209     WKPageNavigationClientV0 navigationClient = {
210         { 0, this },
211         decidePolicyForNavigationAction,
212         nullptr, // decidePolicyForNavigationResponse
213         nullptr, // decidePolicyForPluginLoad
214         nullptr, // didStartProvisionalNavigation
215         nullptr, // didReceiveServerRedirectForProvisionalNavigation
216         nullptr, // didFailProvisionalNavigation
217         nullptr, // didCommitNavigation
218         nullptr, // didFinishNavigation
219         nullptr, // didFailNavigation
220         nullptr, // didFailProvisionalLoadInSubframe
221         nullptr, // didFinishDocumentLoad
222         nullptr, // didSameDocumentNavigation
223         nullptr, // renderingProgressDidChange
224         nullptr, // canAuthenticateAgainstProtectionSpace
225         nullptr, // didReceiveAuthenticationChallenge
226         webProcessDidCrash,
227         nullptr, // copyWebCryptoMasterKey
228
229         nullptr, // didBeginNavigationGesture
230         nullptr, // willEndNavigationGesture
231         nullptr, // didEndNavigationGesture
232         nullptr, // didRemoveNavigationGestureSnapshot
233     };
234
235     RECT r = { 0, 0, static_cast<LONG>(initialWindowWidth), static_cast<LONG>(initialWindowHeight) };
236     auto page = inspectedPage();
237     m_inspectedViewWindow = page->viewWidget();
238     m_inspectedViewParentWindow = ::GetParent(m_inspectedViewWindow);
239     auto view = WebView::create(r, pageConfiguration, m_inspectedViewParentWindow);
240     m_inspectorView = &view.leakRef();
241     auto inspectorPage = m_inspectorView->page();
242     m_inspectorViewWindow = inspectorPage->viewWidget();
243     WKPageSetPageNavigationClient(toAPI(inspectorPage), &navigationClient.base);
244
245     return inspectorPage;
246 }
247
248 void WebInspectorProxy::platformCloseFrontendPageAndWindow()
249 {
250     WebCore::WindowMessageBroadcaster::removeListener(m_inspectedViewWindow, this);
251     m_inspectorView = nullptr;
252     m_inspectorPage = nullptr;
253     if (m_inspectorViewWindow) {
254         ::DestroyWindow(m_inspectorViewWindow);
255         m_inspectorViewWindow = nullptr;
256     }
257     if (m_inspectorDetachWindow) {
258         ::RemoveProp(m_inspectorDetachWindow, WebInspectorProxyPointerProp);
259         ::DestroyWindow(m_inspectorDetachWindow);
260         m_inspectorDetachWindow = nullptr;
261     }
262     m_inspectedViewWindow = nullptr;
263     m_inspectedViewParentWindow = nullptr;
264 }
265
266 String WebInspectorProxy::inspectorPageURL()
267 {
268     RetainPtr<CFURLRef> htmlURLRef = adoptCF(CFBundleCopyResourceURL(WebCore::webKitBundle(), CFSTR("Main"), CFSTR("html"), CFSTR("WebInspectorUI")));
269     return CFURLGetString(htmlURLRef.get());
270 }
271
272 String WebInspectorProxy::inspectorTestPageURL()
273 {
274     RetainPtr<CFURLRef> htmlURLRef = adoptCF(CFBundleCopyResourceURL(WebCore::webKitBundle(), CFSTR("Test"), CFSTR("html"), CFSTR("WebInspectorUI")));
275     return CFURLGetString(htmlURLRef.get());
276 }
277
278 String WebInspectorProxy::inspectorBaseURL()
279 {
280     RetainPtr<CFURLRef> baseURLRef = adoptCF(CFBundleCopyResourceURL(WebCore::webKitBundle(), CFSTR("WebInspectorUI"), nullptr, nullptr));
281     return CFURLGetString(baseURLRef.get());
282 }
283
284 unsigned WebInspectorProxy::platformInspectedWindowHeight()
285 {
286     RECT rect;
287     ::GetClientRect(m_inspectedViewWindow, &rect);
288     return rect.bottom - rect.top;
289 }
290
291 unsigned WebInspectorProxy::platformInspectedWindowWidth()
292 {
293     RECT rect;
294     ::GetClientRect(m_inspectedViewWindow, &rect);
295     return rect.right - rect.left;
296 }
297
298 void WebInspectorProxy::platformAttach()
299 {
300     static const unsigned defaultAttachedSize = 300;
301     static const unsigned minimumAttachedWidth = 750;
302     static const unsigned minimumAttachedHeight = 250;
303
304     unsigned inspectedHeight = platformInspectedWindowHeight();
305     unsigned inspectedWidth = platformInspectedWindowWidth();
306
307     if (m_inspectorDetachWindow && ::GetParent(m_inspectorViewWindow) == m_inspectorDetachWindow) {
308         ::SetParent(m_inspectorViewWindow, m_inspectedViewParentWindow);
309         ::ShowWindow(m_inspectorDetachWindow, SW_HIDE);
310     }
311
312     WebCore::WindowMessageBroadcaster::addListener(m_inspectedViewWindow, this);
313
314     if (m_attachmentSide == AttachmentSide::Bottom) {
315         unsigned maximumAttachedHeight = platformInspectedWindowHeight() * 3 / 4;
316         platformSetAttachedWindowHeight(std::max(minimumAttachedHeight, std::min(defaultAttachedSize, maximumAttachedHeight)));
317     } else {
318         unsigned maximumAttachedWidth = platformInspectedWindowWidth() * 3 / 4;
319         platformSetAttachedWindowWidth(std::max(minimumAttachedWidth, std::min(defaultAttachedSize, maximumAttachedWidth)));
320     }
321     ::ShowWindow(m_inspectorViewWindow, SW_SHOW);
322 }
323
324 void WebInspectorProxy::platformDetach()
325 {
326     if (!inspectedPage()->isValid())
327         return;
328
329     if (!m_inspectorDetachWindow) {
330         static bool haveRegisteredClass = false;
331         registerWindowClass();
332         m_inspectorDetachWindow = ::CreateWindowEx(0, WebInspectorProxyClassName, 0, WS_OVERLAPPEDWINDOW,
333             CW_USEDEFAULT, CW_USEDEFAULT, initialWindowWidth, initialWindowHeight,
334             0, 0, WebCore::instanceHandle(), 0);
335         ::SetProp(m_inspectorDetachWindow, WebInspectorProxyPointerProp, reinterpret_cast<HANDLE>(this));
336     }
337
338     WebCore::WindowMessageBroadcaster::removeListener(m_inspectedViewWindow, this);
339
340     RECT rect;
341     ::GetClientRect(m_inspectorDetachWindow, &rect);
342     auto windowInfo = getInspectedWindowInfo(m_inspectedViewWindow, m_inspectedViewParentWindow);
343     ::SetParent(m_inspectorViewWindow, m_inspectorDetachWindow);
344     ::SetWindowPos(m_inspectorViewWindow, 0, 0, 0, rect.right - rect.left, rect.bottom - rect.top, SWP_NOZORDER);
345     ::SetWindowPos(m_inspectedViewWindow, 0, windowInfo.left, windowInfo.top, windowInfo.parentWidth - windowInfo.left, windowInfo.parentHeight - windowInfo.top, SWP_NOZORDER);
346
347     if (m_isVisible)
348         ::ShowWindow(m_inspectorDetachWindow, SW_SHOW);
349 }
350
351 void WebInspectorProxy::platformSetAttachedWindowHeight(unsigned height)
352 {
353     auto windowInfo = getInspectedWindowInfo(m_inspectedViewWindow, m_inspectedViewParentWindow);
354     ::SetWindowPos(m_inspectorViewWindow, 0, windowInfo.left, windowInfo.parentHeight - height, windowInfo.parentWidth - windowInfo.left, height, SWP_NOZORDER);
355     ::SetWindowPos(m_inspectedViewWindow, 0, windowInfo.left, windowInfo.top, windowInfo.parentWidth - windowInfo.left, windowInfo.parentHeight - windowInfo.top, SWP_NOZORDER);
356 }
357
358 void WebInspectorProxy::platformSetAttachedWindowWidth(unsigned width)
359 {
360     auto windowInfo = getInspectedWindowInfo(m_inspectedViewWindow, m_inspectedViewParentWindow);
361     ::SetWindowPos(m_inspectorViewWindow, 0, windowInfo.parentWidth - width, windowInfo.top, width, windowInfo.parentHeight - windowInfo.top, SWP_NOZORDER);
362     ::SetWindowPos(m_inspectedViewWindow, 0, windowInfo.left, windowInfo.top, windowInfo.parentWidth - windowInfo.left, windowInfo.parentHeight - windowInfo.top, SWP_NOZORDER);
363 }
364
365 bool WebInspectorProxy::platformIsFront()
366 {
367     notImplemented();
368     return false;
369 }
370
371 void WebInspectorProxy::platformHide()
372 {
373     notImplemented();
374 }
375
376 void WebInspectorProxy::platformBringToFront()
377 {
378     notImplemented();
379 }
380
381 void WebInspectorProxy::platformBringInspectedPageToFront()
382 {
383     notImplemented();
384 }
385
386 void WebInspectorProxy::platformInspectedURLChanged(const String& /* url */)
387 {
388     notImplemented();
389 }
390
391 void WebInspectorProxy::platformShowCertificate(const WebCore::CertificateInfo&)
392 {
393     notImplemented();
394 }
395
396 void WebInspectorProxy::platformSave(const String&, const String&, bool, bool)
397 {
398     notImplemented();
399 }
400
401 void WebInspectorProxy::platformAppend(const String&, const String&)
402 {
403     notImplemented();
404 }
405
406 void WebInspectorProxy::platformAttachAvailabilityChanged(bool /* available */)
407 {
408     notImplemented();
409 }
410
411 void WebInspectorProxy::platformCreateFrontendWindow()
412 {
413     platformDetach();
414 }
415
416 void WebInspectorProxy::platformDidCloseForCrash()
417 {
418     notImplemented();
419 }
420
421 void WebInspectorProxy::platformInvalidate()
422 {
423     notImplemented();
424 }
425
426 void WebInspectorProxy::platformStartWindowDrag()
427 {
428     notImplemented();
429 }
430
431 }