1/*
2 * Copyright (C) 2011, 2012 Igalia S.L.
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public License
15 * along with this library; see the file COPYING.LIB. If not, write to
16 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18 */
19
20#include "config.h"
21#include "WebKitUIClient.h"
22
23#include "APIUIClient.h"
24#include "DrawingAreaProxy.h"
25#include "WebKitDeviceInfoPermissionRequestPrivate.h"
26#include "WebKitFileChooserRequestPrivate.h"
27#include "WebKitGeolocationPermissionRequestPrivate.h"
28#include "WebKitNavigationActionPrivate.h"
29#include "WebKitNotificationPermissionRequestPrivate.h"
30#include "WebKitURIRequestPrivate.h"
31#include "WebKitUserMediaPermissionRequestPrivate.h"
32#include "WebKitWebViewPrivate.h"
33#include "WebKitWindowPropertiesPrivate.h"
34#include "WebPageProxy.h"
35#include "WebProcessProxy.h"
36#include "WebsiteDataStore.h"
37#include <wtf/glib/GRefPtr.h>
38
39#if PLATFORM(GTK)
40#include <WebCore/GtkUtilities.h>
41#endif
42
43using namespace WebKit;
44
45class UIClient : public API::UIClient {
46public:
47 explicit UIClient(WebKitWebView* webView)
48 : m_webView(webView)
49 {
50 }
51
52private:
53 void createNewPage(WebPageProxy& page, WebCore::WindowFeatures&& windowFeatures, Ref<API::NavigationAction>&& apiNavigationAction, CompletionHandler<void(RefPtr<WebPageProxy>&&)>&& completionHandler) final
54 {
55 WebKitNavigationAction navigationAction(WTFMove(apiNavigationAction));
56 completionHandler(webkitWebViewCreateNewPage(m_webView, windowFeatures, &navigationAction));
57 }
58
59 void showPage(WebPageProxy*) final
60 {
61 webkitWebViewReadyToShowPage(m_webView);
62 }
63
64 void close(WebPageProxy*) final
65 {
66 webkitWebViewClosePage(m_webView);
67 }
68
69 void runJavaScriptAlert(WebPageProxy*, const String& message, WebFrameProxy*, const WebCore::SecurityOriginData&, Function<void()>&& completionHandler) final
70 {
71 webkitWebViewRunJavaScriptAlert(m_webView, message.utf8(), WTFMove(completionHandler));
72 }
73
74 void runJavaScriptConfirm(WebPageProxy*, const String& message, WebFrameProxy*, const WebCore::SecurityOriginData&, Function<void(bool)>&& completionHandler) final
75 {
76 webkitWebViewRunJavaScriptConfirm(m_webView, message.utf8(), WTFMove(completionHandler));
77 }
78
79 void runJavaScriptPrompt(WebPageProxy*, const String& message, const String& defaultValue, WebFrameProxy*, const WebCore::SecurityOriginData&, Function<void(const String&)>&& completionHandler) final
80 {
81 webkitWebViewRunJavaScriptPrompt(m_webView, message.utf8(), defaultValue.utf8(), WTFMove(completionHandler));
82 }
83
84 bool canRunBeforeUnloadConfirmPanel() const final { return true; }
85
86 void runBeforeUnloadConfirmPanel(WebPageProxy*, const String& message, WebFrameProxy*, const WebCore::SecurityOriginData&, Function<void(bool)>&& completionHandler) final
87 {
88 webkitWebViewRunJavaScriptBeforeUnloadConfirm(m_webView, message.utf8(), WTFMove(completionHandler));
89 }
90
91 void mouseDidMoveOverElement(WebPageProxy&, const WebHitTestResultData& data, OptionSet<WebEvent::Modifier> modifiers, API::Object*) final
92 {
93 webkitWebViewMouseTargetChanged(m_webView, data, modifiers);
94 }
95
96 void toolbarsAreVisible(WebPageProxy&, Function<void(bool)>&& completionHandler) final
97 {
98 completionHandler(webkit_window_properties_get_toolbar_visible(webkit_web_view_get_window_properties(m_webView)));
99 }
100
101 void setToolbarsAreVisible(WebPageProxy&, bool visible) final
102 {
103 webkitWindowPropertiesSetToolbarVisible(webkit_web_view_get_window_properties(m_webView), visible);
104 }
105
106 void menuBarIsVisible(WebPageProxy&, Function<void(bool)>&& completionHandler) final
107 {
108 completionHandler(webkit_window_properties_get_menubar_visible(webkit_web_view_get_window_properties(m_webView)));
109 }
110
111 void setMenuBarIsVisible(WebPageProxy&, bool visible) final
112 {
113 webkitWindowPropertiesSetToolbarVisible(webkit_web_view_get_window_properties(m_webView), visible);
114 }
115
116 void statusBarIsVisible(WebPageProxy&, Function<void(bool)>&& completionHandler) final
117 {
118 completionHandler(webkit_window_properties_get_statusbar_visible(webkit_web_view_get_window_properties(m_webView)));
119 }
120
121 void setStatusBarIsVisible(WebPageProxy&, bool visible) final
122 {
123 webkitWindowPropertiesSetStatusbarVisible(webkit_web_view_get_window_properties(m_webView), visible);
124 }
125
126 void setIsResizable(WebPageProxy&, bool resizable) final
127 {
128 webkitWindowPropertiesSetResizable(webkit_web_view_get_window_properties(m_webView), resizable);
129 }
130
131 void setWindowFrame(WebPageProxy&, const WebCore::FloatRect& frame) final
132 {
133#if PLATFORM(GTK)
134 GdkRectangle geometry = WebCore::IntRect(frame);
135 GtkWidget* window = gtk_widget_get_toplevel(GTK_WIDGET(m_webView));
136 if (webkit_web_view_is_controlled_by_automation(m_webView) && WebCore::widgetIsOnscreenToplevelWindow(window) && gtk_widget_get_visible(window)) {
137 if (geometry.x >= 0 && geometry.y >= 0)
138 gtk_window_move(GTK_WINDOW(window), geometry.x, geometry.y);
139 if (geometry.width > 0 && geometry.height > 0)
140 gtk_window_resize(GTK_WINDOW(window), geometry.width, geometry.height);
141 } else
142 webkitWindowPropertiesSetGeometry(webkit_web_view_get_window_properties(m_webView), &geometry);
143#endif
144 }
145
146 void windowFrame(WebPageProxy&, Function<void(WebCore::FloatRect)>&& completionHandler) final
147 {
148#if PLATFORM(GTK)
149 GdkRectangle geometry = { 0, 0, 0, 0 };
150 GtkWidget* window = gtk_widget_get_toplevel(GTK_WIDGET(m_webView));
151 if (WebCore::widgetIsOnscreenToplevelWindow(window) && gtk_widget_get_visible(window)) {
152 gtk_window_get_position(GTK_WINDOW(window), &geometry.x, &geometry.y);
153 gtk_window_get_size(GTK_WINDOW(window), &geometry.width, &geometry.height);
154 }
155 completionHandler(WebCore::FloatRect(geometry));
156#elif PLATFORM(WPE)
157 // FIXME: I guess this is actually the view size in WPE. We need more refactoring here.
158 WebCore::FloatRect rect;
159 auto& page = webkitWebViewGetPage(m_webView);
160 if (page.drawingArea())
161 rect.setSize(page.drawingArea()->size());
162 completionHandler(WTFMove(rect));
163#endif
164 }
165
166 void exceededDatabaseQuota(WebPageProxy*, WebFrameProxy*, API::SecurityOrigin*, const String&, const String&, unsigned long long /*currentQuota*/, unsigned long long /*currentOriginUsage*/, unsigned long long /*currentDatabaseUsage*/, unsigned long long /*expectedUsage*/, Function<void(unsigned long long)>&& completionHandler) final
167 {
168 static const unsigned long long defaultQuota = 5 * 1024 * 1204; // 5 MB
169 // FIXME: Provide API for this.
170 completionHandler(defaultQuota);
171 }
172
173 bool runOpenPanel(WebPageProxy*, WebFrameProxy*, const WebCore::SecurityOriginData&, API::OpenPanelParameters* parameters, WebOpenPanelResultListenerProxy* listener) final
174 {
175 GRefPtr<WebKitFileChooserRequest> request = adoptGRef(webkitFileChooserRequestCreate(parameters, listener));
176 webkitWebViewRunFileChooserRequest(m_webView, request.get());
177 return true;
178 }
179
180 void decidePolicyForGeolocationPermissionRequest(WebPageProxy&, WebFrameProxy&, API::SecurityOrigin&, Function<void(bool)>& completionHandler) final
181 {
182 GRefPtr<WebKitGeolocationPermissionRequest> geolocationPermissionRequest = adoptGRef(webkitGeolocationPermissionRequestCreate(GeolocationPermissionRequest::create(std::exchange(completionHandler, nullptr)).ptr()));
183 webkitWebViewMakePermissionRequest(m_webView, WEBKIT_PERMISSION_REQUEST(geolocationPermissionRequest.get()));
184 }
185
186 void decidePolicyForUserMediaPermissionRequest(WebPageProxy&, WebFrameProxy&, API::SecurityOrigin& userMediaDocumentOrigin, API::SecurityOrigin& topLevelDocumentOrigin, UserMediaPermissionRequestProxy& permissionRequest) final
187 {
188 GRefPtr<WebKitUserMediaPermissionRequest> userMediaPermissionRequest = adoptGRef(webkitUserMediaPermissionRequestCreate(permissionRequest, userMediaDocumentOrigin, topLevelDocumentOrigin));
189 webkitWebViewMakePermissionRequest(m_webView, WEBKIT_PERMISSION_REQUEST(userMediaPermissionRequest.get()));
190 }
191
192 void checkUserMediaPermissionForOrigin(WebPageProxy& page, WebFrameProxy&, API::SecurityOrigin& userMediaDocumentOrigin, API::SecurityOrigin& topLevelDocumentOrigin, UserMediaPermissionCheckProxy& permissionRequest) override
193 {
194 auto deviceInfoPermissionRequest = adoptGRef(webkitDeviceInfoPermissionRequestCreate(permissionRequest, &page.websiteDataStore().deviceIdHashSaltStorage()));
195 webkitWebViewMakePermissionRequest(m_webView, WEBKIT_PERMISSION_REQUEST(deviceInfoPermissionRequest.get()));
196 }
197
198 void decidePolicyForNotificationPermissionRequest(WebPageProxy&, API::SecurityOrigin&, Function<void(bool)>&& completionHandler) final
199 {
200 GRefPtr<WebKitNotificationPermissionRequest> notificationPermissionRequest = adoptGRef(webkitNotificationPermissionRequestCreate(NotificationPermissionRequest::create(WTFMove(completionHandler)).ptr()));
201 webkitWebViewMakePermissionRequest(m_webView, WEBKIT_PERMISSION_REQUEST(notificationPermissionRequest.get()));
202 }
203
204#if PLATFORM(GTK)
205 void printFrame(WebPageProxy&, WebFrameProxy& frame) final
206 {
207 webkitWebViewPrintFrame(m_webView, &frame);
208 }
209#endif
210
211 bool canRunModal() const final { return true; }
212
213 void runModal(WebPageProxy&) final
214 {
215 webkitWebViewRunAsModal(m_webView);
216 }
217
218 void isPlayingMediaDidChange(WebPageProxy&) final
219 {
220 webkitWebViewIsPlayingAudioChanged(m_webView);
221 }
222
223 WebKitWebView* m_webView;
224};
225
226void attachUIClientToView(WebKitWebView* webView)
227{
228 webkitWebViewGetPage(webView).setUIClient(std::make_unique<UIClient>(webView));
229}
230
231