e687311525f2414e04b580575a07d3d3dea353aa
[WebKit-https.git] / Source / WebKit / UIProcess / API / glib / WebKitWebView.cpp
1 /*
2  * Copyright (C) 2011 Igalia S.L.
3  * Portions Copyright (c) 2011 Motorola Mobility, Inc.  All rights reserved.
4  * Copyright (C) 2014 Collabora Ltd.
5  * Copyright (C) 2017 Igalia S.L.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public License
18  * along with this library; see the file COPYING.LIB.  If not, write to
19  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20  * Boston, MA 02110-1301, USA.
21  */
22
23 #include "config.h"
24 #include "WebKitWebView.h"
25
26 #include "APIData.h"
27 #include "APINavigation.h"
28 #include "APISerializedScriptValue.h"
29 #include "DataReference.h"
30 #include "ImageOptions.h"
31 #include "WebCertificateInfo.h"
32 #include "WebContextMenuItem.h"
33 #include "WebContextMenuItemData.h"
34 #include "WebKitAuthenticationRequestPrivate.h"
35 #include "WebKitBackForwardListPrivate.h"
36 #include "WebKitContextMenuClient.h"
37 #include "WebKitContextMenuItemPrivate.h"
38 #include "WebKitContextMenuPrivate.h"
39 #include "WebKitDownloadPrivate.h"
40 #include "WebKitEditingCommands.h"
41 #include "WebKitEditorStatePrivate.h"
42 #include "WebKitEnumTypes.h"
43 #include "WebKitError.h"
44 #include "WebKitFaviconDatabasePrivate.h"
45 #include "WebKitFormClient.h"
46 #include "WebKitHitTestResultPrivate.h"
47 #include "WebKitIconLoadingClient.h"
48 #include "WebKitInstallMissingMediaPluginsPermissionRequestPrivate.h"
49 #include "WebKitJavascriptResultPrivate.h"
50 #include "WebKitNavigationClient.h"
51 #include "WebKitNotificationPrivate.h"
52 #include "WebKitPrivate.h"
53 #include "WebKitResponsePolicyDecision.h"
54 #include "WebKitScriptDialogPrivate.h"
55 #include "WebKitSettingsPrivate.h"
56 #include "WebKitUIClient.h"
57 #include "WebKitURIRequestPrivate.h"
58 #include "WebKitURIResponsePrivate.h"
59 #include "WebKitWebContextPrivate.h"
60 #include "WebKitWebResourcePrivate.h"
61 #include "WebKitWebViewPrivate.h"
62 #include "WebKitWebViewSessionStatePrivate.h"
63 #include "WebKitWebsiteDataManagerPrivate.h"
64 #include "WebKitWindowPropertiesPrivate.h"
65 #include <JavaScriptCore/APICast.h>
66 #include <JavaScriptCore/JSRetainPtr.h>
67 #include <jsc/JSCContextPrivate.h>
68 #include <WebCore/CertificateInfo.h>
69 #include <WebCore/GUniquePtrSoup.h>
70 #include <WebCore/JSDOMExceptionHandling.h>
71 #include <WebCore/RefPtrCairo.h>
72 #include <WebCore/URL.h>
73 #include <glib/gi18n-lib.h>
74 #include <wtf/SetForScope.h>
75 #include <wtf/glib/GRefPtr.h>
76 #include <wtf/glib/WTFGType.h>
77 #include <wtf/text/CString.h>
78 #include <wtf/text/StringBuilder.h>
79
80 #if PLATFORM(GTK)
81 #include "WebKitPrintOperationPrivate.h"
82 #include "WebKitWebInspectorPrivate.h"
83 #include "WebKitWebViewBasePrivate.h"
84 #include <WebCore/GUniquePtrGtk.h>
85 #endif
86
87 #if PLATFORM(WPE)
88 #include "APIViewClient.h"
89 #include "WPEView.h"
90 #include "WebKitWebViewBackendPrivate.h"
91 #endif
92
93 #if USE(LIBNOTIFY)
94 #include <libnotify/notify.h>
95 #endif
96
97 using namespace WebKit;
98 using namespace WebCore;
99
100 /**
101  * SECTION: WebKitWebView
102  * @Short_description: The central class of the WebKit2GTK+ API
103  * @Title: WebKitWebView
104  *
105  * #WebKitWebView is the central class of the WebKit2GTK+ API. It is
106  * responsible for managing the drawing of the content and forwarding
107  * of events. You can load any URI into the #WebKitWebView or a data
108  * string. With #WebKitSettings you can control various aspects of the
109  * rendering and loading of the content.
110  *
111  * Note that #WebKitWebView is scrollable by itself, so you don't need
112  * to embed it in a #GtkScrolledWindow.
113  */
114
115 enum {
116     LOAD_CHANGED,
117     LOAD_FAILED,
118     LOAD_FAILED_WITH_TLS_ERRORS,
119
120     CREATE,
121     READY_TO_SHOW,
122     RUN_AS_MODAL,
123     CLOSE,
124
125     SCRIPT_DIALOG,
126
127     DECIDE_POLICY,
128     PERMISSION_REQUEST,
129
130     MOUSE_TARGET_CHANGED,
131
132 #if PLATFORM(GTK)
133     PRINT,
134 #endif
135
136     RESOURCE_LOAD_STARTED,
137
138     ENTER_FULLSCREEN,
139     LEAVE_FULLSCREEN,
140
141     RUN_FILE_CHOOSER,
142
143     CONTEXT_MENU,
144     CONTEXT_MENU_DISMISSED,
145
146     SUBMIT_FORM,
147
148     INSECURE_CONTENT_DETECTED,
149
150 #if PLATFORM(GTK)
151     WEB_PROCESS_CRASHED,
152 #endif
153     WEB_PROCESS_TERMINATED,
154
155     AUTHENTICATE,
156
157     SHOW_NOTIFICATION,
158
159 #if PLATFORM(GTK)
160     RUN_COLOR_CHOOSER,
161
162     SHOW_OPTION_MENU,
163 #endif
164
165     LAST_SIGNAL
166 };
167
168 enum {
169     PROP_0,
170
171 #if PLATFORM(WPE)
172     PROP_BACKEND,
173 #endif
174
175     PROP_WEB_CONTEXT,
176     PROP_RELATED_VIEW,
177     PROP_SETTINGS,
178     PROP_USER_CONTENT_MANAGER,
179     PROP_TITLE,
180     PROP_ESTIMATED_LOAD_PROGRESS,
181
182 #if PLATFORM(GTK)
183     PROP_FAVICON,
184 #endif
185
186     PROP_URI,
187     PROP_ZOOM_LEVEL,
188     PROP_IS_LOADING,
189     PROP_IS_PLAYING_AUDIO,
190     PROP_IS_EPHEMERAL,
191     PROP_IS_CONTROLLED_BY_AUTOMATION,
192     PROP_EDITABLE
193 };
194
195 typedef HashMap<uint64_t, GRefPtr<WebKitWebResource> > LoadingResourcesMap;
196 typedef HashMap<uint64_t, GRefPtr<GTask> > SnapshotResultsMap;
197
198 class PageLoadStateObserver;
199
200 struct _WebKitWebViewPrivate {
201     ~_WebKitWebViewPrivate()
202     {
203         // For modal dialogs, make sure the main loop is stopped when finalizing the webView.
204         if (modalLoop && g_main_loop_is_running(modalLoop.get()))
205             g_main_loop_quit(modalLoop.get());
206     }
207
208 #if PLATFORM(WPE)
209     GRefPtr<WebKitWebViewBackend> backend;
210     std::unique_ptr<WKWPE::View> view;
211 #endif
212
213     WebKitWebView* relatedView;
214     CString title;
215     CString customTextEncoding;
216     CString activeURI;
217     bool isLoading;
218     bool isEphemeral;
219     bool isControlledByAutomation;
220
221     std::unique_ptr<PageLoadStateObserver> loadObserver;
222
223     GRefPtr<WebKitBackForwardList> backForwardList;
224     GRefPtr<WebKitSettings> settings;
225     GRefPtr<WebKitUserContentManager> userContentManager;
226     GRefPtr<WebKitWebContext> context;
227     GRefPtr<WebKitWindowProperties> windowProperties;
228     GRefPtr<WebKitEditorState> editorState;
229
230     GRefPtr<GMainLoop> modalLoop;
231
232     GRefPtr<WebKitHitTestResult> mouseTargetHitTestResult;
233     WebEvent::Modifiers mouseTargetModifiers;
234
235     GRefPtr<WebKitFindController> findController;
236
237     GRefPtr<WebKitWebResource> mainResource;
238     LoadingResourcesMap loadingResourcesMap;
239
240     WebKitScriptDialog* currentScriptDialog;
241
242 #if PLATFORM(GTK)
243     GRefPtr<JSCContext> jsContext;
244
245     GRefPtr<WebKitWebInspector> inspector;
246
247     RefPtr<cairo_surface_t> favicon;
248     GRefPtr<GCancellable> faviconCancellable;
249
250     CString faviconURI;
251     unsigned long faviconChangedHandlerID;
252
253     SnapshotResultsMap snapshotResultsMap;
254 #endif
255
256     GRefPtr<WebKitAuthenticationRequest> authenticationRequest;
257
258     GRefPtr<WebKitWebsiteDataManager> websiteDataManager;
259 };
260
261 static guint signals[LAST_SIGNAL] = { 0, };
262
263 #if PLATFORM(GTK)
264 WEBKIT_DEFINE_TYPE(WebKitWebView, webkit_web_view, WEBKIT_TYPE_WEB_VIEW_BASE)
265 #elif PLATFORM(WPE)
266 WEBKIT_DEFINE_TYPE(WebKitWebView, webkit_web_view, G_TYPE_OBJECT)
267 #endif
268
269 static inline WebPageProxy& getPage(WebKitWebView* webView)
270 {
271 #if PLATFORM(GTK)
272     auto* page = webkitWebViewBaseGetPage(reinterpret_cast<WebKitWebViewBase*>(webView));
273     ASSERT(page);
274     return *page;
275 #elif PLATFORM(WPE)
276     ASSERT(webView->priv->view);
277     return webView->priv->view->page();
278 #endif
279 }
280
281 static void webkitWebViewSetIsLoading(WebKitWebView* webView, bool isLoading)
282 {
283     if (webView->priv->isLoading == isLoading)
284         return;
285
286     webView->priv->isLoading = isLoading;
287     g_object_notify(G_OBJECT(webView), "is-loading");
288 }
289
290 void webkitWebViewIsPlayingAudioChanged(WebKitWebView* webView)
291 {
292     g_object_notify(G_OBJECT(webView), "is-playing-audio");
293 }
294
295 class PageLoadStateObserver final : public PageLoadState::Observer {
296 public:
297     PageLoadStateObserver(WebKitWebView* webView)
298         : m_webView(webView)
299     {
300     }
301
302 private:
303     void willChangeIsLoading() override
304     {
305         g_object_freeze_notify(G_OBJECT(m_webView));
306     }
307     void didChangeIsLoading() override
308     {
309         webkitWebViewSetIsLoading(m_webView, getPage(m_webView).pageLoadState().isLoading());
310         g_object_thaw_notify(G_OBJECT(m_webView));
311     }
312
313     void willChangeTitle() override
314     {
315         g_object_freeze_notify(G_OBJECT(m_webView));
316     }
317     void didChangeTitle() override
318     {
319         m_webView->priv->title = getPage(m_webView).pageLoadState().title().utf8();
320         g_object_notify(G_OBJECT(m_webView), "title");
321         g_object_thaw_notify(G_OBJECT(m_webView));
322     }
323
324     void willChangeActiveURL() override
325     {
326         g_object_freeze_notify(G_OBJECT(m_webView));
327     }
328     void didChangeActiveURL() override
329     {
330         m_webView->priv->activeURI = getPage(m_webView).pageLoadState().activeURL().utf8();
331         g_object_notify(G_OBJECT(m_webView), "uri");
332         g_object_thaw_notify(G_OBJECT(m_webView));
333     }
334
335     void willChangeHasOnlySecureContent() override { }
336     void didChangeHasOnlySecureContent() override { }
337
338     void willChangeEstimatedProgress() override
339     {
340         g_object_freeze_notify(G_OBJECT(m_webView));
341     }
342     void didChangeEstimatedProgress() override
343     {
344         g_object_notify(G_OBJECT(m_webView), "estimated-load-progress");
345         g_object_thaw_notify(G_OBJECT(m_webView));
346     }
347
348     void willChangeCanGoBack() override { }
349     void didChangeCanGoBack() override { }
350     void willChangeCanGoForward() override { }
351     void didChangeCanGoForward() override { }
352     void willChangeNetworkRequestsInProgress() override { }
353     void didChangeNetworkRequestsInProgress() override { }
354     void willChangeCertificateInfo() override { }
355     void didChangeCertificateInfo() override { }
356     void willChangeWebProcessIsResponsive() override { }
357     void didChangeWebProcessIsResponsive() override { }
358
359     WebKitWebView* m_webView;
360 };
361
362 #if PLATFORM(WPE)
363 class WebViewClient final : public API::ViewClient {
364 public:
365     explicit WebViewClient(WebKitWebView* webView)
366         : m_webView(webView)
367     {
368     }
369
370 private:
371     void handleDownloadRequest(WKWPE::View&, DownloadProxy& downloadProxy) override
372     {
373         webkitWebViewHandleDownloadRequest(m_webView, &downloadProxy);
374     }
375
376     WebKitWebView* m_webView;
377 };
378 #endif
379
380 static gboolean webkitWebViewLoadFail(WebKitWebView* webView, WebKitLoadEvent, const char* failingURI, GError* error)
381 {
382     if (g_error_matches(error, WEBKIT_NETWORK_ERROR, WEBKIT_NETWORK_ERROR_CANCELLED)
383         || g_error_matches(error, WEBKIT_POLICY_ERROR, WEBKIT_POLICY_ERROR_FRAME_LOAD_INTERRUPTED_BY_POLICY_CHANGE)
384         || g_error_matches(error, WEBKIT_PLUGIN_ERROR, WEBKIT_PLUGIN_ERROR_WILL_HANDLE_LOAD))
385         return FALSE;
386
387     GUniquePtr<char> htmlString(g_strdup_printf("<html><body>%s</body></html>", error->message));
388     webkit_web_view_load_alternate_html(webView, htmlString.get(), failingURI, 0);
389
390     return TRUE;
391 }
392
393 #if PLATFORM(GTK)
394 static GtkWidget* webkitWebViewCreate(WebKitWebView*, WebKitNavigationAction*)
395 {
396     return nullptr;
397 }
398 #else
399 static WebKitWebView* webkitWebViewCreate(WebKitWebView*, WebKitNavigationAction*)
400 {
401     return nullptr;
402 }
403 #endif
404
405 static gboolean webkitWebViewDecidePolicy(WebKitWebView*, WebKitPolicyDecision* decision, WebKitPolicyDecisionType decisionType)
406 {
407     if (decisionType != WEBKIT_POLICY_DECISION_TYPE_RESPONSE) {
408         webkit_policy_decision_use(decision);
409         return TRUE;
410     }
411
412     WebKitURIResponse* response = webkit_response_policy_decision_get_response(WEBKIT_RESPONSE_POLICY_DECISION(decision));
413     const ResourceResponse& resourceResponse = webkitURIResponseGetResourceResponse(response);
414     if (resourceResponse.isAttachment()) {
415         webkit_policy_decision_download(decision);
416         return TRUE;
417     }
418
419     if (webkit_response_policy_decision_is_mime_type_supported(WEBKIT_RESPONSE_POLICY_DECISION(decision)))
420         webkit_policy_decision_use(decision);
421     else
422         webkit_policy_decision_ignore(decision);
423
424     return TRUE;
425 }
426
427 static gboolean webkitWebViewPermissionRequest(WebKitWebView*, WebKitPermissionRequest* request)
428 {
429     webkit_permission_request_deny(request);
430     return TRUE;
431 }
432
433 static void allowModalDialogsChanged(WebKitSettings* settings, GParamSpec*, WebKitWebView* webView)
434 {
435     getPage(webView).setCanRunModal(webkit_settings_get_allow_modal_dialogs(settings));
436 }
437
438 static void zoomTextOnlyChanged(WebKitSettings* settings, GParamSpec*, WebKitWebView* webView)
439 {
440     auto& page = getPage(webView);
441     gboolean zoomTextOnly = webkit_settings_get_zoom_text_only(settings);
442     gdouble pageZoomLevel = zoomTextOnly ? 1 : page.textZoomFactor();
443     gdouble textZoomLevel = zoomTextOnly ? page.pageZoomFactor() : 1;
444     page.setPageAndTextZoomFactors(pageZoomLevel, textZoomLevel);
445 }
446
447 static void userAgentChanged(WebKitSettings* settings, GParamSpec*, WebKitWebView* webView)
448 {
449     getPage(webView).setCustomUserAgent(String::fromUTF8(webkit_settings_get_user_agent(settings)));
450 }
451
452 #if PLATFORM(GTK)
453 static void webkitWebViewUpdateFavicon(WebKitWebView* webView, cairo_surface_t* favicon)
454 {
455     WebKitWebViewPrivate* priv = webView->priv;
456     if (priv->favicon.get() == favicon)
457         return;
458
459     priv->favicon = favicon;
460     g_object_notify(G_OBJECT(webView), "favicon");
461 }
462
463 static void webkitWebViewCancelFaviconRequest(WebKitWebView* webView)
464 {
465     if (!webView->priv->faviconCancellable)
466         return;
467
468     g_cancellable_cancel(webView->priv->faviconCancellable.get());
469     webView->priv->faviconCancellable = 0;
470 }
471
472 static void gotFaviconCallback(GObject* object, GAsyncResult* result, gpointer userData)
473 {
474     GUniqueOutPtr<GError> error;
475     RefPtr<cairo_surface_t> favicon = adoptRef(webkit_favicon_database_get_favicon_finish(WEBKIT_FAVICON_DATABASE(object), result, &error.outPtr()));
476     if (g_error_matches(error.get(), G_IO_ERROR, G_IO_ERROR_CANCELLED))
477         return;
478
479     WebKitWebView* webView = WEBKIT_WEB_VIEW(userData);
480     webkitWebViewUpdateFavicon(webView, favicon.get());
481     webView->priv->faviconCancellable = 0;
482 }
483
484 static void webkitWebViewRequestFavicon(WebKitWebView* webView)
485 {
486     webkitWebViewCancelFaviconRequest(webView);
487
488     WebKitWebViewPrivate* priv = webView->priv;
489     priv->faviconCancellable = adoptGRef(g_cancellable_new());
490     WebKitFaviconDatabase* database = webkit_web_context_get_favicon_database(priv->context.get());
491     webkit_favicon_database_get_favicon(database, priv->activeURI.data(), priv->faviconCancellable.get(), gotFaviconCallback, webView);
492 }
493
494 static void webkitWebViewUpdateFaviconURI(WebKitWebView* webView, const char* faviconURI)
495 {
496     if (webView->priv->faviconURI == faviconURI)
497         return;
498
499     webView->priv->faviconURI = faviconURI;
500     webkitWebViewRequestFavicon(webView);
501 }
502
503 static void faviconChangedCallback(WebKitFaviconDatabase*, const char* pageURI, const char* faviconURI, WebKitWebView* webView)
504 {
505     if (webView->priv->activeURI != pageURI)
506         return;
507
508     webkitWebViewUpdateFaviconURI(webView, faviconURI);
509 }
510 #endif
511
512 static bool webkitWebViewIsConstructed(WebKitWebView* webView)
513 {
514     // The loadObserver is set in webkitWebViewConstructed, right after the
515     // WebPageProxy is created, so we use it to check if the view has been
516     // constructed instead of adding a boolean member only for that.
517     return !!webView->priv->loadObserver;
518 }
519
520 static void webkitWebViewUpdateSettings(WebKitWebView* webView)
521 {
522     // The "settings" property is set on construction, and in that
523     // case webkit_web_view_set_settings() will be called *before* the
524     // WebPageProxy has been created so we should do an early return.
525     if (!webkitWebViewIsConstructed(webView))
526         return;
527
528     auto& page = getPage(webView);
529     WebKitSettings* settings = webView->priv->settings.get();
530     page.setPreferences(*webkitSettingsGetPreferences(settings));
531     page.setCanRunModal(webkit_settings_get_allow_modal_dialogs(settings));
532     page.setCustomUserAgent(String::fromUTF8(webkit_settings_get_user_agent(settings)));
533
534     g_signal_connect(settings, "notify::allow-modal-dialogs", G_CALLBACK(allowModalDialogsChanged), webView);
535     g_signal_connect(settings, "notify::zoom-text-only", G_CALLBACK(zoomTextOnlyChanged), webView);
536     g_signal_connect(settings, "notify::user-agent", G_CALLBACK(userAgentChanged), webView);
537 }
538
539 static void webkitWebViewDisconnectSettingsSignalHandlers(WebKitWebView* webView)
540 {
541     if (!webkitWebViewIsConstructed(webView))
542         return;
543
544     WebKitSettings* settings = webView->priv->settings.get();
545     g_signal_handlers_disconnect_by_func(settings, reinterpret_cast<gpointer>(allowModalDialogsChanged), webView);
546     g_signal_handlers_disconnect_by_func(settings, reinterpret_cast<gpointer>(zoomTextOnlyChanged), webView);
547     g_signal_handlers_disconnect_by_func(settings, reinterpret_cast<gpointer>(userAgentChanged), webView);
548 }
549
550 #if PLATFORM(GTK)
551 static void webkitWebViewWatchForChangesInFavicon(WebKitWebView* webView)
552 {
553     WebKitWebViewPrivate* priv = webView->priv;
554     if (priv->faviconChangedHandlerID)
555         return;
556
557     WebKitFaviconDatabase* database = webkit_web_context_get_favicon_database(priv->context.get());
558     priv->faviconChangedHandlerID = g_signal_connect(database, "favicon-changed", G_CALLBACK(faviconChangedCallback), webView);
559 }
560
561 static void webkitWebViewDisconnectFaviconDatabaseSignalHandlers(WebKitWebView* webView)
562 {
563     WebKitWebViewPrivate* priv = webView->priv;
564     if (priv->faviconChangedHandlerID)
565         g_signal_handler_disconnect(webkit_web_context_get_favicon_database(priv->context.get()), priv->faviconChangedHandlerID);
566     priv->faviconChangedHandlerID = 0;
567 }
568 #endif
569
570 #if USE(LIBNOTIFY)
571 static const char* gNotifyNotificationID = "wk-notify-notification";
572
573 static void notifyNotificationClosed(NotifyNotification*, WebKitNotification* webNotification)
574 {
575     g_object_set_data(G_OBJECT(webNotification), gNotifyNotificationID, nullptr);
576     webkit_notification_close(webNotification);
577 }
578
579 static void notifyNotificationClicked(NotifyNotification*, char*, WebKitNotification* webNotification)
580 {
581     webkit_notification_clicked(webNotification);
582 }
583
584 static void webNotificationClosed(WebKitNotification* webNotification)
585 {
586     NotifyNotification* notification = NOTIFY_NOTIFICATION(g_object_get_data(G_OBJECT(webNotification), gNotifyNotificationID));
587     if (!notification)
588         return;
589
590     notify_notification_close(notification, nullptr);
591     g_object_set_data(G_OBJECT(webNotification), gNotifyNotificationID, nullptr);
592 }
593 #endif // USE(LIBNOTIFY)
594
595 static gboolean webkitWebViewShowNotification(WebKitWebView*, WebKitNotification* webNotification)
596 {
597 #if USE(LIBNOTIFY)
598     if (!notify_is_initted())
599         notify_init(g_get_prgname());
600
601     NotifyNotification* notification = NOTIFY_NOTIFICATION(g_object_get_data(G_OBJECT(webNotification), gNotifyNotificationID));
602     if (!notification) {
603         notification = notify_notification_new(webkit_notification_get_title(webNotification),
604             webkit_notification_get_body(webNotification), nullptr);
605
606         notify_notification_add_action(notification, "default", _("Acknowledge"), NOTIFY_ACTION_CALLBACK(notifyNotificationClicked), webNotification, nullptr);
607
608         g_signal_connect_object(notification, "closed", G_CALLBACK(notifyNotificationClosed), webNotification, static_cast<GConnectFlags>(0));
609         g_signal_connect(webNotification, "closed", G_CALLBACK(webNotificationClosed), nullptr);
610         g_object_set_data_full(G_OBJECT(webNotification), gNotifyNotificationID, notification, static_cast<GDestroyNotify>(g_object_unref));
611     } else {
612         notify_notification_update(notification, webkit_notification_get_title(webNotification),
613             webkit_notification_get_body(webNotification), nullptr);
614     }
615
616     notify_notification_show(notification, nullptr);
617     return TRUE;
618 #else
619     UNUSED_PARAM(webNotification);
620     return FALSE;
621 #endif
622 }
623
624 static void webkitWebViewConstructed(GObject* object)
625 {
626     G_OBJECT_CLASS(webkit_web_view_parent_class)->constructed(object);
627
628     WebKitWebView* webView = WEBKIT_WEB_VIEW(object);
629     WebKitWebViewPrivate* priv = webView->priv;
630     if (priv->relatedView) {
631         priv->context = webkit_web_view_get_context(priv->relatedView);
632         priv->isEphemeral = webkit_web_view_is_ephemeral(priv->relatedView);
633         priv->isControlledByAutomation = webkit_web_view_is_controlled_by_automation(priv->relatedView);
634     } else if (!priv->context)
635         priv->context = webkit_web_context_get_default();
636     else if (!priv->isEphemeral)
637         priv->isEphemeral = webkit_web_context_is_ephemeral(priv->context.get());
638
639     if (!priv->settings)
640         priv->settings = adoptGRef(webkit_settings_new());
641
642     if (!priv->userContentManager)
643         priv->userContentManager = adoptGRef(webkit_user_content_manager_new());
644
645     if (priv->isEphemeral && !webkit_web_context_is_ephemeral(priv->context.get())) {
646         priv->websiteDataManager = adoptGRef(webkit_website_data_manager_new_ephemeral());
647         webkitWebsiteDataManagerAddProcessPool(priv->websiteDataManager.get(), webkitWebContextGetProcessPool(priv->context.get()));
648     }
649
650     webkitWebContextCreatePageForWebView(priv->context.get(), webView, priv->userContentManager.get(), priv->relatedView);
651
652     priv->loadObserver = std::make_unique<PageLoadStateObserver>(webView);
653     getPage(webView).pageLoadState().addObserver(*priv->loadObserver);
654
655     // The related view is only valid during the construction.
656     priv->relatedView = nullptr;
657
658     attachNavigationClientToView(webView);
659     attachUIClientToView(webView);
660     attachContextMenuClientToView(webView);
661     attachFormClientToView(webView);
662
663 #if PLATFORM(GTK)
664     attachIconLoadingClientToView(webView);
665 #endif
666
667 #if PLATFORM(WPE)
668     priv->view->setClient(std::make_unique<WebViewClient>(webView));
669 #endif
670
671     // This needs to be after attachUIClientToView() because WebPageProxy::setUIClient() calls setCanRunModal() with true.
672     // See https://bugs.webkit.org/show_bug.cgi?id=135412.
673     webkitWebViewUpdateSettings(webView);
674
675     priv->backForwardList = adoptGRef(webkitBackForwardListCreate(&getPage(webView).backForwardList()));
676     priv->windowProperties = adoptGRef(webkitWindowPropertiesCreate());
677 }
678
679 static void webkitWebViewSetProperty(GObject* object, guint propId, const GValue* value, GParamSpec* paramSpec)
680 {
681     WebKitWebView* webView = WEBKIT_WEB_VIEW(object);
682
683     switch (propId) {
684 #if PLATFORM(WPE)
685     case PROP_BACKEND: {
686         gpointer backend = g_value_get_boxed(value);
687         webView->priv->backend = backend ? adoptGRef(static_cast<WebKitWebViewBackend*>(backend)) : nullptr;
688         break;
689     }
690 #endif
691     case PROP_WEB_CONTEXT: {
692         gpointer webContext = g_value_get_object(value);
693         webView->priv->context = webContext ? WEBKIT_WEB_CONTEXT(webContext) : nullptr;
694         break;
695     }
696     case PROP_RELATED_VIEW: {
697         gpointer relatedView = g_value_get_object(value);
698         webView->priv->relatedView = relatedView ? WEBKIT_WEB_VIEW(relatedView) : nullptr;
699         break;
700     }
701     case PROP_SETTINGS: {
702         if (gpointer settings = g_value_get_object(value))
703             webkit_web_view_set_settings(webView, WEBKIT_SETTINGS(settings));
704         break;
705     }
706     case PROP_USER_CONTENT_MANAGER: {
707         gpointer userContentManager = g_value_get_object(value);
708         webView->priv->userContentManager = userContentManager ? WEBKIT_USER_CONTENT_MANAGER(userContentManager) : nullptr;
709         break;
710     }
711     case PROP_ZOOM_LEVEL:
712         webkit_web_view_set_zoom_level(webView, g_value_get_double(value));
713         break;
714     case PROP_IS_EPHEMERAL:
715         webView->priv->isEphemeral = g_value_get_boolean(value);
716         break;
717     case PROP_IS_CONTROLLED_BY_AUTOMATION:
718         webView->priv->isControlledByAutomation = g_value_get_boolean(value);
719         break;
720     case PROP_EDITABLE:
721         webkit_web_view_set_editable(webView, g_value_get_boolean(value));
722         break;
723     default:
724         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propId, paramSpec);
725     }
726 }
727
728 static void webkitWebViewGetProperty(GObject* object, guint propId, GValue* value, GParamSpec* paramSpec)
729 {
730     WebKitWebView* webView = WEBKIT_WEB_VIEW(object);
731
732     switch (propId) {
733 #if PLATFORM(WPE)
734     case PROP_BACKEND:
735         g_value_set_static_boxed(value, webView->priv->backend.get());
736         break;
737 #endif
738     case PROP_WEB_CONTEXT:
739         g_value_set_object(value, webView->priv->context.get());
740         break;
741     case PROP_SETTINGS:
742         g_value_set_object(value, webkit_web_view_get_settings(webView));
743         break;
744     case PROP_USER_CONTENT_MANAGER:
745         g_value_set_object(value, webkit_web_view_get_user_content_manager(webView));
746         break;
747     case PROP_TITLE:
748         g_value_set_string(value, webView->priv->title.data());
749         break;
750     case PROP_ESTIMATED_LOAD_PROGRESS:
751         g_value_set_double(value, webkit_web_view_get_estimated_load_progress(webView));
752         break;
753 #if PLATFORM(GTK)
754     case PROP_FAVICON:
755         g_value_set_pointer(value, webkit_web_view_get_favicon(webView));
756         break;
757 #endif
758     case PROP_URI:
759         g_value_set_string(value, webkit_web_view_get_uri(webView));
760         break;
761     case PROP_ZOOM_LEVEL:
762         g_value_set_double(value, webkit_web_view_get_zoom_level(webView));
763         break;
764     case PROP_IS_LOADING:
765         g_value_set_boolean(value, webkit_web_view_is_loading(webView));
766         break;
767     case PROP_IS_PLAYING_AUDIO:
768         g_value_set_boolean(value, webkit_web_view_is_playing_audio(webView));
769         break;
770     case PROP_IS_EPHEMERAL:
771         g_value_set_boolean(value, webkit_web_view_is_ephemeral(webView));
772         break;
773     case PROP_IS_CONTROLLED_BY_AUTOMATION:
774         g_value_set_boolean(value, webkit_web_view_is_controlled_by_automation(webView));
775         break;
776     case PROP_EDITABLE:
777         g_value_set_boolean(value, webkit_web_view_is_editable(webView));
778         break;
779     default:
780         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propId, paramSpec);
781     }
782 }
783
784 static void webkitWebViewDispose(GObject* object)
785 {
786     WebKitWebView* webView = WEBKIT_WEB_VIEW(object);
787
788 #if PLATFORM(GTK)
789     webkitWebViewCancelFaviconRequest(webView);
790     webkitWebViewDisconnectFaviconDatabaseSignalHandlers(webView);
791 #endif
792
793     webkitWebViewDisconnectSettingsSignalHandlers(webView);
794
795     if (webView->priv->loadObserver) {
796         getPage(webView).pageLoadState().removeObserver(*webView->priv->loadObserver);
797         webView->priv->loadObserver.reset();
798
799         // We notify the context here to ensure it's called only once. Ideally we should
800         // call this in finalize, not dispose, but finalize is used internally and we don't
801         // have access to the instance pointer from the private struct destructor.
802         webkitWebContextWebViewDestroyed(webView->priv->context.get(), webView);
803     }
804
805     if (webView->priv->websiteDataManager) {
806         webkitWebsiteDataManagerRemoveProcessPool(webView->priv->websiteDataManager.get(), webkitWebContextGetProcessPool(webView->priv->context.get()));
807         webView->priv->websiteDataManager = nullptr;
808     }
809
810 #if PLATFORM(WPE)
811     webView->priv->view->close();
812 #endif
813
814     G_OBJECT_CLASS(webkit_web_view_parent_class)->dispose(object);
815 }
816
817 static gboolean webkitWebViewAccumulatorObjectHandled(GSignalInvocationHint*, GValue* returnValue, const GValue* handlerReturn, gpointer)
818 {
819     void* object = g_value_get_object(handlerReturn);
820     if (object)
821         g_value_set_object(returnValue, object);
822
823     return !object;
824 }
825
826 static void webkit_web_view_class_init(WebKitWebViewClass* webViewClass)
827 {
828     GObjectClass* gObjectClass = G_OBJECT_CLASS(webViewClass);
829
830     gObjectClass->constructed = webkitWebViewConstructed;
831     gObjectClass->set_property = webkitWebViewSetProperty;
832     gObjectClass->get_property = webkitWebViewGetProperty;
833     gObjectClass->dispose = webkitWebViewDispose;
834
835     webViewClass->load_failed = webkitWebViewLoadFail;
836     webViewClass->create = webkitWebViewCreate;
837     webViewClass->script_dialog = webkitWebViewScriptDialog;
838     webViewClass->decide_policy = webkitWebViewDecidePolicy;
839     webViewClass->permission_request = webkitWebViewPermissionRequest;
840     webViewClass->run_file_chooser = webkitWebViewRunFileChooser;
841     webViewClass->authenticate = webkitWebViewAuthenticate;
842     webViewClass->show_notification = webkitWebViewShowNotification;
843
844 #if PLATFORM(WPE)
845     /**
846      * WebKitWebView:backend:
847      *
848      * The #WebKitWebViewBackend of the view.
849      *
850      * since: 2.20
851      */
852     g_object_class_install_property(
853         gObjectClass,
854         PROP_BACKEND,
855         g_param_spec_boxed(
856             "backend",
857             _("Backend"),
858             _("The backend for the web view"),
859             WEBKIT_TYPE_WEB_VIEW_BACKEND,
860             static_cast<GParamFlags>(WEBKIT_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)));
861 #endif
862
863     /**
864      * WebKitWebView:web-context:
865      *
866      * The #WebKitWebContext of the view.
867      */
868     g_object_class_install_property(gObjectClass,
869                                     PROP_WEB_CONTEXT,
870                                     g_param_spec_object("web-context",
871                                                         _("Web Context"),
872                                                         _("The web context for the view"),
873                                                         WEBKIT_TYPE_WEB_CONTEXT,
874                                                         static_cast<GParamFlags>(WEBKIT_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)));
875     /**
876      * WebKitWebView:related-view:
877      *
878      * The related #WebKitWebView used when creating the view to share the
879      * same web process. This property is not readable because the related
880      * web view is only valid during the object construction.
881      *
882      * Since: 2.4
883      */
884     g_object_class_install_property(
885         gObjectClass,
886         PROP_RELATED_VIEW,
887         g_param_spec_object(
888             "related-view",
889             _("Related WebView"),
890             _("The related WebKitWebView used when creating the view to share the same web process"),
891             WEBKIT_TYPE_WEB_VIEW,
892             static_cast<GParamFlags>(WEBKIT_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)));
893
894     /**
895      * WebKitWebView:settings:
896      *
897      * The #WebKitSettings of the view.
898      *
899      * Since: 2.6
900      */
901     g_object_class_install_property(
902         gObjectClass,
903         PROP_SETTINGS,
904         g_param_spec_object(
905             "settings",
906             _("WebView settings"),
907             _("The WebKitSettings of the view"),
908             WEBKIT_TYPE_SETTINGS,
909             static_cast<GParamFlags>(WEBKIT_PARAM_WRITABLE | G_PARAM_CONSTRUCT)));
910
911     /**
912      * WebKitWebView:user-content-manager:
913      *
914      * The #WebKitUserContentManager of the view.
915      *
916      * Since: 2.6
917      */
918     g_object_class_install_property(
919         gObjectClass,
920         PROP_USER_CONTENT_MANAGER,
921         g_param_spec_object(
922             "user-content-manager",
923             _("WebView user content manager"),
924             _("The WebKitUserContentManager of the view"),
925             WEBKIT_TYPE_USER_CONTENT_MANAGER,
926             static_cast<GParamFlags>(WEBKIT_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)));
927
928     /**
929      * WebKitWebView:title:
930      *
931      * The main frame document title of this #WebKitWebView. If
932      * the title has not been received yet, it will be %NULL.
933      */
934     g_object_class_install_property(gObjectClass,
935                                     PROP_TITLE,
936                                     g_param_spec_string("title",
937                                                         _("Title"),
938                                                         _("Main frame document title"),
939                                                         0,
940                                                         WEBKIT_PARAM_READABLE));
941
942     /**
943      * WebKitWebView:estimated-load-progress:
944      *
945      * An estimate of the percent completion for the current loading operation.
946      * This value will range from 0.0 to 1.0 and, once a load completes,
947      * will remain at 1.0 until a new load starts, at which point it
948      * will be reset to 0.0.
949      * The value is an estimate based on the total number of bytes expected
950      * to be received for a document, including all its possible subresources
951      * and child documents.
952      */
953     g_object_class_install_property(gObjectClass,
954                                     PROP_ESTIMATED_LOAD_PROGRESS,
955                                     g_param_spec_double("estimated-load-progress",
956                                                         _("Estimated Load Progress"),
957                                                         _("An estimate of the percent completion for a document load"),
958                                                         0.0, 1.0, 0.0,
959                                                         WEBKIT_PARAM_READABLE));
960 #if PLATFORM(GTK)
961     /**
962      * WebKitWebView:favicon:
963      *
964      * The favicon currently associated to the #WebKitWebView.
965      * See webkit_web_view_get_favicon() for more details.
966      */
967     g_object_class_install_property(gObjectClass,
968                                     PROP_FAVICON,
969                                     g_param_spec_pointer("favicon",
970                                                          _("Favicon"),
971                                                          _("The favicon associated to the view, if any"),
972                                                          WEBKIT_PARAM_READABLE));
973 #endif
974
975     /**
976      * WebKitWebView:uri:
977      *
978      * The current active URI of the #WebKitWebView.
979      * See webkit_web_view_get_uri() for more details.
980      */
981     g_object_class_install_property(gObjectClass,
982                                     PROP_URI,
983                                     g_param_spec_string("uri",
984                                                         _("URI"),
985                                                         _("The current active URI of the view"),
986                                                         0,
987                                                         WEBKIT_PARAM_READABLE));
988
989     /**
990      * WebKitWebView:zoom-level:
991      *
992      * The zoom level of the #WebKitWebView content.
993      * See webkit_web_view_set_zoom_level() for more details.
994      */
995     g_object_class_install_property(
996         gObjectClass,
997         PROP_ZOOM_LEVEL,
998         g_param_spec_double(
999             "zoom-level",
1000             _("Zoom level"),
1001             _("The zoom level of the view content"),
1002             0, G_MAXDOUBLE, 1,
1003             WEBKIT_PARAM_READWRITE));
1004
1005     /**
1006      * WebKitWebView:is-loading:
1007      *
1008      * Whether the #WebKitWebView is currently loading a page. This property becomes
1009      * %TRUE as soon as a new load operation is requested and before the
1010      * #WebKitWebView::load-changed signal is emitted with %WEBKIT_LOAD_STARTED and
1011      * at that point the active URI is the requested one.
1012      * When the load operation finishes the property is set to %FALSE before
1013      * #WebKitWebView::load-changed is emitted with %WEBKIT_LOAD_FINISHED.
1014      */
1015     g_object_class_install_property(
1016         gObjectClass,
1017         PROP_IS_LOADING,
1018         g_param_spec_boolean(
1019             "is-loading",
1020             _("Is Loading"),
1021             _("Whether the view is loading a page"),
1022             FALSE,
1023             WEBKIT_PARAM_READABLE));
1024
1025     /**
1026      * WebKitWebView:is-playing-audio:
1027      *
1028      * Whether the #WebKitWebView is currently playing audio from a page.
1029      * This property becomes %TRUE as soon as web content starts playing any
1030      * kind of audio. When a page is no longer playing any kind of sound,
1031      * the property is set back to %FALSE.
1032      *
1033      * Since: 2.8
1034      */
1035     g_object_class_install_property(
1036         gObjectClass,
1037         PROP_IS_PLAYING_AUDIO,
1038         g_param_spec_boolean(
1039             "is-playing-audio",
1040             "Is Playing Audio",
1041             _("Whether the view is playing audio"),
1042             FALSE,
1043             WEBKIT_PARAM_READABLE));
1044
1045     /**
1046      * WebKitWebView:is-ephemeral:
1047      *
1048      * Whether the #WebKitWebView is ephemeral. An ephemeral web view never writes
1049      * website data to the client storage, no matter what #WebKitWebsiteDataManager
1050      * its context is using. This is normally used to implement private browsing mode.
1051      * This is a %G_PARAM_CONSTRUCT_ONLY property, so you have to create a ephemeral
1052      * #WebKitWebView and it can't be changed. Note that all #WebKitWebView<!-- -->s
1053      * created with an ephemeral #WebKitWebContext will be ephemeral automatically.
1054      * See also webkit_web_context_new_ephemeral().
1055      *
1056      * Since: 2.16
1057      */
1058     g_object_class_install_property(
1059         gObjectClass,
1060         PROP_IS_EPHEMERAL,
1061         g_param_spec_boolean(
1062             "is-ephemeral",
1063             "Is Ephemeral",
1064             _("Whether the web view is ephemeral"),
1065             FALSE,
1066             static_cast<GParamFlags>(WEBKIT_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)));
1067
1068     /**
1069      * WebKitWebView:is-controlled-by-automation:
1070      *
1071      * Whether the #WebKitWebView is controlled by automation. This should only be used when
1072      * creating a new #WebKitWebView as a response to #WebKitAutomationSession::create-web-view
1073      * signal request.
1074      *
1075      * Since: 2.18
1076      */
1077     g_object_class_install_property(
1078         gObjectClass,
1079         PROP_IS_CONTROLLED_BY_AUTOMATION,
1080         g_param_spec_boolean(
1081             "is-controlled-by-automation",
1082             "Is Controlled By Automation",
1083             _("Whether the web view is controlled by automation"),
1084             FALSE,
1085             static_cast<GParamFlags>(WEBKIT_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)));
1086
1087     /**
1088      * WebKitWebView:editable:
1089      *
1090      * Whether the pages loaded inside #WebKitWebView are editable. For more
1091      * information see webkit_web_view_set_editable().
1092      *
1093      * Since: 2.8
1094      */
1095     g_object_class_install_property(
1096         gObjectClass,
1097         PROP_EDITABLE,
1098         g_param_spec_boolean(
1099             "editable",
1100             _("Editable"),
1101             _("Whether the content can be modified by the user."),
1102             FALSE,
1103             WEBKIT_PARAM_READWRITE));
1104
1105     /**
1106      * WebKitWebView::load-changed:
1107      * @web_view: the #WebKitWebView on which the signal is emitted
1108      * @load_event: the #WebKitLoadEvent
1109      *
1110      * Emitted when a load operation in @web_view changes.
1111      * The signal is always emitted with %WEBKIT_LOAD_STARTED when a
1112      * new load request is made and %WEBKIT_LOAD_FINISHED when the load
1113      * finishes successfully or due to an error. When the ongoing load
1114      * operation fails #WebKitWebView::load-failed signal is emitted
1115      * before #WebKitWebView::load-changed is emitted with
1116      * %WEBKIT_LOAD_FINISHED.
1117      * If a redirection is received from the server, this signal is emitted
1118      * with %WEBKIT_LOAD_REDIRECTED after the initial emission with
1119      * %WEBKIT_LOAD_STARTED and before %WEBKIT_LOAD_COMMITTED.
1120      * When the page content starts arriving the signal is emitted with
1121      * %WEBKIT_LOAD_COMMITTED event.
1122      *
1123      * You can handle this signal and use a switch to track any ongoing
1124      * load operation.
1125      *
1126      * <informalexample><programlisting>
1127      * static void web_view_load_changed (WebKitWebView  *web_view,
1128      *                                    WebKitLoadEvent load_event,
1129      *                                    gpointer        user_data)
1130      * {
1131      *     switch (load_event) {
1132      *     case WEBKIT_LOAD_STARTED:
1133      *         /<!-- -->* New load, we have now a provisional URI *<!-- -->/
1134      *         provisional_uri = webkit_web_view_get_uri (web_view);
1135      *         /<!-- -->* Here we could start a spinner or update the
1136      *          <!-- -->* location bar with the provisional URI *<!-- -->/
1137      *         break;
1138      *     case WEBKIT_LOAD_REDIRECTED:
1139      *         redirected_uri = webkit_web_view_get_uri (web_view);
1140      *         break;
1141      *     case WEBKIT_LOAD_COMMITTED:
1142      *         /<!-- -->* The load is being performed. Current URI is
1143      *          <!-- -->* the final one and it won't change unless a new
1144      *          <!-- -->* load is requested or a navigation within the
1145      *          <!-- -->* same page is performed *<!-- -->/
1146      *         uri = webkit_web_view_get_uri (web_view);
1147      *         break;
1148      *     case WEBKIT_LOAD_FINISHED:
1149      *         /<!-- -->* Load finished, we can now stop the spinner *<!-- -->/
1150      *         break;
1151      *     }
1152      * }
1153      * </programlisting></informalexample>
1154      */
1155     signals[LOAD_CHANGED] =
1156         g_signal_new("load-changed",
1157                      G_TYPE_FROM_CLASS(webViewClass),
1158                      G_SIGNAL_RUN_LAST,
1159                      G_STRUCT_OFFSET(WebKitWebViewClass, load_changed),
1160                      0, 0,
1161                      g_cclosure_marshal_VOID__ENUM,
1162                      G_TYPE_NONE, 1,
1163                      WEBKIT_TYPE_LOAD_EVENT);
1164
1165     /**
1166      * WebKitWebView::load-failed:
1167      * @web_view: the #WebKitWebView on which the signal is emitted
1168      * @load_event: the #WebKitLoadEvent of the load operation
1169      * @failing_uri: the URI that failed to load
1170      * @error: the #GError that was triggered
1171      *
1172      * Emitted when an error occurs during a load operation.
1173      * If the error happened when starting to load data for a page
1174      * @load_event will be %WEBKIT_LOAD_STARTED. If it happened while
1175      * loading a committed data source @load_event will be %WEBKIT_LOAD_COMMITTED.
1176      * Since a load error causes the load operation to finish, the signal
1177      * WebKitWebView::load-changed will always be emitted with
1178      * %WEBKIT_LOAD_FINISHED event right after this one.
1179      *
1180      * By default, if the signal is not handled, a stock error page will be displayed.
1181      * You need to handle the signal if you want to provide your own error page.
1182      *
1183      * Returns: %TRUE to stop other handlers from being invoked for the event.
1184      *    %FALSE to propagate the event further.
1185      */
1186     signals[LOAD_FAILED] =
1187         g_signal_new(
1188             "load-failed",
1189             G_TYPE_FROM_CLASS(webViewClass),
1190             G_SIGNAL_RUN_LAST,
1191             G_STRUCT_OFFSET(WebKitWebViewClass, load_failed),
1192             g_signal_accumulator_true_handled, 0,
1193             g_cclosure_marshal_generic,
1194             G_TYPE_BOOLEAN, 3,
1195             WEBKIT_TYPE_LOAD_EVENT,
1196             G_TYPE_STRING,
1197             G_TYPE_ERROR | G_SIGNAL_TYPE_STATIC_SCOPE);
1198
1199     /**
1200      * WebKitWebView::load-failed-with-tls-errors:
1201      * @web_view: the #WebKitWebView on which the signal is emitted
1202      * @failing_uri: the URI that failed to load
1203      * @certificate: a #GTlsCertificate
1204      * @errors: a #GTlsCertificateFlags with the verification status of @certificate
1205      *
1206      * Emitted when a TLS error occurs during a load operation.
1207      * To allow an exception for this @certificate
1208      * and the host of @failing_uri use webkit_web_context_allow_tls_certificate_for_host().
1209      *
1210      * To handle this signal asynchronously you should call g_object_ref() on @certificate
1211      * and return %TRUE.
1212      *
1213      * If %FALSE is returned, #WebKitWebView::load-failed will be emitted. The load
1214      * will finish regardless of the returned value.
1215      *
1216      * Returns: %TRUE to stop other handlers from being invoked for the event.
1217      *   %FALSE to propagate the event further.
1218      *
1219      * Since: 2.6
1220      */
1221     signals[LOAD_FAILED_WITH_TLS_ERRORS] =
1222         g_signal_new("load-failed-with-tls-errors",
1223             G_TYPE_FROM_CLASS(webViewClass),
1224             G_SIGNAL_RUN_LAST,
1225             G_STRUCT_OFFSET(WebKitWebViewClass, load_failed_with_tls_errors),
1226             g_signal_accumulator_true_handled, 0 /* accumulator data */,
1227             g_cclosure_marshal_generic,
1228             G_TYPE_BOOLEAN, 3,
1229             G_TYPE_STRING,
1230             G_TYPE_TLS_CERTIFICATE,
1231             G_TYPE_TLS_CERTIFICATE_FLAGS);
1232
1233     /**
1234      * WebKitWebView::create:
1235      * @web_view: the #WebKitWebView on which the signal is emitted
1236      * @navigation_action: a #WebKitNavigationAction
1237      *
1238      * Emitted when the creation of a new #WebKitWebView is requested.
1239      * If this signal is handled the signal handler should return the
1240      * newly created #WebKitWebView.
1241      *
1242      * The #WebKitNavigationAction parameter contains information about the
1243      * navigation action that triggered this signal.
1244      *
1245      * When using %WEBKIT_PROCESS_MODEL_MULTIPLE_SECONDARY_PROCESSES
1246      * process model, the new #WebKitWebView should be related to
1247      * @web_view to share the same web process, see webkit_web_view_new_with_related_view()
1248      * for more details.
1249      *
1250      * The new #WebKitWebView should not be displayed to the user
1251      * until the #WebKitWebView::ready-to-show signal is emitted.
1252      *
1253      * Returns: (transfer full): a newly allocated #WebKitWebView widget
1254      *    or %NULL to propagate the event further.
1255      */
1256     signals[CREATE] = g_signal_new(
1257         "create",
1258         G_TYPE_FROM_CLASS(webViewClass),
1259         G_SIGNAL_RUN_LAST,
1260         G_STRUCT_OFFSET(WebKitWebViewClass, create),
1261         webkitWebViewAccumulatorObjectHandled, 0,
1262         g_cclosure_marshal_generic,
1263 #if PLATFORM(GTK)
1264         GTK_TYPE_WIDGET,
1265 #else
1266         WEBKIT_TYPE_WEB_VIEW,
1267 #endif
1268         1,
1269         WEBKIT_TYPE_NAVIGATION_ACTION | G_SIGNAL_TYPE_STATIC_SCOPE);
1270
1271     /**
1272      * WebKitWebView::ready-to-show:
1273      * @web_view: the #WebKitWebView on which the signal is emitted
1274      *
1275      * Emitted after #WebKitWebView::create on the newly created #WebKitWebView
1276      * when it should be displayed to the user. When this signal is emitted
1277      * all the information about how the window should look, including
1278      * size, position, whether the location, status and scrollbars
1279      * should be displayed, is already set on the #WebKitWindowProperties
1280      * of @web_view. See also webkit_web_view_get_window_properties().
1281      */
1282     signals[READY_TO_SHOW] =
1283         g_signal_new("ready-to-show",
1284                      G_TYPE_FROM_CLASS(webViewClass),
1285                      G_SIGNAL_RUN_LAST,
1286                      G_STRUCT_OFFSET(WebKitWebViewClass, ready_to_show),
1287                      0, 0,
1288                      g_cclosure_marshal_VOID__VOID,
1289                      G_TYPE_NONE, 0);
1290
1291      /**
1292      * WebKitWebView::run-as-modal:
1293      * @web_view: the #WebKitWebView on which the signal is emitted
1294      *
1295      * Emitted after #WebKitWebView::ready-to-show on the newly
1296      * created #WebKitWebView when JavaScript code calls
1297      * <function>window.showModalDialog</function>. The purpose of
1298      * this signal is to allow the client application to prepare the
1299      * new view to behave as modal. Once the signal is emitted a new
1300      * main loop will be run to block user interaction in the parent
1301      * #WebKitWebView until the new dialog is closed.
1302      */
1303     signals[RUN_AS_MODAL] =
1304             g_signal_new("run-as-modal",
1305                          G_TYPE_FROM_CLASS(webViewClass),
1306                          G_SIGNAL_RUN_LAST,
1307                          G_STRUCT_OFFSET(WebKitWebViewClass, run_as_modal),
1308                          0, 0,
1309                          g_cclosure_marshal_VOID__VOID,
1310                          G_TYPE_NONE, 0);
1311
1312     /**
1313      * WebKitWebView::close:
1314      * @web_view: the #WebKitWebView on which the signal is emitted
1315      *
1316      * Emitted when closing a #WebKitWebView is requested. This occurs when a
1317      * call is made from JavaScript's <function>window.close</function> function or
1318      * after trying to close the @web_view with webkit_web_view_try_close().
1319      * It is the owner's responsibility to handle this signal to hide or
1320      * destroy the #WebKitWebView, if necessary.
1321      */
1322     signals[CLOSE] =
1323         g_signal_new("close",
1324                      G_TYPE_FROM_CLASS(webViewClass),
1325                      G_SIGNAL_RUN_LAST,
1326                      G_STRUCT_OFFSET(WebKitWebViewClass, close),
1327                      0, 0,
1328                      g_cclosure_marshal_VOID__VOID,
1329                      G_TYPE_NONE, 0);
1330
1331     /**
1332      * WebKitWebView::script-dialog:
1333      * @web_view: the #WebKitWebView on which the signal is emitted
1334      * @dialog: the #WebKitScriptDialog to show
1335      *
1336      * Emitted when JavaScript code calls <function>window.alert</function>,
1337      * <function>window.confirm</function> or <function>window.prompt</function>,
1338      * or when <function>onbeforeunload</function> event is fired.
1339      * The @dialog parameter should be used to build the dialog.
1340      * If the signal is not handled a different dialog will be built and shown depending
1341      * on the dialog type:
1342      * <itemizedlist>
1343      * <listitem><para>
1344      *  %WEBKIT_SCRIPT_DIALOG_ALERT: message dialog with a single Close button.
1345      * </para></listitem>
1346      * <listitem><para>
1347      *  %WEBKIT_SCRIPT_DIALOG_CONFIRM: message dialog with OK and Cancel buttons.
1348      * </para></listitem>
1349      * <listitem><para>
1350      *  %WEBKIT_SCRIPT_DIALOG_PROMPT: message dialog with OK and Cancel buttons and
1351      *  a text entry with the default text.
1352      * </para></listitem>
1353      * <listitem><para>
1354      *  %WEBKIT_SCRIPT_DIALOG_BEFORE_UNLOAD_CONFIRM: message dialog with Stay and Leave buttons.
1355      * </para></listitem>
1356      * </itemizedlist>
1357      *
1358      * Returns: %TRUE to stop other handlers from being invoked for the event.
1359      *    %FALSE to propagate the event further.
1360      */
1361     signals[SCRIPT_DIALOG] = g_signal_new(
1362         "script-dialog",
1363         G_TYPE_FROM_CLASS(webViewClass),
1364         G_SIGNAL_RUN_LAST,
1365         G_STRUCT_OFFSET(WebKitWebViewClass, script_dialog),
1366         g_signal_accumulator_true_handled, nullptr,
1367         g_cclosure_marshal_generic,
1368         G_TYPE_BOOLEAN, 1,
1369         WEBKIT_TYPE_SCRIPT_DIALOG | G_SIGNAL_TYPE_STATIC_SCOPE);
1370
1371     /**
1372      * WebKitWebView::decide-policy:
1373      * @web_view: the #WebKitWebView on which the signal is emitted
1374      * @decision: the #WebKitPolicyDecision
1375      * @decision_type: a #WebKitPolicyDecisionType denoting the type of @decision
1376      *
1377      * This signal is emitted when WebKit is requesting the client to decide a policy
1378      * decision, such as whether to navigate to a page, open a new window or whether or
1379      * not to download a resource. The #WebKitNavigationPolicyDecision passed in the
1380      * @decision argument is a generic type, but should be casted to a more
1381      * specific type when making the decision. For example:
1382      *
1383      * <informalexample><programlisting>
1384      * static gboolean
1385      * decide_policy_cb (WebKitWebView *web_view,
1386      *                   WebKitPolicyDecision *decision,
1387      *                   WebKitPolicyDecisionType type)
1388      * {
1389      *     switch (type) {
1390      *     case WEBKIT_POLICY_DECISION_TYPE_NAVIGATION_ACTION:
1391      *         WebKitNavigationPolicyDecision *navigation_decision = WEBKIT_NAVIGATION_POLICY_DECISION (decision);
1392      *         /<!-- -->* Make a policy decision here. *<!-- -->/
1393      *         break;
1394      *     case WEBKIT_POLICY_DECISION_TYPE_NEW_WINDOW_ACTION:
1395      *         WebKitNavigationPolicyDecision *navigation_decision = WEBKIT_NAVIGATION_POLICY_DECISION (decision);
1396      *         /<!-- -->* Make a policy decision here. *<!-- -->/
1397      *         break;
1398      *     case WEBKIT_POLICY_DECISION_TYPE_RESPONSE:
1399      *         WebKitResponsePolicyDecision *response = WEBKIT_RESPONSE_POLICY_DECISION (decision);
1400      *         /<!-- -->* Make a policy decision here. *<!-- -->/
1401      *         break;
1402      *     default:
1403      *         /<!-- -->* Making no decision results in webkit_policy_decision_use(). *<!-- -->/
1404      *         return FALSE;
1405      *     }
1406      *     return TRUE;
1407      * }
1408      * </programlisting></informalexample>
1409      *
1410      * It is possible to make policy decision asynchronously, by simply calling g_object_ref()
1411      * on the @decision argument and returning %TRUE to block the default signal handler.
1412      * If the last reference is removed on a #WebKitPolicyDecision and no decision has been
1413      * made explicitly, webkit_policy_decision_use() will be the default policy decision. The
1414      * default signal handler will simply call webkit_policy_decision_use(). Only the first
1415      * policy decision chosen for a given #WebKitPolicyDecision will have any affect.
1416      *
1417      * Returns: %TRUE to stop other handlers from being invoked for the event.
1418      *   %FALSE to propagate the event further.
1419      *
1420      */
1421     signals[DECIDE_POLICY] = g_signal_new(
1422         "decide-policy",
1423         G_TYPE_FROM_CLASS(webViewClass),
1424         G_SIGNAL_RUN_LAST,
1425         G_STRUCT_OFFSET(WebKitWebViewClass, decide_policy),
1426         g_signal_accumulator_true_handled, nullptr /* accumulator data */,
1427         g_cclosure_marshal_generic,
1428         G_TYPE_BOOLEAN, 2, /* number of parameters */
1429         WEBKIT_TYPE_POLICY_DECISION,
1430         WEBKIT_TYPE_POLICY_DECISION_TYPE);
1431
1432     /**
1433      * WebKitWebView::permission-request:
1434      * @web_view: the #WebKitWebView on which the signal is emitted
1435      * @request: the #WebKitPermissionRequest
1436      *
1437      * This signal is emitted when WebKit is requesting the client to
1438      * decide about a permission request, such as allowing the browser
1439      * to switch to fullscreen mode, sharing its location or similar
1440      * operations.
1441      *
1442      * A possible way to use this signal could be through a dialog
1443      * allowing the user decide what to do with the request:
1444      *
1445      * <informalexample><programlisting>
1446      * static gboolean permission_request_cb (WebKitWebView *web_view,
1447      *                                        WebKitPermissionRequest *request,
1448      *                                        GtkWindow *parent_window)
1449      * {
1450      *     GtkWidget *dialog = gtk_message_dialog_new (parent_window,
1451      *                                                 GTK_DIALOG_MODAL,
1452      *                                                 GTK_MESSAGE_QUESTION,
1453      *                                                 GTK_BUTTONS_YES_NO,
1454      *                                                 "Allow Permission Request?");
1455      *     gtk_widget_show (dialog);
1456      *     gint result = gtk_dialog_run (GTK_DIALOG (dialog));
1457      *
1458      *     switch (result) {
1459      *     case GTK_RESPONSE_YES:
1460      *         webkit_permission_request_allow (request);
1461      *         break;
1462      *     default:
1463      *         webkit_permission_request_deny (request);
1464      *         break;
1465      *     }
1466      *     gtk_widget_destroy (dialog);
1467      *
1468      *     return TRUE;
1469      * }
1470      * </programlisting></informalexample>
1471      *
1472      * It is possible to handle permission requests asynchronously, by
1473      * simply calling g_object_ref() on the @request argument and
1474      * returning %TRUE to block the default signal handler.  If the
1475      * last reference is removed on a #WebKitPermissionRequest and the
1476      * request has not been handled, webkit_permission_request_deny()
1477      * will be the default action.
1478      *
1479      * If the signal is not handled, the @request will be completed automatically
1480      * by the specific #WebKitPermissionRequest that could allow or deny it. Check the
1481      * documentation of classes implementing #WebKitPermissionRequest interface to know
1482      * their default action.
1483      *
1484      * Returns: %TRUE to stop other handlers from being invoked for the event.
1485      *   %FALSE to propagate the event further.
1486      *
1487      */
1488     signals[PERMISSION_REQUEST] = g_signal_new(
1489         "permission-request",
1490         G_TYPE_FROM_CLASS(webViewClass),
1491         G_SIGNAL_RUN_LAST,
1492         G_STRUCT_OFFSET(WebKitWebViewClass, permission_request),
1493         g_signal_accumulator_true_handled, nullptr /* accumulator data */,
1494         g_cclosure_marshal_generic,
1495         G_TYPE_BOOLEAN, 1, /* number of parameters */
1496         WEBKIT_TYPE_PERMISSION_REQUEST);
1497     /**
1498      * WebKitWebView::mouse-target-changed:
1499      * @web_view: the #WebKitWebView on which the signal is emitted
1500      * @hit_test_result: a #WebKitHitTestResult
1501      * @modifiers: a bitmask of #GdkModifierType
1502      *
1503      * This signal is emitted when the mouse cursor moves over an
1504      * element such as a link, image or a media element. To determine
1505      * what type of element the mouse cursor is over, a Hit Test is performed
1506      * on the current mouse coordinates and the result is passed in the
1507      * @hit_test_result argument. The @modifiers argument is a bitmask of
1508      * #GdkModifierType flags indicating the state of modifier keys.
1509      * The signal is emitted again when the mouse is moved out of the
1510      * current element with a new @hit_test_result.
1511      */
1512     signals[MOUSE_TARGET_CHANGED] = g_signal_new(
1513         "mouse-target-changed",
1514         G_TYPE_FROM_CLASS(webViewClass),
1515         G_SIGNAL_RUN_LAST,
1516         G_STRUCT_OFFSET(WebKitWebViewClass, mouse_target_changed),
1517         nullptr, nullptr,
1518         g_cclosure_marshal_generic,
1519         G_TYPE_NONE, 2,
1520         WEBKIT_TYPE_HIT_TEST_RESULT,
1521         G_TYPE_UINT);
1522
1523 #if PLATFORM(GTK)
1524     /**
1525      * WebKitWebView::print:
1526      * @web_view: the #WebKitWebView on which the signal is emitted
1527      * @print_operation: the #WebKitPrintOperation that will handle the print request
1528      *
1529      * Emitted when printing is requested on @web_view, usually by a JavaScript call,
1530      * before the print dialog is shown. This signal can be used to set the initial
1531      * print settings and page setup of @print_operation to be used as default values in
1532      * the print dialog. You can call webkit_print_operation_set_print_settings() and
1533      * webkit_print_operation_set_page_setup() and then return %FALSE to propagate the
1534      * event so that the print dialog is shown.
1535      *
1536      * You can connect to this signal and return %TRUE to cancel the print operation
1537      * or implement your own print dialog.
1538      *
1539      * Returns: %TRUE to stop other handlers from being invoked for the event.
1540      *    %FALSE to propagate the event further.
1541      */
1542     signals[PRINT] = g_signal_new(
1543         "print",
1544         G_TYPE_FROM_CLASS(webViewClass),
1545         G_SIGNAL_RUN_LAST,
1546         G_STRUCT_OFFSET(WebKitWebViewClass, print),
1547         g_signal_accumulator_true_handled, nullptr,
1548         g_cclosure_marshal_generic,
1549         G_TYPE_BOOLEAN, 1,
1550         WEBKIT_TYPE_PRINT_OPERATION);
1551 #endif // PLATFORM(GTK)
1552
1553     /**
1554      * WebKitWebView::resource-load-started:
1555      * @web_view: the #WebKitWebView on which the signal is emitted
1556      * @resource: a #WebKitWebResource
1557      * @request: a #WebKitURIRequest
1558      *
1559      * Emitted when a new resource is going to be loaded. The @request parameter
1560      * contains the #WebKitURIRequest that will be sent to the server.
1561      * You can monitor the load operation by connecting to the different signals
1562      * of @resource.
1563      */
1564     signals[RESOURCE_LOAD_STARTED] = g_signal_new(
1565         "resource-load-started",
1566         G_TYPE_FROM_CLASS(webViewClass),
1567         G_SIGNAL_RUN_LAST,
1568         G_STRUCT_OFFSET(WebKitWebViewClass, resource_load_started),
1569         nullptr, nullptr,
1570         g_cclosure_marshal_generic,
1571         G_TYPE_NONE, 2,
1572         WEBKIT_TYPE_WEB_RESOURCE,
1573                      WEBKIT_TYPE_URI_REQUEST);
1574
1575     /**
1576      * WebKitWebView::enter-fullscreen:
1577      * @web_view: the #WebKitWebView on which the signal is emitted.
1578      *
1579      * Emitted when JavaScript code calls
1580      * <function>element.webkitRequestFullScreen</function>. If the
1581      * signal is not handled the #WebKitWebView will proceed to full screen
1582      * its top level window. This signal can be used by client code to
1583      * request permission to the user prior doing the full screen
1584      * transition and eventually prepare the top-level window
1585      * (e.g. hide some widgets that would otherwise be part of the
1586      * full screen window).
1587      *
1588      * Returns: %TRUE to stop other handlers from being invoked for the event.
1589      *    %FALSE to continue emission of the event.
1590      */
1591     signals[ENTER_FULLSCREEN] = g_signal_new(
1592         "enter-fullscreen",
1593         G_TYPE_FROM_CLASS(webViewClass),
1594         G_SIGNAL_RUN_LAST,
1595         G_STRUCT_OFFSET(WebKitWebViewClass, enter_fullscreen),
1596         g_signal_accumulator_true_handled, nullptr,
1597         g_cclosure_marshal_generic,
1598         G_TYPE_BOOLEAN, 0);
1599
1600     /**
1601      * WebKitWebView::leave-fullscreen:
1602      * @web_view: the #WebKitWebView on which the signal is emitted.
1603      *
1604      * Emitted when the #WebKitWebView is about to restore its top level
1605      * window out of its full screen state. This signal can be used by
1606      * client code to restore widgets hidden during the
1607      * #WebKitWebView::enter-fullscreen stage for instance.
1608      *
1609      * Returns: %TRUE to stop other handlers from being invoked for the event.
1610      *    %FALSE to continue emission of the event.
1611      */
1612     signals[LEAVE_FULLSCREEN] = g_signal_new(
1613         "leave-fullscreen",
1614         G_TYPE_FROM_CLASS(webViewClass),
1615         G_SIGNAL_RUN_LAST,
1616         G_STRUCT_OFFSET(WebKitWebViewClass, leave_fullscreen),
1617         g_signal_accumulator_true_handled, nullptr,
1618         g_cclosure_marshal_generic,
1619         G_TYPE_BOOLEAN, 0);
1620
1621      /**
1622      * WebKitWebView::run-file-chooser:
1623      * @web_view: the #WebKitWebView on which the signal is emitted
1624      * @request: a #WebKitFileChooserRequest
1625      *
1626      * This signal is emitted when the user interacts with a &lt;input
1627      * type='file' /&gt; HTML element, requesting from WebKit to show
1628      * a dialog to select one or more files to be uploaded. To let the
1629      * application know the details of the file chooser, as well as to
1630      * allow the client application to either cancel the request or
1631      * perform an actual selection of files, the signal will pass an
1632      * instance of the #WebKitFileChooserRequest in the @request
1633      * argument.
1634      *
1635      * The default signal handler will asynchronously run a regular
1636      * #GtkFileChooserDialog for the user to interact with.
1637      *
1638      * Returns: %TRUE to stop other handlers from being invoked for the event.
1639      *   %FALSE to propagate the event further.
1640      *
1641      */
1642     signals[RUN_FILE_CHOOSER] = g_signal_new(
1643         "run-file-chooser",
1644         G_TYPE_FROM_CLASS(webViewClass),
1645         G_SIGNAL_RUN_LAST,
1646         G_STRUCT_OFFSET(WebKitWebViewClass, run_file_chooser),
1647         g_signal_accumulator_true_handled, nullptr /* accumulator data */,
1648         g_cclosure_marshal_generic,
1649         G_TYPE_BOOLEAN, 1, /* number of parameters */
1650         WEBKIT_TYPE_FILE_CHOOSER_REQUEST);
1651
1652     /**
1653      * WebKitWebView::context-menu:
1654      * @web_view: the #WebKitWebView on which the signal is emitted
1655      * @context_menu: the proposed #WebKitContextMenu
1656      * @event: the #GdkEvent that triggered the context menu
1657      * @hit_test_result: a #WebKitHitTestResult
1658      *
1659      * Emitted when a context menu is about to be displayed to give the application
1660      * a chance to customize the proposed menu, prevent the menu from being displayed,
1661      * or build its own context menu.
1662      * <itemizedlist>
1663      * <listitem><para>
1664      *  To customize the proposed menu you can use webkit_context_menu_prepend(),
1665      *  webkit_context_menu_append() or webkit_context_menu_insert() to add new
1666      *  #WebKitContextMenuItem<!-- -->s to @context_menu, webkit_context_menu_move_item()
1667      *  to reorder existing items, or webkit_context_menu_remove() to remove an
1668      *  existing item. The signal handler should return %FALSE, and the menu represented
1669      *  by @context_menu will be shown.
1670      * </para></listitem>
1671      * <listitem><para>
1672      *  To prevent the menu from being displayed you can just connect to this signal
1673      *  and return %TRUE so that the proposed menu will not be shown.
1674      * </para></listitem>
1675      * <listitem><para>
1676      *  To build your own menu, you can remove all items from the proposed menu with
1677      *  webkit_context_menu_remove_all(), add your own items and return %FALSE so
1678      *  that the menu will be shown. You can also ignore the proposed #WebKitContextMenu,
1679      *  build your own #GtkMenu and return %TRUE to prevent the proposed menu from being shown.
1680      * </para></listitem>
1681      * <listitem><para>
1682      *  If you just want the default menu to be shown always, simply don't connect to this
1683      *  signal because showing the proposed context menu is the default behaviour.
1684      * </para></listitem>
1685      * </itemizedlist>
1686      *
1687      * The @event is expected to be one of the following types:
1688      * <itemizedlist>
1689      * <listitem><para>
1690      * a #GdkEventButton of type %GDK_BUTTON_PRESS when the context menu
1691      * was triggered with mouse.
1692      * </para></listitem>
1693      * <listitem><para>
1694      * a #GdkEventKey of type %GDK_KEY_PRESS if the keyboard was used to show
1695      * the menu.
1696      * </para></listitem>
1697      * <listitem><para>
1698      * a generic #GdkEvent of type %GDK_NOTHING when the #GtkWidget::popup-menu
1699      * signal was used to show the context menu.
1700      * </para></listitem>
1701      * </itemizedlist>
1702      *
1703      * If the signal handler returns %FALSE the context menu represented by @context_menu
1704      * will be shown, if it return %TRUE the context menu will not be shown.
1705      *
1706      * The proposed #WebKitContextMenu passed in @context_menu argument is only valid
1707      * during the signal emission.
1708      *
1709      * Returns: %TRUE to stop other handlers from being invoked for the event.
1710      *    %FALSE to propagate the event further.
1711      */
1712     signals[CONTEXT_MENU] = g_signal_new(
1713         "context-menu",
1714         G_TYPE_FROM_CLASS(webViewClass),
1715         G_SIGNAL_RUN_LAST,
1716         G_STRUCT_OFFSET(WebKitWebViewClass, context_menu),
1717         g_signal_accumulator_true_handled, nullptr,
1718         g_cclosure_marshal_generic,
1719         G_TYPE_BOOLEAN, 3,
1720         WEBKIT_TYPE_CONTEXT_MENU,
1721 #if PLATFORM(GTK)
1722         GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE,
1723 #elif PLATFORM(WPE)
1724         G_TYPE_POINTER, // FIXME: use a wpe thing here. I'm not sure we want to expose libwpe in the API.
1725 #endif
1726         WEBKIT_TYPE_HIT_TEST_RESULT);
1727
1728     /**
1729      * WebKitWebView::context-menu-dismissed:
1730      * @web_view: the #WebKitWebView on which the signal is emitted
1731      *
1732      * Emitted after #WebKitWebView::context-menu signal, if the context menu is shown,
1733      * to notify that the context menu is dismissed.
1734      */
1735     signals[CONTEXT_MENU_DISMISSED] =
1736         g_signal_new("context-menu-dismissed",
1737                      G_TYPE_FROM_CLASS(webViewClass),
1738                      G_SIGNAL_RUN_LAST,
1739                      G_STRUCT_OFFSET(WebKitWebViewClass, context_menu_dismissed),
1740                      0, 0,
1741                      g_cclosure_marshal_VOID__VOID,
1742                      G_TYPE_NONE, 0);
1743
1744     /**
1745      * WebKitWebView::submit-form:
1746      * @web_view: the #WebKitWebView on which the signal is emitted
1747      * @request: a #WebKitFormSubmissionRequest
1748      *
1749      * This signal is emitted when a form is about to be submitted. The @request
1750      * argument passed contains information about the text fields of the form. This
1751      * is typically used to store login information that can be used later to
1752      * pre-fill the form.
1753      * The form will not be submitted until webkit_form_submission_request_submit() is called.
1754      *
1755      * It is possible to handle the form submission request asynchronously, by
1756      * simply calling g_object_ref() on the @request argument and calling
1757      * webkit_form_submission_request_submit() when done to continue with the form submission.
1758      * If the last reference is removed on a #WebKitFormSubmissionRequest and the
1759      * form has not been submitted, webkit_form_submission_request_submit() will be called.
1760      */
1761     signals[SUBMIT_FORM] =
1762         g_signal_new("submit-form",
1763                      G_TYPE_FROM_CLASS(webViewClass),
1764                      G_SIGNAL_RUN_LAST,
1765                      G_STRUCT_OFFSET(WebKitWebViewClass, submit_form),
1766                      0, 0,
1767                      g_cclosure_marshal_VOID__OBJECT,
1768                      G_TYPE_NONE, 1,
1769                      WEBKIT_TYPE_FORM_SUBMISSION_REQUEST);
1770
1771     /**
1772      * WebKitWebView::insecure-content-detected:
1773      * @web_view: the #WebKitWebView on which the signal is emitted
1774      * @event: the #WebKitInsecureContentEvent
1775      *
1776      * This signal is emitted when insecure content has been detected
1777      * in a page loaded through a secure connection. This typically
1778      * means that a external resource from an unstrusted source has
1779      * been run or displayed, resulting in a mix of HTTPS and
1780      * non-HTTPS content.
1781      *
1782      * You can check the @event parameter to know exactly which kind
1783      * of event has been detected (see #WebKitInsecureContentEvent).
1784      */
1785     signals[INSECURE_CONTENT_DETECTED] =
1786         g_signal_new("insecure-content-detected",
1787             G_TYPE_FROM_CLASS(webViewClass),
1788             G_SIGNAL_RUN_LAST,
1789             G_STRUCT_OFFSET(WebKitWebViewClass, insecure_content_detected),
1790             0, 0,
1791             g_cclosure_marshal_VOID__ENUM,
1792             G_TYPE_NONE, 1,
1793             WEBKIT_TYPE_INSECURE_CONTENT_EVENT);
1794
1795 #if PLATFORM(GTK)
1796     /**
1797      * WebKitWebView::web-process-crashed:
1798      * @web_view: the #WebKitWebView
1799      *
1800      * This signal is emitted when the web process crashes.
1801      *
1802      * Returns: %TRUE to stop other handlers from being invoked for the event.
1803      *    %FALSE to propagate the event further.
1804      *
1805      * Deprecated: 2.20: Use WebKitWebView::web-process-terminated instead.
1806      */
1807     signals[WEB_PROCESS_CRASHED] = g_signal_new(
1808         "web-process-crashed",
1809         G_TYPE_FROM_CLASS(webViewClass),
1810         G_SIGNAL_RUN_LAST,
1811         G_STRUCT_OFFSET(WebKitWebViewClass, web_process_crashed),
1812         g_signal_accumulator_true_handled, nullptr,
1813         g_cclosure_marshal_generic,
1814         G_TYPE_BOOLEAN, 0);
1815 #endif
1816
1817     /**
1818      * WebKitWebView::web-process-terminated:
1819      * @web_view: the #WebKitWebView
1820      * @reason: the a #WebKitWebProcessTerminationReason
1821      *
1822      * This signal is emitted when the web process terminates abnormally due
1823      * to @reason.
1824      *
1825      * Since: 2.20
1826      */
1827     signals[WEB_PROCESS_TERMINATED] = g_signal_new(
1828         "web-process-terminated",
1829         G_TYPE_FROM_CLASS(webViewClass),
1830         G_SIGNAL_RUN_LAST,
1831         G_STRUCT_OFFSET(WebKitWebViewClass, web_process_terminated),
1832         0, 0,
1833         g_cclosure_marshal_VOID__ENUM,
1834         G_TYPE_NONE, 1,
1835         WEBKIT_TYPE_WEB_PROCESS_TERMINATION_REASON);
1836
1837     /**
1838      * WebKitWebView::authenticate:
1839      * @web_view: the #WebKitWebView on which the signal is emitted
1840      * @request: a #WebKitAuthenticationRequest
1841      *
1842      * This signal is emitted when the user is challenged with HTTP
1843      * authentication. To let the  application access or supply
1844      * the credentials as well as to allow the client application
1845      * to either cancel the request or perform the authentication,
1846      * the signal will pass an instance of the
1847      * #WebKitAuthenticationRequest in the @request argument.
1848      * To handle this signal asynchronously you should keep a ref
1849      * of the request and return %TRUE. To disable HTTP authentication
1850      * entirely, connect to this signal and simply return %TRUE.
1851      *
1852      * The default signal handler will run a default authentication
1853      * dialog asynchronously for the user to interact with.
1854      *
1855      * Returns: %TRUE to stop other handlers from being invoked for the event.
1856      *   %FALSE to propagate the event further.
1857      *
1858      * Since: 2.2
1859      */
1860     signals[AUTHENTICATE] = g_signal_new(
1861         "authenticate",
1862         G_TYPE_FROM_CLASS(webViewClass),
1863         G_SIGNAL_RUN_LAST,
1864         G_STRUCT_OFFSET(WebKitWebViewClass, authenticate),
1865         g_signal_accumulator_true_handled, nullptr /* accumulator data */,
1866         g_cclosure_marshal_generic,
1867         G_TYPE_BOOLEAN, 1, /* number of parameters */
1868         WEBKIT_TYPE_AUTHENTICATION_REQUEST);
1869
1870     /**
1871      * WebKitWebView::show-notification:
1872      * @web_view: the #WebKitWebView
1873      * @notification: a #WebKitNotification
1874      *
1875      * This signal is emitted when a notification should be presented to the
1876      * user. The @notification is kept alive until either: 1) the web page cancels it
1877      * or 2) a navigation happens.
1878      *
1879      * The default handler will emit a notification using libnotify, if built with
1880      * support for it.
1881      *
1882      * Returns: %TRUE to stop other handlers from being invoked. %FALSE otherwise.
1883      *
1884      * Since: 2.8
1885      */
1886     signals[SHOW_NOTIFICATION] = g_signal_new(
1887         "show-notification",
1888         G_TYPE_FROM_CLASS(gObjectClass),
1889         G_SIGNAL_RUN_LAST,
1890         G_STRUCT_OFFSET(WebKitWebViewClass, show_notification),
1891         g_signal_accumulator_true_handled, nullptr /* accumulator data */,
1892         g_cclosure_marshal_generic,
1893         G_TYPE_BOOLEAN, 1,
1894         WEBKIT_TYPE_NOTIFICATION);
1895
1896 #if PLATFORM(GTK)
1897      /**
1898       * WebKitWebView::run-color-chooser:
1899       * @web_view: the #WebKitWebView on which the signal is emitted
1900       * @request: a #WebKitColorChooserRequest
1901       *
1902       * This signal is emitted when the user interacts with a &lt;input
1903       * type='color' /&gt; HTML element, requesting from WebKit to show
1904       * a dialog to select a color. To let the application know the details of
1905       * the color chooser, as well as to allow the client application to either
1906       * cancel the request or perform an actual color selection, the signal will
1907       * pass an instance of the #WebKitColorChooserRequest in the @request
1908       * argument.
1909       *
1910       * It is possible to handle this request asynchronously by increasing the
1911       * reference count of the request.
1912       *
1913       * The default signal handler will asynchronously run a regular
1914       * #GtkColorChooser for the user to interact with.
1915       *
1916       * Returns: %TRUE to stop other handlers from being invoked for the event.
1917       *   %FALSE to propagate the event further.
1918       *
1919       * Since: 2.8
1920       */
1921     signals[RUN_COLOR_CHOOSER] = g_signal_new(
1922         "run-color-chooser",
1923         G_TYPE_FROM_CLASS(webViewClass),
1924         G_SIGNAL_RUN_LAST,
1925         G_STRUCT_OFFSET(WebKitWebViewClass, run_color_chooser),
1926         g_signal_accumulator_true_handled, nullptr,
1927         g_cclosure_marshal_generic,
1928         G_TYPE_BOOLEAN, 1,
1929         WEBKIT_TYPE_COLOR_CHOOSER_REQUEST);
1930
1931     /**
1932      * WebKitWebView::show-option-menu:
1933      * @web_view: the #WebKitWebView on which the signal is emitted
1934      * @menu: the #WebKitOptionMenu
1935      * @event: the #GdkEvent that triggered the menu, or %NULL
1936      * @rectangle: the option element area
1937      *
1938      * This signal is emitted when a select element in @web_view needs to display a
1939      * dropdown menu. This signal can be used to show a custom menu, using @menu to get
1940      * the details of all items that should be displayed. The area of the element in the
1941      * #WebKitWebView is given as @rectangle parameter, it can be used to position the
1942      * menu. If this was triggered by a user interaction, like a mouse click,
1943      * @event parameter provides the #GdkEvent.
1944      * To handle this signal asynchronously you should keep a ref of the @menu.
1945      *
1946      * The default signal handler will pop up a #GtkMenu.
1947      *
1948      * Returns: %TRUE to stop other handlers from being invoked for the event.
1949      *   %FALSE to propagate the event further.
1950      *
1951      * Since: 2.18
1952      */
1953     signals[SHOW_OPTION_MENU] = g_signal_new(
1954         "show-option-menu",
1955         G_TYPE_FROM_CLASS(webViewClass),
1956         G_SIGNAL_RUN_LAST,
1957         G_STRUCT_OFFSET(WebKitWebViewClass, show_option_menu),
1958         g_signal_accumulator_true_handled, nullptr,
1959         g_cclosure_marshal_generic,
1960         G_TYPE_BOOLEAN, 3,
1961         WEBKIT_TYPE_OPTION_MENU,
1962         GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE,
1963         GDK_TYPE_RECTANGLE | G_SIGNAL_TYPE_STATIC_SCOPE);
1964 #endif // PLATFORM(GTK)
1965 }
1966
1967 static void webkitWebViewCancelAuthenticationRequest(WebKitWebView* webView)
1968 {
1969     if (!webView->priv->authenticationRequest)
1970         return;
1971
1972     webkit_authentication_request_cancel(webView->priv->authenticationRequest.get());
1973     webView->priv->authenticationRequest.clear();
1974 }
1975
1976 void webkitWebViewCreatePage(WebKitWebView* webView, Ref<API::PageConfiguration>&& configuration)
1977 {
1978 #if PLATFORM(GTK)
1979     webkitWebViewBaseCreateWebPage(WEBKIT_WEB_VIEW_BASE(webView), WTFMove(configuration));
1980 #elif PLATFORM(WPE)
1981     webView->priv->view.reset(WKWPE::View::create(webkit_web_view_backend_get_wpe_backend(webView->priv->backend.get()), configuration.get()));
1982 #endif
1983 }
1984
1985 WebPageProxy& webkitWebViewGetPage(WebKitWebView* webView)
1986 {
1987     return getPage(webView);
1988 }
1989
1990 void webkitWebViewLoadChanged(WebKitWebView* webView, WebKitLoadEvent loadEvent)
1991 {
1992     WebKitWebViewPrivate* priv = webView->priv;
1993     switch (loadEvent) {
1994     case WEBKIT_LOAD_STARTED:
1995 #if PLATFORM(GTK)
1996         webkitWebViewCancelFaviconRequest(webView);
1997         webkitWebViewWatchForChangesInFavicon(webView);
1998 #endif
1999         webkitWebViewCancelAuthenticationRequest(webView);
2000         priv->loadingResourcesMap.clear();
2001         priv->mainResource = nullptr;
2002         break;
2003 #if PLATFORM(GTK)
2004     case WEBKIT_LOAD_COMMITTED: {
2005         WebKitFaviconDatabase* database = webkit_web_context_get_favicon_database(priv->context.get());
2006         GUniquePtr<char> faviconURI(webkit_favicon_database_get_favicon_uri(database, priv->activeURI.data()));
2007         webkitWebViewUpdateFaviconURI(webView, faviconURI.get());
2008         break;
2009     }
2010 #endif
2011     case WEBKIT_LOAD_FINISHED:
2012         webkitWebViewCancelAuthenticationRequest(webView);
2013         break;
2014     default:
2015         break;
2016     }
2017
2018     g_signal_emit(webView, signals[LOAD_CHANGED], 0, loadEvent);
2019 }
2020
2021 void webkitWebViewLoadFailed(WebKitWebView* webView, WebKitLoadEvent loadEvent, const char* failingURI, GError *error)
2022 {
2023     webkitWebViewCancelAuthenticationRequest(webView);
2024
2025     gboolean returnValue;
2026     g_signal_emit(webView, signals[LOAD_FAILED], 0, loadEvent, failingURI, error, &returnValue);
2027     g_signal_emit(webView, signals[LOAD_CHANGED], 0, WEBKIT_LOAD_FINISHED);
2028 }
2029
2030 void webkitWebViewLoadFailedWithTLSErrors(WebKitWebView* webView, const char* failingURI, GError* error, GTlsCertificateFlags tlsErrors, GTlsCertificate* certificate)
2031 {
2032     webkitWebViewCancelAuthenticationRequest(webView);
2033
2034     WebKitTLSErrorsPolicy tlsErrorsPolicy = webkit_web_context_get_tls_errors_policy(webView->priv->context.get());
2035     if (tlsErrorsPolicy == WEBKIT_TLS_ERRORS_POLICY_FAIL) {
2036         gboolean returnValue;
2037         g_signal_emit(webView, signals[LOAD_FAILED_WITH_TLS_ERRORS], 0, failingURI, certificate, tlsErrors, &returnValue);
2038         if (!returnValue)
2039             g_signal_emit(webView, signals[LOAD_FAILED], 0, WEBKIT_LOAD_STARTED, failingURI, error, &returnValue);
2040     }
2041
2042     g_signal_emit(webView, signals[LOAD_CHANGED], 0, WEBKIT_LOAD_FINISHED);
2043 }
2044
2045 #if PLATFORM(GTK)
2046 void webkitWebViewGetLoadDecisionForIcon(WebKitWebView* webView, const LinkIcon& icon, Function<void(bool)>&& completionHandler)
2047 {
2048     WebKitFaviconDatabase* database = webkit_web_context_get_favicon_database(webView->priv->context.get());
2049     webkitFaviconDatabaseGetLoadDecisionForIcon(database, icon, getPage(webView).pageLoadState().activeURL(), WTFMove(completionHandler));
2050 }
2051
2052 void webkitWebViewSetIcon(WebKitWebView* webView, const LinkIcon& icon, API::Data& iconData)
2053 {
2054     WebKitFaviconDatabase* database = webkit_web_context_get_favicon_database(webView->priv->context.get());
2055     webkitFaviconDatabaseSetIconForPageURL(database, icon, iconData, getPage(webView).pageLoadState().activeURL());
2056 }
2057 #endif
2058
2059 WebPageProxy* webkitWebViewCreateNewPage(WebKitWebView* webView, const WindowFeatures& windowFeatures, WebKitNavigationAction* navigationAction)
2060 {
2061     WebKitWebView* newWebView;
2062     g_signal_emit(webView, signals[CREATE], 0, navigationAction, &newWebView);
2063     if (!newWebView)
2064         return 0;
2065
2066     webkitWindowPropertiesUpdateFromWebWindowFeatures(newWebView->priv->windowProperties.get(), windowFeatures);
2067
2068     RefPtr<WebPageProxy> newPage = &getPage(newWebView);
2069     return newPage.leakRef();
2070 }
2071
2072 void webkitWebViewReadyToShowPage(WebKitWebView* webView)
2073 {
2074     g_signal_emit(webView, signals[READY_TO_SHOW], 0, NULL);
2075 }
2076
2077 void webkitWebViewRunAsModal(WebKitWebView* webView)
2078 {
2079     g_signal_emit(webView, signals[RUN_AS_MODAL], 0, NULL);
2080
2081     webView->priv->modalLoop = adoptGRef(g_main_loop_new(0, FALSE));
2082
2083 #if PLATFORM(GTK)
2084 // This is to suppress warnings about gdk_threads_leave and gdk_threads_enter.
2085 #pragma GCC diagnostic push
2086 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
2087     gdk_threads_leave();
2088 #endif
2089
2090     g_main_loop_run(webView->priv->modalLoop.get());
2091
2092 #if PLATFORM(GTK)
2093     gdk_threads_enter();
2094 #pragma GCC diagnostic pop
2095 #endif
2096 }
2097
2098 void webkitWebViewClosePage(WebKitWebView* webView)
2099 {
2100     g_signal_emit(webView, signals[CLOSE], 0, NULL);
2101 }
2102
2103 void webkitWebViewRunJavaScriptAlert(WebKitWebView* webView, const CString& message)
2104 {
2105     WebKitScriptDialog dialog(WEBKIT_SCRIPT_DIALOG_ALERT, message);
2106     SetForScope<WebKitScriptDialog*> change(webView->priv->currentScriptDialog, &dialog);
2107     gboolean returnValue;
2108     g_signal_emit(webView, signals[SCRIPT_DIALOG], 0, &dialog, &returnValue);
2109 }
2110
2111 bool webkitWebViewRunJavaScriptConfirm(WebKitWebView* webView, const CString& message)
2112 {
2113     WebKitScriptDialog dialog(WEBKIT_SCRIPT_DIALOG_CONFIRM, message);
2114     SetForScope<WebKitScriptDialog*> change(webView->priv->currentScriptDialog, &dialog);
2115     gboolean returnValue;
2116     g_signal_emit(webView, signals[SCRIPT_DIALOG], 0, &dialog, &returnValue);
2117     return dialog.confirmed;
2118 }
2119
2120 CString webkitWebViewRunJavaScriptPrompt(WebKitWebView* webView, const CString& message, const CString& defaultText)
2121 {
2122     WebKitScriptDialog dialog(WEBKIT_SCRIPT_DIALOG_PROMPT, message, defaultText);
2123     SetForScope<WebKitScriptDialog*> change(webView->priv->currentScriptDialog, &dialog);
2124     gboolean returnValue;
2125     g_signal_emit(webView, signals[SCRIPT_DIALOG], 0, &dialog, &returnValue);
2126     return dialog.text;
2127 }
2128
2129 bool webkitWebViewRunJavaScriptBeforeUnloadConfirm(WebKitWebView* webView, const CString& message)
2130 {
2131     WebKitScriptDialog dialog(WEBKIT_SCRIPT_DIALOG_BEFORE_UNLOAD_CONFIRM, message);
2132     SetForScope<WebKitScriptDialog*> change(webView->priv->currentScriptDialog, &dialog);
2133     gboolean returnValue;
2134     g_signal_emit(webView, signals[SCRIPT_DIALOG], 0, &dialog, &returnValue);
2135     return dialog.confirmed;
2136 }
2137
2138 bool webkitWebViewIsShowingScriptDialog(WebKitWebView* webView)
2139 {
2140     if (!webView->priv->currentScriptDialog)
2141         return false;
2142
2143     // FIXME: Add API to ask the user in case default implementation is not being used.
2144     return webkitScriptDialogIsRunning(webView->priv->currentScriptDialog);
2145 }
2146
2147 String webkitWebViewGetCurrentScriptDialogMessage(WebKitWebView* webView)
2148 {
2149     if (!webView->priv->currentScriptDialog)
2150         return { };
2151
2152     return String::fromUTF8(webView->priv->currentScriptDialog->message);
2153 }
2154
2155 void webkitWebViewSetCurrentScriptDialogUserInput(WebKitWebView* webView, const String& userInput)
2156 {
2157     if (!webView->priv->currentScriptDialog)
2158         return;
2159
2160     // FIXME: Add API to ask the user in case default implementation is not being used.
2161     if (webkitScriptDialogIsRunning(webView->priv->currentScriptDialog))
2162         webkitScriptDialogSetUserInput(webView->priv->currentScriptDialog, userInput);
2163 }
2164
2165 void webkitWebViewAcceptCurrentScriptDialog(WebKitWebView* webView)
2166 {
2167     if (!webView->priv->currentScriptDialog)
2168         return;
2169
2170     // FIXME: Add API to ask the user in case default implementation is not being used.
2171     if (webkitScriptDialogIsRunning(webView->priv->currentScriptDialog))
2172         webkitScriptDialogAccept(webView->priv->currentScriptDialog);
2173 }
2174
2175 void webkitWebViewDismissCurrentScriptDialog(WebKitWebView* webView)
2176 {
2177     if (!webView->priv->currentScriptDialog)
2178         return;
2179
2180     // FIXME: Add API to ask the user in case default implementation is not being used.
2181     if (webkitScriptDialogIsRunning(webView->priv->currentScriptDialog))
2182         webkitScriptDialogDismiss(webView->priv->currentScriptDialog);
2183 }
2184
2185 std::optional<WebKitScriptDialogType> webkitWebViewGetCurrentScriptDialogType(WebKitWebView* webView)
2186 {
2187     if (!webView->priv->currentScriptDialog)
2188         return std::nullopt;
2189
2190     return static_cast<WebKitScriptDialogType>(webView->priv->currentScriptDialog->type);
2191 }
2192
2193 void webkitWebViewMakePolicyDecision(WebKitWebView* webView, WebKitPolicyDecisionType type, WebKitPolicyDecision* decision)
2194 {
2195     gboolean returnValue;
2196     g_signal_emit(webView, signals[DECIDE_POLICY], 0, decision, type, &returnValue);
2197 }
2198
2199 void webkitWebViewMakePermissionRequest(WebKitWebView* webView, WebKitPermissionRequest* request)
2200 {
2201     gboolean returnValue;
2202     g_signal_emit(webView, signals[PERMISSION_REQUEST], 0, request, &returnValue);
2203 }
2204
2205 void webkitWebViewMouseTargetChanged(WebKitWebView* webView, const WebHitTestResultData& hitTestResult, WebEvent::Modifiers modifiers)
2206 {
2207 #if PLATFORM(GTK)
2208     webkitWebViewBaseSetTooltipArea(WEBKIT_WEB_VIEW_BASE(webView), hitTestResult.elementBoundingBox);
2209 #endif
2210
2211     WebKitWebViewPrivate* priv = webView->priv;
2212     if (priv->mouseTargetHitTestResult
2213         && priv->mouseTargetModifiers == modifiers
2214         && webkitHitTestResultCompare(priv->mouseTargetHitTestResult.get(), hitTestResult))
2215         return;
2216
2217     priv->mouseTargetModifiers = modifiers;
2218     priv->mouseTargetHitTestResult = adoptGRef(webkitHitTestResultCreate(hitTestResult));
2219     g_signal_emit(webView, signals[MOUSE_TARGET_CHANGED], 0, priv->mouseTargetHitTestResult.get(), toPlatformModifiers(modifiers));
2220 }
2221
2222 void webkitWebViewHandleDownloadRequest(WebKitWebView* webView, DownloadProxy* downloadProxy)
2223 {
2224     ASSERT(downloadProxy);
2225     GRefPtr<WebKitDownload> download = webkitWebContextGetOrCreateDownload(downloadProxy);
2226     webkitDownloadSetWebView(download.get(), webView);
2227 }
2228
2229 #if PLATFORM(GTK)
2230 void webkitWebViewPrintFrame(WebKitWebView* webView, WebFrameProxy* frame)
2231 {
2232     auto printOperation = adoptGRef(webkit_print_operation_new(webView));
2233     webkitPrintOperationSetPrintMode(printOperation.get(), PrintInfo::PrintModeSync);
2234     gboolean returnValue;
2235     g_signal_emit(webView, signals[PRINT], 0, printOperation.get(), &returnValue);
2236     if (returnValue)
2237         return;
2238
2239     WebKitPrintOperationResponse response = webkitPrintOperationRunDialogForFrame(printOperation.get(), 0, frame);
2240     if (response == WEBKIT_PRINT_OPERATION_RESPONSE_CANCEL)
2241         return;
2242     g_signal_connect(printOperation.leakRef(), "finished", G_CALLBACK(g_object_unref), 0);
2243 }
2244 #endif
2245
2246 void webkitWebViewResourceLoadStarted(WebKitWebView* webView, WebFrameProxy* frame, uint64_t resourceIdentifier, WebKitURIRequest* request)
2247 {
2248     WebKitWebViewPrivate* priv = webView->priv;
2249     bool isMainResource = frame->isMainFrame() && !priv->mainResource;
2250     WebKitWebResource* resource = webkitWebResourceCreate(frame, request, isMainResource);
2251     if (isMainResource)
2252         priv->mainResource = resource;
2253     priv->loadingResourcesMap.set(resourceIdentifier, adoptGRef(resource));
2254     g_signal_emit(webView, signals[RESOURCE_LOAD_STARTED], 0, resource, request);
2255 }
2256
2257 WebKitWebResource* webkitWebViewGetLoadingWebResource(WebKitWebView* webView, uint64_t resourceIdentifier)
2258 {
2259     GRefPtr<WebKitWebResource> resource = webView->priv->loadingResourcesMap.get(resourceIdentifier);
2260     return resource.get();
2261 }
2262
2263 void webkitWebViewRemoveLoadingWebResource(WebKitWebView* webView, uint64_t resourceIdentifier)
2264 {
2265     WebKitWebViewPrivate* priv = webView->priv;
2266     ASSERT(priv->loadingResourcesMap.contains(resourceIdentifier));
2267     priv->loadingResourcesMap.remove(resourceIdentifier);
2268 }
2269
2270 void webkitWebViewEnterFullScreen(WebKitWebView* webView)
2271 {
2272 #if ENABLE(FULLSCREEN_API)
2273     gboolean returnValue;
2274     g_signal_emit(webView, signals[ENTER_FULLSCREEN], 0, &returnValue);
2275 #if PLATFORM(GTK)
2276     if (!returnValue)
2277         webkitWebViewBaseEnterFullScreen(WEBKIT_WEB_VIEW_BASE(webView));
2278 #endif
2279 #endif
2280 }
2281
2282 void webkitWebViewExitFullScreen(WebKitWebView* webView)
2283 {
2284 #if ENABLE(FULLSCREEN_API)
2285     gboolean returnValue;
2286     g_signal_emit(webView, signals[LEAVE_FULLSCREEN], 0, &returnValue);
2287 #if PLATFORM(GTK)
2288     if (!returnValue)
2289         webkitWebViewBaseExitFullScreen(WEBKIT_WEB_VIEW_BASE(webView));
2290 #endif
2291 #endif
2292 }
2293
2294 void webkitWebViewRunFileChooserRequest(WebKitWebView* webView, WebKitFileChooserRequest* request)
2295 {
2296     gboolean returnValue;
2297     g_signal_emit(webView, signals[RUN_FILE_CHOOSER], 0, request, &returnValue);
2298 }
2299
2300 #if PLATFORM(GTK)
2301 static void contextMenuDismissed(GtkMenuShell*, WebKitWebView* webView)
2302 {
2303     g_signal_emit(webView, signals[CONTEXT_MENU_DISMISSED], 0, NULL);
2304 }
2305
2306 void webkitWebViewPopulateContextMenu(WebKitWebView* webView, const Vector<WebContextMenuItemData>& proposedMenu, const WebHitTestResultData& hitTestResultData, GVariant* userData)
2307 {
2308     WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(webView);
2309     WebContextMenuProxyGtk* contextMenuProxy = webkitWebViewBaseGetActiveContextMenuProxy(webViewBase);
2310     ASSERT(contextMenuProxy);
2311
2312     GRefPtr<WebKitContextMenu> contextMenu = adoptGRef(webkitContextMenuCreate(proposedMenu));
2313     if (userData)
2314         webkit_context_menu_set_user_data(WEBKIT_CONTEXT_MENU(contextMenu.get()), userData);
2315
2316     GRefPtr<WebKitHitTestResult> hitTestResult = adoptGRef(webkitHitTestResultCreate(hitTestResultData));
2317     GUniquePtr<GdkEvent> contextMenuEvent(webkitWebViewBaseTakeContextMenuEvent(webViewBase));
2318     gboolean returnValue;
2319     g_signal_emit(webView, signals[CONTEXT_MENU], 0, contextMenu.get(), contextMenuEvent.get(), hitTestResult.get(), &returnValue);
2320     if (returnValue)
2321         return;
2322
2323     Vector<WebContextMenuItemGlib> contextMenuItems;
2324     webkitContextMenuPopulate(contextMenu.get(), contextMenuItems);
2325     contextMenuProxy->populate(contextMenuItems);
2326
2327     g_signal_connect(contextMenuProxy->gtkMenu(), "deactivate", G_CALLBACK(contextMenuDismissed), webView);
2328
2329     // Clear the menu to make sure it's useless after signal emission.
2330     webkit_context_menu_remove_all(contextMenu.get());
2331 }
2332 #elif PLATFORM(WPE)
2333 void webkitWebViewPopulateContextMenu(WebKitWebView* webView, const Vector<WebContextMenuItemData>& proposedMenu, const WebHitTestResultData& hitTestResultData, GVariant* userData)
2334 {
2335     GRefPtr<WebKitContextMenu> contextMenu = adoptGRef(webkitContextMenuCreate(proposedMenu));
2336     if (userData)
2337         webkit_context_menu_set_user_data(WEBKIT_CONTEXT_MENU(contextMenu.get()), userData);
2338     GRefPtr<WebKitHitTestResult> hitTestResult = adoptGRef(webkitHitTestResultCreate(hitTestResultData));
2339     gboolean returnValue;
2340     g_signal_emit(webView, signals[CONTEXT_MENU], 0, contextMenu.get(), nullptr, hitTestResult.get(), &returnValue);
2341 }
2342 #endif
2343
2344 void webkitWebViewSubmitFormRequest(WebKitWebView* webView, WebKitFormSubmissionRequest* request)
2345 {
2346     g_signal_emit(webView, signals[SUBMIT_FORM], 0, request);
2347 }
2348
2349 void webkitWebViewHandleAuthenticationChallenge(WebKitWebView* webView, AuthenticationChallengeProxy* authenticationChallenge)
2350 {
2351 #if PLATFORM(GTK)
2352     G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
2353     gboolean privateBrowsingEnabled = webView->priv->isEphemeral || webkit_settings_get_enable_private_browsing(webView->priv->settings.get());
2354     G_GNUC_END_IGNORE_DEPRECATIONS;
2355 #else
2356     gboolean privateBrowsingEnabled = webView->priv->isEphemeral;
2357 #endif
2358     webView->priv->authenticationRequest = adoptGRef(webkitAuthenticationRequestCreate(authenticationChallenge, privateBrowsingEnabled));
2359     gboolean returnValue;
2360     g_signal_emit(webView, signals[AUTHENTICATE], 0, webView->priv->authenticationRequest.get(), &returnValue);
2361 }
2362
2363 void webkitWebViewInsecureContentDetected(WebKitWebView* webView, WebKitInsecureContentEvent type)
2364 {
2365     g_signal_emit(webView, signals[INSECURE_CONTENT_DETECTED], 0, type);
2366 }
2367
2368 bool webkitWebViewEmitShowNotification(WebKitWebView* webView, WebKitNotification* webNotification)
2369 {
2370     gboolean handled;
2371     g_signal_emit(webView, signals[SHOW_NOTIFICATION], 0, webNotification, &handled);
2372     return handled;
2373 }
2374
2375 #if PLATFORM(GTK)
2376 bool webkitWebViewEmitRunColorChooser(WebKitWebView* webView, WebKitColorChooserRequest* request)
2377 {
2378     gboolean handled;
2379     g_signal_emit(webView, signals[RUN_COLOR_CHOOSER], 0, request, &handled);
2380     return handled;
2381 }
2382 #endif
2383
2384 void webkitWebViewSelectionDidChange(WebKitWebView* webView)
2385 {
2386     if (!webView->priv->editorState)
2387         return;
2388
2389     webkitEditorStateChanged(webView->priv->editorState.get(), getPage(webView).editorState());
2390 }
2391
2392 void webkitWebViewRequestInstallMissingMediaPlugins(WebKitWebView* webView, InstallMissingMediaPluginsPermissionRequest& request)
2393 {
2394 #if ENABLE(VIDEO)
2395     GRefPtr<WebKitInstallMissingMediaPluginsPermissionRequest> installMediaPluginsPermissionRequest = adoptGRef(webkitInstallMissingMediaPluginsPermissionRequestCreate(request));
2396     webkitWebViewMakePermissionRequest(webView, WEBKIT_PERMISSION_REQUEST(installMediaPluginsPermissionRequest.get()));
2397 #else
2398     ASSERT_NOT_REACHED();
2399 #endif
2400 }
2401
2402 WebKitWebsiteDataManager* webkitWebViewGetWebsiteDataManager(WebKitWebView* webView)
2403 {
2404     return webView->priv->websiteDataManager.get();
2405 }
2406
2407 #if PLATFORM(GTK)
2408 bool webkitWebViewShowOptionMenu(WebKitWebView* webView, const IntRect& rect, WebKitOptionMenu* menu, const GdkEvent* event)
2409 {
2410     GdkRectangle menuRect = rect;
2411     gboolean handled;
2412     g_signal_emit(webView, signals[SHOW_OPTION_MENU], 0, menu, event, &menuRect, &handled);
2413     return handled;
2414 }
2415 #endif
2416
2417 #if PLATFORM(WPE)
2418 /**
2419  * webkit_web_view_get_backend:
2420  * @web_view: a #WebKitWebView
2421  *
2422  * Get the #WebKitWebViewBackend of @web_view
2423  *
2424  * Returns: (transfer none): the #WebKitWebViewBackend of @web_view
2425  *
2426  * Since: 2.20
2427  */
2428 WebKitWebViewBackend* webkit_web_view_get_backend(WebKitWebView* webView)
2429 {
2430     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), nullptr);
2431
2432     return webView->priv->backend.get();
2433 }
2434 #endif
2435
2436 /**
2437  * webkit_web_view_get_context:
2438  * @web_view: a #WebKitWebView
2439  *
2440  * Gets the web context of @web_view.
2441  *
2442  * Returns: (transfer none): the #WebKitWebContext of the view
2443  */
2444 WebKitWebContext* webkit_web_view_get_context(WebKitWebView *webView)
2445 {
2446     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0);
2447
2448     return webView->priv->context.get();
2449 }
2450
2451 /**
2452  * webkit_web_view_get_user_content_manager:
2453  * @web_view: a #WebKitWebView
2454  *
2455  * Gets the user content manager associated to @web_view.
2456  *
2457  * Returns: (transfer none): the #WebKitUserContentManager associated with the view
2458  *
2459  * Since: 2.6
2460  */
2461 WebKitUserContentManager* webkit_web_view_get_user_content_manager(WebKitWebView* webView)
2462 {
2463     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), nullptr);
2464
2465     return webView->priv->userContentManager.get();
2466 }
2467
2468 /**
2469  * webkit_web_view_is_ephemeral:
2470  * @web_view: a #WebKitWebView
2471  *
2472  * Get whether a #WebKitWebView is ephemeral. To create an ephemeral #WebKitWebView you need to
2473  * use g_object_new() and pass is-ephemeral property with %TRUE value. See
2474  * #WebKitWebView:is-ephemeral for more details.
2475  * If @web_view was created with a ephemeral #WebKitWebView:related-view or an
2476  * ephemeral #WebKitWebView:web-context it will also be ephemeral.
2477  *
2478  * Returns: %TRUE if @web_view is ephemeral or %FALSE otherwise.
2479  *
2480  * Since: 2.16
2481  */
2482 gboolean webkit_web_view_is_ephemeral(WebKitWebView* webView)
2483 {
2484     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), FALSE);
2485
2486     return webView->priv->isEphemeral;
2487 }
2488
2489 /**
2490  * webkit_web_view_is_controlled_by_automation:
2491  * @web_view: a #WebKitWebView
2492  *
2493  * Get whether a #WebKitWebView was created with #WebKitWebView:is-controlled-by-automation
2494  * property enabled. Only #WebKitWebView<!-- -->s controlled by automation can be used in an
2495  * automation session.
2496  *
2497  * Returns: %TRUE if @web_view is controlled by automation, or %FALSE otherwise.
2498  *
2499  * Since: 2.18
2500  */
2501 gboolean webkit_web_view_is_controlled_by_automation(WebKitWebView* webView)
2502 {
2503     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), FALSE);
2504
2505     return webView->priv->isControlledByAutomation;
2506 }
2507
2508 /**
2509  * webkit_web_view_get_website_data_manager:
2510  * @web_view: a #WebKitWebView
2511  *
2512  * Get the #WebKitWebsiteDataManager associated to @web_view. If @web_view is not ephemeral,
2513  * the returned #WebKitWebsiteDataManager will be the same as the #WebKitWebsiteDataManager
2514  * of @web_view's #WebKitWebContext.
2515  *
2516  * Returns: (transfer none): a #WebKitWebsiteDataManager
2517  *
2518  * Since: 2.16
2519  */
2520 WebKitWebsiteDataManager* webkit_web_view_get_website_data_manager(WebKitWebView* webView)
2521 {
2522     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), nullptr);
2523
2524     if (webView->priv->websiteDataManager)
2525         return webView->priv->websiteDataManager.get();
2526
2527     return webkit_web_context_get_website_data_manager(webView->priv->context.get());
2528 }
2529
2530 /**
2531  * webkit_web_view_try_close:
2532  * @web_view: a #WebKitWebView
2533  *
2534  * Tries to close the @web_view. This will fire the onbeforeunload event
2535  * to ask the user for confirmation to close the page. If there isn't an
2536  * onbeforeunload event handler or the user confirms to close the page,
2537  * the #WebKitWebView::close signal is emitted, otherwise nothing happens.
2538  *
2539  * Since: 2.12
2540  */
2541 void webkit_web_view_try_close(WebKitWebView *webView)
2542 {
2543     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
2544     if (getPage(webView).tryClose())
2545         webkitWebViewClosePage(webView);
2546 }
2547
2548 /**
2549  * webkit_web_view_load_uri:
2550  * @web_view: a #WebKitWebView
2551  * @uri: an URI string
2552  *
2553  * Requests loading of the specified URI string.
2554  * You can monitor the load operation by connecting to
2555  * #WebKitWebView::load-changed signal.
2556  */
2557 void webkit_web_view_load_uri(WebKitWebView* webView, const gchar* uri)
2558 {
2559     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
2560     g_return_if_fail(uri);
2561
2562     GUniquePtr<SoupURI> soupURI(soup_uri_new(uri));
2563     getPage(webView).loadRequest(URL(soupURI.get()));
2564 }
2565
2566 /**
2567  * webkit_web_view_load_html:
2568  * @web_view: a #WebKitWebView
2569  * @content: The HTML string to load
2570  * @base_uri: (allow-none): The base URI for relative locations or %NULL
2571  *
2572  * Load the given @content string with the specified @base_uri.
2573  * If @base_uri is not %NULL, relative URLs in the @content will be
2574  * resolved against @base_uri and absolute local paths must be children of the @base_uri.
2575  * For security reasons absolute local paths that are not children of @base_uri
2576  * will cause the web process to terminate.
2577  * If you need to include URLs in @content that are local paths in a different
2578  * directory than @base_uri you can build a data URI for them. When @base_uri is %NULL,
2579  * it defaults to "about:blank". The mime type of the document will be "text/html".
2580  * You can monitor the load operation by connecting to #WebKitWebView::load-changed signal.
2581  */
2582 void webkit_web_view_load_html(WebKitWebView* webView, const gchar* content, const gchar* baseURI)
2583 {
2584     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
2585     g_return_if_fail(content);
2586
2587     getPage(webView).loadData({ reinterpret_cast<const uint8_t*>(content), content ? strlen(content) : 0 }, "text/html"_s, "UTF-8"_s, String::fromUTF8(baseURI));
2588 }
2589
2590 /**
2591  * webkit_web_view_load_alternate_html:
2592  * @web_view: a #WebKitWebView
2593  * @content: the new content to display as the main page of the @web_view
2594  * @content_uri: the URI for the alternate page content
2595  * @base_uri: (allow-none): the base URI for relative locations or %NULL
2596  *
2597  * Load the given @content string for the URI @content_uri.
2598  * This allows clients to display page-loading errors in the #WebKitWebView itself.
2599  * When this method is called from #WebKitWebView::load-failed signal to show an
2600  * error page, then the back-forward list is maintained appropriately.
2601  * For everything else this method works the same way as webkit_web_view_load_html().
2602  */
2603 void webkit_web_view_load_alternate_html(WebKitWebView* webView, const gchar* content, const gchar* contentURI, const gchar* baseURI)
2604 {
2605     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
2606     g_return_if_fail(content);
2607     g_return_if_fail(contentURI);
2608
2609     getPage(webView).loadAlternateHTML({ reinterpret_cast<const uint8_t*>(content), content ? strlen(content) : 0 }, "UTF-8"_s, URL(URL(), String::fromUTF8(baseURI)), URL(URL(), String::fromUTF8(contentURI)));
2610 }
2611
2612 /**
2613  * webkit_web_view_load_plain_text:
2614  * @web_view: a #WebKitWebView
2615  * @plain_text: The plain text to load
2616  *
2617  * Load the specified @plain_text string into @web_view. The mime type of
2618  * document will be "text/plain". You can monitor the load
2619  * operation by connecting to #WebKitWebView::load-changed signal.
2620  */
2621 void webkit_web_view_load_plain_text(WebKitWebView* webView, const gchar* plainText)
2622 {
2623     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
2624     g_return_if_fail(plainText);
2625
2626     getPage(webView).loadData({ reinterpret_cast<const uint8_t*>(plainText), plainText ? strlen(plainText) : 0 }, "text/plain"_s, "UTF-8"_s, blankURL().string());
2627 }
2628
2629 /**
2630  * webkit_web_view_load_bytes:
2631  * @web_view: a #WebKitWebView
2632  * @bytes: input data to load
2633  * @mime_type: (allow-none): the MIME type of @bytes, or %NULL
2634  * @encoding: (allow-none): the character encoding of @bytes, or %NULL
2635  * @base_uri: (allow-none): the base URI for relative locations or %NULL
2636  *
2637  * Load the specified @bytes into @web_view using the given @mime_type and @encoding.
2638  * When @mime_type is %NULL, it defaults to "text/html".
2639  * When @encoding is %NULL, it defaults to "UTF-8".
2640  * When @base_uri is %NULL, it defaults to "about:blank".
2641  * You can monitor the load operation by connecting to #WebKitWebView::load-changed signal.
2642  *
2643  * Since: 2.6
2644  */
2645 void webkit_web_view_load_bytes(WebKitWebView* webView, GBytes* bytes, const char* mimeType, const char* encoding, const char* baseURI)
2646 {
2647     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
2648     g_return_if_fail(bytes);
2649
2650     gsize bytesDataSize;
2651     gconstpointer bytesData = g_bytes_get_data(bytes, &bytesDataSize);
2652     g_return_if_fail(bytesDataSize);
2653
2654     getPage(webView).loadData({ reinterpret_cast<const uint8_t*>(bytesData), bytesDataSize }, mimeType ? String::fromUTF8(mimeType) : String::fromUTF8("text/html"),
2655         encoding ? String::fromUTF8(encoding) : String::fromUTF8("UTF-8"), String::fromUTF8(baseURI));
2656 }
2657
2658 /**
2659  * webkit_web_view_load_request:
2660  * @web_view: a #WebKitWebView
2661  * @request: a #WebKitURIRequest to load
2662  *
2663  * Requests loading of the specified #WebKitURIRequest.
2664  * You can monitor the load operation by connecting to
2665  * #WebKitWebView::load-changed signal.
2666  */
2667 void webkit_web_view_load_request(WebKitWebView* webView, WebKitURIRequest* request)
2668 {
2669     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
2670     g_return_if_fail(WEBKIT_IS_URI_REQUEST(request));
2671
2672     ResourceRequest resourceRequest;
2673     webkitURIRequestGetResourceRequest(request, resourceRequest);
2674     getPage(webView).loadRequest(WTFMove(resourceRequest));
2675 }
2676
2677 /**
2678  * webkit_web_view_get_page_id:
2679  * @web_view: a #WebKitWebView
2680  *
2681  * Get the identifier of the #WebKitWebPage corresponding to
2682  * the #WebKitWebView
2683  *
2684  * Returns: the page ID of @web_view.
2685  */
2686 guint64 webkit_web_view_get_page_id(WebKitWebView* webView)
2687 {
2688     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0);
2689
2690     return getPage(webView).pageID();
2691 }
2692
2693 /**
2694  * webkit_web_view_get_title:
2695  * @web_view: a #WebKitWebView
2696  *
2697  * Gets the value of the #WebKitWebView:title property.
2698  * You can connect to notify::title signal of @web_view to
2699  * be notified when the title has been received.
2700  *
2701  * Returns: The main frame document title of @web_view.
2702  */
2703 const gchar* webkit_web_view_get_title(WebKitWebView* webView)
2704 {
2705     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0);
2706
2707     return webView->priv->title.data();
2708 }
2709
2710 /**
2711  * webkit_web_view_reload:
2712  * @web_view: a #WebKitWebView
2713  *
2714  * Reloads the current contents of @web_view.
2715  * See also webkit_web_view_reload_bypass_cache().
2716  */
2717 void webkit_web_view_reload(WebKitWebView* webView)
2718 {
2719     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
2720
2721     getPage(webView).reload({ });
2722 }
2723
2724 /**
2725  * webkit_web_view_reload_bypass_cache:
2726  * @web_view: a #WebKitWebView
2727  *
2728  * Reloads the current contents of @web_view without
2729  * using any cached data.
2730  */
2731 void webkit_web_view_reload_bypass_cache(WebKitWebView* webView)
2732 {
2733     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
2734
2735     getPage(webView).reload(ReloadOption::FromOrigin);
2736 }
2737
2738 /**
2739  * webkit_web_view_stop_loading:
2740  * @web_view: a #WebKitWebView
2741  *
2742  * Stops any ongoing loading operation in @web_view.
2743  * This method does nothing if no content is being loaded.
2744  * If there is a loading operation in progress, it will be cancelled and
2745  * #WebKitWebView::load-failed signal will be emitted with
2746  * %WEBKIT_NETWORK_ERROR_CANCELLED error.
2747  */
2748 void webkit_web_view_stop_loading(WebKitWebView* webView)
2749 {
2750     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
2751
2752     getPage(webView).stopLoading();
2753 }
2754
2755 /**
2756  * webkit_web_view_is_loading:
2757  * @web_view: a #WebKitWebView
2758  *
2759  * Gets the value of the #WebKitWebView:is-loading property.
2760  * You can monitor when a #WebKitWebView is loading a page by connecting to
2761  * notify::is-loading signal of @web_view. This is useful when you are
2762  * interesting in knowing when the view is loading something but not in the
2763  * details about the status of the load operation, for example to start a spinner
2764  * when the view is loading a page and stop it when it finishes.
2765  *
2766  * Returns: %TRUE if @web_view is loading a page or %FALSE otherwise.
2767  */
2768 gboolean webkit_web_view_is_loading(WebKitWebView* webView)
2769 {
2770     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), FALSE);
2771
2772     return webView->priv->isLoading;
2773 }
2774
2775 /**
2776  * webkit_web_view_is_playing_audio:
2777  * @web_view: a #WebKitWebView
2778  *
2779  * Gets the value of the #WebKitWebView:is-playing-audio property.
2780  * You can monitor when a page in a #WebKitWebView is playing audio by
2781  * connecting to the notify::is-playing-audio signal of @web_view. This
2782  * is useful when the application wants to provide visual feedback when a
2783  * page is producing sound.
2784  *
2785  * Returns: %TRUE if a page in @web_view is playing audio or %FALSE otherwise.
2786  *
2787  * Since: 2.8
2788  */
2789 gboolean webkit_web_view_is_playing_audio(WebKitWebView* webView)
2790 {
2791     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), FALSE);
2792
2793     return getPage(webView).isPlayingAudio();
2794 }
2795
2796 /**
2797  * webkit_web_view_go_back:
2798  * @web_view: a #WebKitWebView
2799  *
2800  * Loads the previous history item.
2801  * You can monitor the load operation by connecting to
2802  * #WebKitWebView::load-changed signal.
2803  */
2804 void webkit_web_view_go_back(WebKitWebView* webView)
2805 {
2806     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
2807
2808     getPage(webView).goBack();
2809 }
2810
2811 /**
2812  * webkit_web_view_can_go_back:
2813  * @web_view: a #WebKitWebView
2814  *
2815  * Determines whether @web_view has a previous history item.
2816  *
2817  * Returns: %TRUE if able to move back or %FALSE otherwise.
2818  */
2819 gboolean webkit_web_view_can_go_back(WebKitWebView* webView)
2820 {
2821     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), FALSE);
2822
2823     return !!getPage(webView).backForwardList().backItem();
2824 }
2825
2826 /**
2827  * webkit_web_view_go_forward:
2828  * @web_view: a #WebKitWebView
2829  *
2830  * Loads the next history item.
2831  * You can monitor the load operation by connecting to
2832  * #WebKitWebView::load-changed signal.
2833  */
2834 void webkit_web_view_go_forward(WebKitWebView* webView)
2835 {
2836     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
2837
2838     getPage(webView).goForward();
2839 }
2840
2841 /**
2842  * webkit_web_view_can_go_forward:
2843  * @web_view: a #WebKitWebView
2844  *
2845  * Determines whether @web_view has a next history item.
2846  *
2847  * Returns: %TRUE if able to move forward or %FALSE otherwise.
2848  */
2849 gboolean webkit_web_view_can_go_forward(WebKitWebView* webView)
2850 {
2851     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), FALSE);
2852
2853     return !!getPage(webView).backForwardList().forwardItem();
2854 }
2855
2856 /**
2857  * webkit_web_view_get_uri:
2858  * @web_view: a #WebKitWebView
2859  *
2860  * Returns the current active URI of @web_view. The active URI might change during
2861  * a load operation:
2862  *
2863  * <orderedlist>
2864  * <listitem><para>
2865  *   When nothing has been loaded yet on @web_view the active URI is %NULL.
2866  * </para></listitem>
2867  * <listitem><para>
2868  *   When a new load operation starts the active URI is the requested URI:
2869  *   <itemizedlist>
2870  *   <listitem><para>
2871  *     If the load operation was started by webkit_web_view_load_uri(),
2872  *     the requested URI is the given one.
2873  *   </para></listitem>
2874  *   <listitem><para>
2875  *     If the load operation was started by webkit_web_view_load_html(),
2876  *     the requested URI is "about:blank".
2877  *   </para></listitem>
2878  *   <listitem><para>
2879  *     If the load operation was started by webkit_web_view_load_alternate_html(),
2880  *     the requested URI is content URI provided.
2881  *   </para></listitem>
2882  *   <listitem><para>
2883  *     If the load operation was started by webkit_web_view_go_back() or
2884  *     webkit_web_view_go_forward(), the requested URI is the original URI
2885  *     of the previous/next item in the #WebKitBackForwardList of @web_view.
2886  *   </para></listitem>
2887  *   <listitem><para>
2888  *     If the load operation was started by
2889  *     webkit_web_view_go_to_back_forward_list_item(), the requested URI
2890  *     is the opriginal URI of the given #WebKitBackForwardListItem.
2891  *   </para></listitem>
2892  *   </itemizedlist>
2893  * </para></listitem>
2894  * <listitem><para>
2895  *   If there is a server redirection during the load operation,
2896  *   the active URI is the redirected URI. When the signal
2897  *   #WebKitWebView::load-changed is emitted with %WEBKIT_LOAD_REDIRECTED
2898  *   event, the active URI is already updated to the redirected URI.
2899  * </para></listitem>
2900  * <listitem><para>
2901  *   When the signal #WebKitWebView::load-changed is emitted
2902  *   with %WEBKIT_LOAD_COMMITTED event, the active URI is the final
2903  *   one and it will not change unless a new load operation is started
2904  *   or a navigation action within the same page is performed.
2905  * </para></listitem>
2906  * </orderedlist>
2907  *
2908  * You can monitor the active URI by connecting to the notify::uri
2909  * signal of @web_view.
2910  *
2911  * Returns: the current active URI of @web_view or %NULL
2912  *    if nothing has been loaded yet.
2913  */
2914 const gchar* webkit_web_view_get_uri(WebKitWebView* webView)
2915 {
2916     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0);
2917
2918     return webView->priv->activeURI.data();
2919 }
2920
2921 #if PLATFORM(GTK)
2922 /**
2923  * webkit_web_view_get_favicon:
2924  * @web_view: a #WebKitWebView
2925  *
2926  * Returns favicon currently associated to @web_view, if any. You can
2927  * connect to notify::favicon signal of @web_view to be notified when
2928  * the favicon is available.
2929  *
2930  * Returns: (transfer none): a pointer to a #cairo_surface_t with the
2931  *    favicon or %NULL if there's no icon associated with @web_view.
2932  */
2933 cairo_surface_t* webkit_web_view_get_favicon(WebKitWebView* webView)
2934 {
2935     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0);
2936     if (webView->priv->activeURI.isNull())
2937         return 0;
2938
2939     return webView->priv->favicon.get();
2940 }
2941 #endif
2942
2943 /**
2944  * webkit_web_view_get_custom_charset:
2945  * @web_view: a #WebKitWebView
2946  *
2947  * Returns the current custom character encoding name of @web_view.
2948  *
2949  * Returns: the current custom character encoding name or %NULL if no
2950  *    custom character encoding has been set.
2951  */
2952 const gchar* webkit_web_view_get_custom_charset(WebKitWebView* webView)
2953 {
2954     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0);
2955
2956     String customTextEncoding = getPage(webView).customTextEncodingName();
2957     if (customTextEncoding.isEmpty())
2958         return 0;
2959
2960     webView->priv->customTextEncoding = customTextEncoding.utf8();
2961     return webView->priv->customTextEncoding.data();
2962 }
2963
2964 /**
2965  * webkit_web_view_set_custom_charset:
2966  * @web_view: a #WebKitWebView
2967  * @charset: (allow-none): a character encoding name or %NULL
2968  *
2969  * Sets the current custom character encoding override of @web_view. The custom
2970  * character encoding will override any text encoding detected via HTTP headers or
2971  * META tags. Calling this method will stop any current load operation and reload the
2972  * current page. Setting the custom character encoding to %NULL removes the character
2973  * encoding override.
2974  */
2975 void webkit_web_view_set_custom_charset(WebKitWebView* webView, const gchar* charset)
2976 {
2977     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
2978
2979     getPage(webView).setCustomTextEncodingName(String::fromUTF8(charset));
2980 }
2981
2982 /**
2983  * webkit_web_view_get_estimated_load_progress:
2984  * @web_view: a #WebKitWebView
2985  *
2986  * Gets the value of the #WebKitWebView:estimated-load-progress property.
2987  * You can monitor the estimated progress of a load operation by
2988  * connecting to the notify::estimated-load-progress signal of @web_view.
2989  *
2990  * Returns: an estimate of the of the percent complete for a document
2991  *     load as a range from 0.0 to 1.0.
2992  */
2993 gdouble webkit_web_view_get_estimated_load_progress(WebKitWebView* webView)
2994 {
2995     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0);
2996     return getPage(webView).pageLoadState().estimatedProgress();
2997 }
2998
2999 /**
3000  * webkit_web_view_get_back_forward_list:
3001  * @web_view: a #WebKitWebView
3002  *
3003  * Obtains the #WebKitBackForwardList associated with the given #WebKitWebView. The
3004  * #WebKitBackForwardList is owned by the #WebKitWebView.
3005  *
3006  * Returns: (transfer none): the #WebKitBackForwardList
3007  */
3008 WebKitBackForwardList* webkit_web_view_get_back_forward_list(WebKitWebView* webView)
3009 {
3010     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0);
3011
3012     return webView->priv->backForwardList.get();
3013 }
3014
3015 /**
3016  * webkit_web_view_go_to_back_forward_list_item:
3017  * @web_view: a #WebKitWebView
3018  * @list_item: a #WebKitBackForwardListItem
3019  *
3020  * Loads the specific history item @list_item.
3021  * You can monitor the load operation by connecting to
3022  * #WebKitWebView::load-changed signal.
3023  */
3024 void webkit_web_view_go_to_back_forward_list_item(WebKitWebView* webView, WebKitBackForwardListItem* listItem)
3025 {
3026     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
3027     g_return_if_fail(WEBKIT_IS_BACK_FORWARD_LIST_ITEM(listItem));
3028
3029     getPage(webView).goToBackForwardItem(*webkitBackForwardListItemGetItem(listItem));
3030 }
3031
3032 /**
3033  * webkit_web_view_set_settings:
3034  * @web_view: a #WebKitWebView
3035  * @settings: a #WebKitSettings
3036  *
3037  * Sets the #WebKitSettings to be applied to @web_view. The
3038  * existing #WebKitSettings of @web_view will be replaced by
3039  * @settings. New settings are applied immediately on @web_view.
3040  * The same #WebKitSettings object can be shared
3041  * by multiple #WebKitWebView<!-- -->s.
3042  */
3043 void webkit_web_view_set_settings(WebKitWebView* webView, WebKitSettings* settings)
3044 {
3045     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
3046     g_return_if_fail(WEBKIT_IS_SETTINGS(settings));
3047
3048     if (webView->priv->settings == settings)
3049         return;
3050
3051     // The "settings" property is set on construction, and in that
3052     // case webkit_web_view_set_settings() will be called *before*
3053     // any settings have been assigned. In that case there are no
3054     // signal handlers to disconnect.
3055     if (webView->priv->settings)
3056         webkitWebViewDisconnectSettingsSignalHandlers(webView);
3057
3058     webView->priv->settings = settings;
3059     webkitWebViewUpdateSettings(webView);
3060     g_object_notify(G_OBJECT(webView), "settings");
3061 }
3062
3063 /**
3064  * webkit_web_view_get_settings:
3065  * @web_view: a #WebKitWebView
3066  *
3067  * Gets the #WebKitSettings currently applied to @web_view.
3068  * If no other #WebKitSettings have been explicitly applied to
3069  * @web_view with webkit_web_view_set_settings(), the default
3070  * #WebKitSettings will be returned. This method always returns
3071  * a valid #WebKitSettings object.
3072  * To modify any of the @web_view settings, you can either create
3073  * a new #WebKitSettings object with webkit_settings_new(), setting
3074  * the desired preferences, and then replace the existing @web_view
3075  * settings with webkit_web_view_set_settings() or get the existing
3076  * @web_view settings and update it directly. #WebKitSettings objects
3077  * can be shared by multiple #WebKitWebView<!-- -->s, so modifying
3078  * the settings of a #WebKitWebView would affect other
3079  * #WebKitWebView<!-- -->s using the same #WebKitSettings.
3080  *
3081  * Returns: (transfer none): the #WebKitSettings attached to @web_view
3082  */
3083 WebKitSettings* webkit_web_view_get_settings(WebKitWebView* webView)
3084 {
3085     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), nullptr);
3086     return webView->priv->settings.get();
3087 }
3088
3089 /**
3090  * webkit_web_view_get_window_properties:
3091  * @web_view: a #WebKitWebView
3092  *
3093  * Get the #WebKitWindowProperties object containing the properties
3094  * that the window containing @web_view should have.
3095  *
3096  * Returns: (transfer none): the #WebKitWindowProperties of @web_view
3097  */
3098 WebKitWindowProperties* webkit_web_view_get_window_properties(WebKitWebView* webView)
3099 {
3100     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0);
3101
3102     return webView->priv->windowProperties.get();
3103 }
3104
3105 /**
3106  * webkit_web_view_set_zoom_level:
3107  * @web_view: a #WebKitWebView
3108  * @zoom_level: the zoom level
3109  *
3110  * Set the zoom level of @web_view, i.e. the factor by which the
3111  * view contents are scaled with respect to their original size.
3112  */
3113 void webkit_web_view_set_zoom_level(WebKitWebView* webView, gdouble zoomLevel)
3114 {
3115     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
3116
3117     if (webkit_web_view_get_zoom_level(webView) == zoomLevel)
3118         return;
3119
3120     auto& page = getPage(webView);
3121     page.scalePage(1.0, IntPoint()); // Reset page scale when zoom level is changed
3122     if (webkit_settings_get_zoom_text_only(webView->priv->settings.get()))
3123         page.setTextZoomFactor(zoomLevel);
3124     else
3125         page.setPageZoomFactor(zoomLevel);
3126     g_object_notify(G_OBJECT(webView), "zoom-level");
3127 }
3128
3129 /**
3130  * webkit_web_view_get_zoom_level:
3131  * @web_view: a #WebKitWebView
3132  *
3133  * Get the zoom level of @web_view, i.e. the factor by which the
3134  * view contents are scaled with respect to their original size.
3135  *
3136  * Returns: the current zoom level of @web_view
3137  */
3138 gdouble webkit_web_view_get_zoom_level(WebKitWebView* webView)
3139 {
3140     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 1);
3141
3142     auto& page = getPage(webView);
3143     gboolean zoomTextOnly = webkit_settings_get_zoom_text_only(webView->priv->settings.get());
3144     return zoomTextOnly ? page.textZoomFactor() : page.pageZoomFactor();
3145 }
3146
3147 /**
3148  * webkit_web_view_can_execute_editing_command:
3149  * @web_view: a #WebKitWebView
3150  * @command: the command to check
3151  * @cancellable: (allow-none): a #GCancellable or %NULL to ignore
3152  * @callback: (scope async): a #GAsyncReadyCallback to call when the request is satisfied
3153  * @user_data: (closure): the data to pass to callback function
3154  *
3155  * Asynchronously check if it is possible to execute the given editing command.
3156  *
3157  * When the operation is finished, @callback will be called. You can then call
3158  * webkit_web_view_can_execute_editing_command_finish() to get the result of the operation.
3159  */
3160 void webkit_web_view_can_execute_editing_command(WebKitWebView* webView, const char* command, GCancellable* cancellable, GAsyncReadyCallback callback, gpointer userData)
3161 {
3162     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
3163     g_return_if_fail(command);
3164
3165     GRefPtr<GTask> task = adoptGRef(g_task_new(webView, cancellable, callback, userData));
3166     getPage(webView).validateCommand(String::fromUTF8(command), [task = WTFMove(task)](const String&, bool isEnabled, int32_t, WebKit::CallbackBase::Error) {
3167         g_task_return_boolean(task.get(), isEnabled);
3168     });
3169 }
3170
3171 /**
3172  * webkit_web_view_can_execute_editing_command_finish:
3173  * @web_view: a #WebKitWebView
3174  * @result: a #GAsyncResult
3175  * @error: return location for error or %NULL to ignore
3176  *
3177  * Finish an asynchronous operation started with webkit_web_view_can_execute_editing_command().
3178  *
3179  * Returns: %TRUE if the editing command can be executed or %FALSE otherwise
3180  */
3181 gboolean webkit_web_view_can_execute_editing_command_finish(WebKitWebView* webView, GAsyncResult* result, GError** error)
3182 {
3183     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), FALSE);
3184     g_return_val_if_fail(g_task_is_valid(result, webView), FALSE);
3185
3186     return g_task_propagate_boolean(G_TASK(result), error);
3187 }
3188
3189 /**
3190  * webkit_web_view_execute_editing_command:
3191  * @web_view: a #WebKitWebView
3192  * @command: the command to execute
3193  *
3194  * Request to execute the given @command for @web_view. You can use
3195  * webkit_web_view_can_execute_editing_command() to check whether
3196  * it's possible to execute the command.
3197  */
3198 void webkit_web_view_execute_editing_command(WebKitWebView* webView, const char* command)
3199 {
3200     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
3201     g_return_if_fail(command);
3202
3203     getPage(webView).executeEditCommand(String::fromUTF8(command));
3204 }
3205
3206 /**
3207  * webkit_web_view_execute_editing_command_with_argument:
3208  * @web_view: a #WebKitWebView
3209  * @command: the command to execute
3210  * @argument: the command argument
3211  *
3212  * Request to execute the given @command with @argument for @web_view. You can use
3213  * webkit_web_view_can_execute_editing_command() to check whether
3214  * it's possible to execute the command.
3215  *
3216  * Since: 2.10
3217  */
3218 void webkit_web_view_execute_editing_command_with_argument(WebKitWebView* webView, const char* command, const char* argument)
3219 {
3220     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
3221     g_return_if_fail(command);
3222     g_return_if_fail(argument);
3223
3224     getPage(webView).executeEditCommand(String::fromUTF8(command), String::fromUTF8(argument));
3225 }
3226
3227 /**
3228  * webkit_web_view_get_find_controller:
3229  * @web_view: the #WebKitWebView
3230  *
3231  * Gets the #WebKitFindController that will allow the caller to query
3232  * the #WebKitWebView for the text to look for.
3233  *
3234  * Returns: (transfer none): the #WebKitFindController associated to
3235  * this particular #WebKitWebView.
3236  */
3237 WebKitFindController* webkit_web_view_get_find_controller(WebKitWebView* webView)
3238 {
3239     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0);
3240
3241     if (!webView->priv->findController)
3242         webView->priv->findController = adoptGRef(WEBKIT_FIND_CONTROLLER(g_object_new(WEBKIT_TYPE_FIND_CONTROLLER, "web-view", webView, NULL)));
3243
3244     return webView->priv->findController.get();
3245 }
3246
3247 #if PLATFORM(GTK)
3248 /**
3249  * webkit_web_view_get_javascript_global_context: (skip)
3250  * @web_view: a #WebKitWebView
3251  *
3252  * Get the global JavaScript context used by @web_view to deserialize the
3253  * result values of scripts executed with webkit_web_view_run_javascript().
3254  *
3255  * Returns: the <function>JSGlobalContextRef</function> used by @web_view to deserialize
3256  *    the result values of scripts.
3257  *
3258  * Deprecated: 2.22: Use jsc_value_get_context() instead.
3259  */
3260 JSGlobalContextRef webkit_web_view_get_javascript_global_context(WebKitWebView* webView)
3261 {
3262     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), nullptr);
3263
3264     // We keep a reference to the js context in the view only when this method is called
3265     // for backwards compatibility.
3266     if (!webView->priv->jsContext)
3267         webView->priv->jsContext = SharedJavascriptContext::singleton().getOrCreateContext();
3268     return jscContextGetJSContext(webView->priv->jsContext.get());
3269 }
3270 #endif
3271
3272 static void webkitWebViewRunJavaScriptCallback(API::SerializedScriptValue* wkSerializedScriptValue, const ExceptionDetails& exceptionDetails, GTask* task)
3273 {
3274     if (g_task_return_error_if_cancelled(task))
3275         return;
3276
3277     if (!wkSerializedScriptValue) {
3278         StringBuilder builder;
3279         if (!exceptionDetails.sourceURL.isEmpty()) {
3280             builder.append(exceptionDetails.sourceURL);
3281             if (exceptionDetails.lineNumber > 0) {
3282                 builder.append(':');
3283                 builder.appendNumber(exceptionDetails.lineNumber);
3284             }
3285             if (exceptionDetails.columnNumber > 0) {
3286                 builder.append(':');
3287                 builder.appendNumber(exceptionDetails.columnNumber);
3288             }
3289             builder.appendLiteral(": ");
3290         }
3291         builder.append(exceptionDetails.message);
3292         g_task_return_new_error(task, WEBKIT_JAVASCRIPT_ERROR, WEBKIT_JAVASCRIPT_ERROR_SCRIPT_FAILED,
3293             "%s", builder.toString().utf8().data());
3294         return;
3295     }
3296
3297     g_task_return_pointer(task, webkitJavascriptResultCreate(wkSerializedScriptValue->internalRepresentation()),
3298         reinterpret_cast<GDestroyNotify>(webkit_javascript_result_unref));
3299 }
3300
3301 /**
3302  * webkit_web_view_run_javascript:
3303  * @web_view: a #WebKitWebView
3304  * @script: the script to run
3305  * @cancellable: (allow-none): a #GCancellable or %NULL to ignore
3306  * @callback: (scope async): a #GAsyncReadyCallback to call when the script finished
3307  * @user_data: (closure): the data to pass to callback function
3308  *
3309  * Asynchronously run @script in the context of the current page in @web_view. If
3310  * WebKitSettings:enable-javascript is FALSE, this method will do nothing.
3311  *
3312  * When the operation is finished, @callback will be called. You can then call
3313  * webkit_web_view_run_javascript_finish() to get the result of the operation.
3314  */
3315 void webkit_web_view_run_javascript(WebKitWebView* webView, const gchar* script, GCancellable* cancellable, GAsyncReadyCallback callback, gpointer userData)
3316 {
3317     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
3318     g_return_if_fail(script);
3319
3320     GRefPtr<GTask> task = adoptGRef(g_task_new(webView, cancellable, callback, userData));
3321     getPage(webView).runJavaScriptInMainFrame(String::fromUTF8(script), true, [task = WTFMove(task)](API::SerializedScriptValue* serializedScriptValue, bool, const ExceptionDetails& exceptionDetails, WebKit::CallbackBase::Error) {
3322         webkitWebViewRunJavaScriptCallback(serializedScriptValue, exceptionDetails, task.get());
3323     });
3324 }
3325
3326 /**
3327  * webkit_web_view_run_javascript_finish:
3328  * @web_view: a #WebKitWebView
3329  * @result: a #GAsyncResult
3330  * @error: return location for error or %NULL to ignore
3331  *
3332  * Finish an asynchronous operation started with webkit_web_view_run_javascript().
3333  *
3334  * This is an example of using webkit_web_view_run_javascript() with a script returning
3335  * a string:
3336  *
3337  * <informalexample><programlisting>
3338  * static void
3339  * web_view_javascript_finished (GObject      *object,
3340  *                               GAsyncResult *result,
3341  *                               gpointer      user_data)
3342  * {
3343  *     WebKitJavascriptResult *js_result;
3344  *     JSCValue               *value;
3345  *     GError                 *error = NULL;
3346  *
3347  *     js_result = webkit_web_view_run_javascript_finish (WEBKIT_WEB_VIEW (object), result, &error);
3348  *     if (!js_result) {
3349  *         g_warning ("Error running javascript: %s", error->message);
3350  *         g_error_free (error);
3351  *         return;
3352  *     }
3353  *
3354  *     value = webkit_javascript_result_get_js_value (js_result);
3355  *     if (jsc_value_is_string (value)) {
3356  *         JSCException *exception;
3357  *         gchar        *str_value;
3358  *
3359  *         str_value = jsc_value_to_string (value);
3360  *         exception = jsc_context_get_exception (jsc_value_get_context (value));
3361  *         if (exception)
3362  *             g_warning ("Error running javascript: %s", jsc_exception_get_message (exception));
3363  *         else
3364  *             g_print ("Script result: %s\n", str_value);
3365  *         g_free (str_value);
3366  *     } else {
3367  *         g_warning ("Error running javascript: unexpected return value");
3368  *     }
3369  *     webkit_javascript_result_unref (js_result);
3370  * }
3371  *
3372  * static void
3373  * web_view_get_link_url (WebKitWebView *web_view,
3374  *                        const gchar   *link_id)
3375  * {
3376  *     gchar *script;
3377  *
3378  *     script = g_strdup_printf ("window.document.getElementById('%s').href;", link_id);
3379  *     webkit_web_view_run_javascript (web_view, script, NULL, web_view_javascript_finished, NULL);
3380  *     g_free (script);
3381  * }
3382  * </programlisting></informalexample>
3383  *
3384  * Returns: (transfer full): a #WebKitJavascriptResult with the result of the last executed statement in @script
3385  *    or %NULL in case of error
3386  */
3387 WebKitJavascriptResult* webkit_web_view_run_javascript_finish(WebKitWebView* webView, GAsyncResult* result, GError** error)
3388 {
3389     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), nullptr);
3390     g_return_val_if_fail(g_task_is_valid(result, webView), nullptr);
3391
3392     return static_cast<WebKitJavascriptResult*>(g_task_propagate_pointer(G_TASK(result), error));
3393 }
3394
3395 /**
3396  * webkit_web_view_run_javascript_in_world:
3397  * @web_view: a #WebKitWebView
3398  * @script: the script to run
3399  * @world_name: the name of a #WebKitScriptWorld
3400  * @cancellable: (allow-none): a #GCancellable or %NULL to ignore
3401  * @callback: (scope async): a #GAsyncReadyCallback to call when the script finished
3402  * @user_data: (closure): the data to pass to callback function
3403  *
3404  * Asynchronously run @script in the script world with name @world_name of the current page context in @web_view.
3405  * If WebKitSettings:enable-javascript is FALSE, this method will do nothing.
3406  *
3407  * When the operation is finished, @callback will be called. You can then call
3408  * webkit_web_view_run_javascript_in_world_finish() to get the result of the operation.
3409  *
3410  * Since: 2.22
3411  */
3412 void webkit_web_view_run_javascript_in_world(WebKitWebView* webView, const gchar* script, const char* worldName, GCancellable* cancellable, GAsyncReadyCallback callback, gpointer userData)
3413 {
3414     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
3415     g_return_if_fail(script);
3416     g_return_if_fail(worldName);
3417
3418     GRefPtr<GTask> task = adoptGRef(g_task_new(webView, cancellable, callback, userData));
3419     getPage(webView).runJavaScriptInMainFrameScriptWorld(String::fromUTF8(script), true, String::fromUTF8(worldName), [task = WTFMove(task)](API::SerializedScriptValue* serializedScriptValue, bool, const ExceptionDetails& exceptionDetails, WebKit::CallbackBase::Error) {
3420         webkitWebViewRunJavaScriptCallback(serializedScriptValue, exceptionDetails, task.get());
3421     });
3422 }
3423
3424 /**
3425  * webkit_web_view_run_javascript_in_world_finish:
3426  * @web_view: a #WebKitWebView
3427  * @result: a #GAsyncResult
3428  * @error: return location for error or %NULL to ignore
3429  *
3430  * Finish an asynchronous operation started with webkit_web_view_run_javascript_in_world().
3431  *
3432  * Returns: (transfer full): a #WebKitJavascriptResult with the result of the last executed statement in @script
3433  *    or %NULL in case of error
3434  *
3435  * Since: 2.22
3436  */
3437 WebKitJavascriptResult* webkit_web_view_run_javascript_in_world_finish(WebKitWebView* webView, GAsyncResult* result, GError** error)
3438 {
3439     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), nullptr);
3440     g_return_val_if_fail(g_task_is_valid(result, webView), nullptr);
3441
3442     return static_cast<WebKitJavascriptResult*>(g_task_propagate_pointer(G_TASK(result), error));
3443 }
3444
3445 static void resourcesStreamReadCallback(GObject* object, GAsyncResult* result, gpointer userData)
3446 {
3447     GRefPtr<GTask> task = adoptGRef(G_TASK(userData));
3448
3449     GError* error = 0;
3450     g_output_stream_splice_finish(G_OUTPUT_STREAM(object), result, &error);
3451     if (error) {
3452         g_task_return_error(task.get(), error);
3453         return;
3454     }
3455
3456     WebKitWebView* webView = WEBKIT_WEB_VIEW(g_task_get_source_object(task.get()));
3457     gpointer outputStreamData = g_memory_output_stream_get_data(G_MEMORY_OUTPUT_STREAM(object));
3458     getPage(webView).runJavaScriptInMainFrame(String::fromUTF8(reinterpret_cast<const gchar*>(outputStreamData)), true,
3459         [task](API::SerializedScriptValue* serializedScriptValue, bool, const ExceptionDetails& exceptionDetails, WebKit::CallbackBase::Error) {
3460             webkitWebViewRunJavaScriptCallback(serializedScriptValue, exceptionDetails, task.get());
3461         });
3462 }
3463
3464 /**
3465  * webkit_web_view_run_javascript_from_gresource:
3466  * @web_view: a #WebKitWebView
3467  * @resource: the location of the resource to load
3468  * @cancellable: (allow-none): a #GCancellable or %NULL to ignore
3469  * @callback: (scope async): a #GAsyncReadyCallback to call when the script finished
3470  * @user_data: (closure): the data to pass to callback function
3471  *
3472  * Asynchronously run the script from @resource in the context of the
3473  * current page in @web_view.
3474  *
3475  * When the operation is finished, @callback will be called. You can
3476  * then call webkit_web_view_run_javascript_from_gresource_finish() to get the result
3477  * of the operation.
3478  */
3479 void webkit_web_view_run_javascript_from_gresource(WebKitWebView* webView, const gchar* resource, GCancellable* cancellable, GAsyncReadyCallback callback, gpointer userData)
3480 {
3481     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
3482     g_return_if_fail(resource);
3483
3484     GError* error = 0;
3485     GRefPtr<GInputStream> inputStream = adoptGRef(g_resources_open_stream(resource, G_RESOURCE_LOOKUP_FLAGS_NONE, &error));
3486     if (error) {
3487         g_task_report_error(webView, callback, userData, 0, error);
3488         return;
3489     }
3490
3491     GTask* task = g_task_new(webView, cancellable, callback, userData);
3492     GRefPtr<GOutputStream> outputStream = adoptGRef(g_memory_output_stream_new(0, 0, fastRealloc, fastFree));
3493     g_output_stream_splice_async(outputStream.get(), inputStream.get(),
3494         static_cast<GOutputStreamSpliceFlags>(G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE | G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET),
3495         G_PRIORITY_DEFAULT, cancellable, resourcesStreamReadCallback, task);
3496 }
3497
3498 /**
3499  * webkit_web_view_run_javascript_from_gresource_finish:
3500  * @web_view: a #WebKitWebView
3501  * @result: a #GAsyncResult
3502  * @error: return location for error or %NULL to ignore
3503  *
3504  * Finish an asynchronous operation started with webkit_web_view_run_javascript_from_gresource().
3505  *
3506  * Check webkit_web_view_run_javascript_finish() for a usage example.
3507  *
3508  * Returns: (transfer full): a #WebKitJavascriptResult with the result of the last executed statement in @script
3509  *    or %NULL in case of error
3510  */
3511 WebKitJavascriptResult* webkit_web_view_run_javascript_from_gresource_finish(WebKitWebView* webView, GAsyncResult* result, GError** error)
3512 {
3513     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0);
3514     g_return_val_if_fail(g_task_is_valid(result, webView), 0);
3515
3516     return static_cast<WebKitJavascriptResult*>(g_task_propagate_pointer(G_TASK(result), error));
3517 }
3518
3519 /**
3520  * webkit_web_view_get_main_resource:
3521  * @web_view: a #WebKitWebView
3522  *
3523  * Return the main resource of @web_view.
3524  *
3525  * Returns: (transfer none): the main #WebKitWebResource of the view
3526  *    or %NULL if nothing has been loaded.
3527  */
3528 WebKitWebResource* webkit_web_view_get_main_resource(WebKitWebView* webView)
3529 {
3530     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0);
3531
3532     return webView->priv->mainResource.get();
3533 }
3534
3535 #if PLATFORM(GTK)
3536 /**
3537  * webkit_web_view_get_inspector:
3538  * @web_view: a #WebKitWebView
3539  *
3540  * Get the #WebKitWebInspector associated to @web_view
3541  *
3542  * Returns: (transfer none): the #WebKitWebInspector of @web_view
3543  */
3544 WebKitWebInspector* webkit_web_view_get_inspector(WebKitWebView* webView)
3545 {
3546     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0);
3547
3548     if (!webView->priv->inspector)
3549         webView->priv->inspector = adoptGRef(webkitWebInspectorCreate(getPage(webView).inspector()));
3550
3551     return webView->priv->inspector.get();
3552 }
3553 #endif
3554
3555 /**
3556  * webkit_web_view_can_show_mime_type:
3557  * @web_view: a #WebKitWebView
3558  * @mime_type: a MIME type
3559  *
3560  * Whether or not a MIME type can be displayed in @web_view.
3561  *
3562  * Returns: %TRUE if the MIME type @mime_type can be displayed or %FALSE otherwise
3563  */
3564 gboolean webkit_web_view_can_show_mime_type(WebKitWebView* webView, const char* mimeType)
3565 {
3566     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), FALSE);
3567     g_return_val_if_fail(mimeType, FALSE);
3568
3569     return getPage(webView).canShowMIMEType(String::fromUTF8(mimeType));
3570 }
3571
3572 struct ViewSaveAsyncData {
3573     RefPtr<API::Data> webData;
3574     GRefPtr<GFile> file;
3575 };
3576 WEBKIT_DEFINE_ASYNC_DATA_STRUCT(ViewSaveAsyncData)
3577
3578 static void fileReplaceContentsCallback(GObject* object, GAsyncResult* result, gpointer data)
3579 {
3580     GRefPtr<GTask> task = adoptGRef(G_TASK(data));
3581     GError* error = 0;
3582     if (!g_file_replace_contents_finish(G_FILE(object), result, 0, &error)) {
3583         g_task_return_error(task.get(), error);
3584         return;
3585     }
3586
3587     g_task_return_boolean(task.get(), TRUE);
3588 }
3589
3590 static void getContentsAsMHTMLDataCallback(API::Data* wkData, GTask* taskPtr)
3591 {
3592     auto task = adoptGRef(taskPtr);
3593     if (g_task_return_error_if_cancelled(task.get()))
3594         return;
3595
3596     ViewSaveAsyncData* data = static_cast<ViewSaveAsyncData*>(g_task_get_task_data(task.get()));
3597     // We need to retain the data until the asyncronous process
3598     // initiated by the user has finished completely.
3599     data->webData = wkData;
3600
3601     // If we are saving to a file we need to write the data on disk before finishing.
3602     if (g_task_get_source_tag(task.get()) == webkit_web_view_save_to_file) {
3603         ASSERT(G_IS_FILE(data->file.get()));
3604         GCancellable* cancellable = g_task_get_cancellable(task.get());
3605         g_file_replace_contents_async(data->file.get(), reinterpret_cast<const gchar*>(data->webData->bytes()), data->webData->size(),
3606             0, FALSE, G_FILE_CREATE_REPLACE_DESTINATION, cancellable, fileReplaceContentsCallback, task.leakRef());
3607         return;
3608     }
3609
3610     g_task_return_boolean(task.get(), TRUE);
3611 }
3612
3613 /**
3614  * webkit_web_view_save:
3615  * @web_view: a #WebKitWebView
3616  * @save_mode: the #WebKitSaveMode specifying how the web page should be saved.
3617  * @cancellable: (allow-none): a #GCancellable or %NULL to ignore
3618  * @callback: (scope async): a #GAsyncReadyCallback to call when the request is satisfied
3619  * @user_data: (closure): the data to pass to callback function
3620  *
3621  * Asynchronously save the current web page associated to the
3622  * #WebKitWebView into a self-contained format using the mode
3623  * specified in @save_mode.
3624  *
3625  * When the operation is finished, @callback will be called. You can
3626  * then call webkit_web_view_save_finish() to get the result of the
3627  * operation.
3628  */
3629 void webkit_web_view_save(WebKitWebView* webView, WebKitSaveMode saveMode, GCancellable* cancellable, GAsyncReadyCallback callback, gpointer userData)
3630 {
3631     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
3632
3633     // We only support MHTML at the moment.
3634     g_return_if_fail(saveMode == WEBKIT_SAVE_MODE_MHTML);
3635
3636     GTask* task = g_task_new(webView, cancellable, callback, userData);
3637     g_task_set_source_tag(task, reinterpret_cast<gpointer>(webkit_web_view_save));
3638     g_task_set_task_data(task, createViewSaveAsyncData(), reinterpret_cast<GDestroyNotify>(destroyViewSaveAsyncData));
3639     getPage(webView).getContentsAsMHTMLData([task](API::Data* data, WebKit::CallbackBase::Error) {
3640         getContentsAsMHTMLDataCallback(data, task);
3641     });
3642 }
3643
3644 /**
3645  * webkit_web_view_save_finish:
3646  * @web_view: a #WebKitWebView
3647  * @result: a #GAsyncResult
3648  * @error: return location for error or %NULL to ignore
3649  *
3650  * Finish an asynchronous operation started with webkit_web_view_save().
3651  *
3652  * Returns: (transfer full): a #GInputStream with the result of saving
3653  *    the current web page or %NULL in case of error.
3654  */
3655 GInputStream* webkit_web_view_save_finish(WebKitWebView* webView, GAsyncResult* result, GError** error)
3656 {
3657     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0);
3658     g_return_val_if_fail(g_task_is_valid(result, webView), 0);
3659
3660     GTask* task = G_TASK(result);
3661     if (!g_task_propagate_boolean(task, error))
3662         return 0;
3663
3664     GInputStream* dataStream = g_memory_input_stream_new();
3665     ViewSaveAsyncData* data = static_cast<ViewSaveAsyncData*>(g_task_get_task_data(task));
3666     gsize length = data->webData->size();
3667     if (length)
3668         g_memory_input_stream_add_data(G_MEMORY_INPUT_STREAM(dataStream), g_memdup(data->webData->bytes(), length), length, g_free);
3669
3670     return dataStream;
3671 }
3672
3673 /**
3674  * webkit_web_view_save_to_file:
3675  * @web_view: a #WebKitWebView
3676  * @file: the #GFile where the current web page should be saved to.
3677  * @save_mode: the #WebKitSaveMode specifying how the web page should be saved.
3678  * @cancellable: (allow-none): a #GCancellable or %NULL to ignore
3679  * @callback: (scope async): a #GAsyncReadyCallback to call when the request is satisfied
3680  * @user_data: (closure): the data to pass to callback function
3681  *
3682  * Asynchronously save the current web page associated to the
3683  * #WebKitWebView into a self-contained format using the mode
3684  * specified in @save_mode and writing it to @file.
3685  *
3686  * When the operation is finished, @callback will be called. You can
3687  * then call webkit_web_view_save_to_file_finish() to get the result of the
3688  * operation.
3689  */
3690 void webkit_web_view_save_to_file(WebKitWebView* webView, GFile* file, WebKitSaveMode saveMode, GCancellable* cancellable, GAsyncReadyCallback callback, gpointer userData)
3691 {
3692     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
3693     g_return_if_fail(G_IS_FILE(file));
3694
3695     // We only support MHTML at the moment.
3696     g_return_if_fail(saveMode == WEBKIT_SAVE_MODE_MHTML);
3697
3698     GTask* task = g_task_new(webView, cancellable, callback, userData);
3699     g_task_set_source_tag(task, reinterpret_cast<gpointer>(webkit_web_view_save_to_file));
3700     ViewSaveAsyncData* data = createViewSaveAsyncData();
3701     data->file = file;
3702     g_task_set_task_data(task, data, reinterpret_cast<GDestroyNotify>(destroyViewSaveAsyncData));
3703
3704     getPage(webView).getContentsAsMHTMLData([task](API::Data* data, WebKit::CallbackBase::Error) {
3705         getContentsAsMHTMLDataCallback(data, task);
3706     });
3707 }
3708
3709 /**
3710  * webkit_web_view_save_to_file_finish:
3711  * @web_view: a #WebKitWebView
3712  * @result: a #GAsyncResult
3713  * @error: return location for error or %NULL to ignore
3714  *
3715  * Finish an asynchronous operation started with webkit_web_view_save_to_file().
3716  *
3717  * Returns: %TRUE if the web page was successfully saved to a file or %FALSE otherwise.
3718  */
3719 gboolean webkit_web_view_save_to_file_finish(WebKitWebView* webView, GAsyncResult* result, GError** error)
3720 {
3721     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), FALSE);
3722     g_return_val_if_fail(g_task_is_valid(result, webView), FALSE);
3723
3724     return g_task_propagate_boolean(G_TASK(result), error);
3725 }
3726
3727 /**
3728  * webkit_web_view_download_uri:
3729  * @web_view: a #WebKitWebView
3730  * @uri: the URI to download
3731  *
3732  * Requests downloading of the specified URI string for @web_view.
3733  *
3734  * Returns: (transfer full): a new #WebKitDownload representing
3735  *    the download operation.
3736  */
3737 WebKitDownload* webkit_web_view_download_uri(WebKitWebView* webView, const char* uri)
3738 {
3739     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), nullptr);
3740     g_return_val_if_fail(uri, nullptr);
3741
3742     GRefPtr<WebKitDownload> download = webkitWebContextStartDownload(webView->priv->context.get(), uri, &getPage(webView));
3743     return download.leakRef();
3744 }
3745
3746 /**
3747  * webkit_web_view_get_tls_info:
3748  * @web_view: a #WebKitWebView
3749  * @certificate: (out) (transfer none): return location for a #GTlsCertificate
3750  * @errors: (out): return location for a #GTlsCertificateFlags the verification status of @certificate
3751  *
3752  * Retrieves the #GTlsCertificate associated with the main resource of @web_view,
3753  * and the #GTlsCertificateFlags showing what problems, if any, have been found
3754  * with that certificate.
3755  * If the connection is not HTTPS, this function returns %FALSE.
3756  * This function should be called after a response has been received from the
3757  * server, so you can connect to #WebKitWebView::load-changed and call this function
3758  * when it's emitted with %WEBKIT_LOAD_COMMITTED event.
3759  *
3760  * Note that this function provides no information about the security of the web
3761  * page if the current #WebKitTLSErrorsPolicy is @WEBKIT_TLS_ERRORS_POLICY_IGNORE,
3762  * as subresources of the page may be controlled by an attacker. This function
3763  * may safely be used to determine the security status of the current page only
3764  * if the current #WebKitTLSErrorsPolicy is @WEBKIT_TLS_ERRORS_POLICY_FAIL, in
3765  * which case subresources that fail certificate verification will be blocked.
3766  *
3767  * Returns: %TRUE if the @web_view connection uses HTTPS and a response has been received
3768  *    from the server, or %FALSE otherwise.
3769  */
3770 gboolean webkit_web_view_get_tls_info(WebKitWebView* webView, GTlsCertificate** certificate, GTlsCertificateFlags* errors)
3771 {
3772     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), FALSE);
3773
3774     WebFrameProxy* mainFrame = getPage(webView).mainFrame();
3775     if (!mainFrame)
3776         return FALSE;
3777
3778     auto* wkCertificateInfo = mainFrame->certificateInfo();
3779     g_return_val_if_fail(wkCertificateInfo, FALSE);
3780
3781     const auto& certificateInfo = wkCertificateInfo->certificateInfo();
3782     if (certificate)
3783         *certificate = certificateInfo.certificate();
3784     if (errors)
3785         *errors = certificateInfo.tlsErrors();
3786
3787     return !!certificateInfo.certificate();
3788 }
3789
3790 #if PLATFORM(GTK)
3791 void webKitWebViewDidReceiveSnapshot(WebKitWebView* webView, uint64_t callbackID, WebImage* webImage)
3792 {
3793     GRefPtr<GTask> task = webView->priv->snapshotResultsMap.take(callbackID);
3794     if (g_task_return_error_if_cancelled(task.get()))
3795         return;
3796
3797     if (!webImage) {
3798         g_task_return_new_error(task.get(), WEBKIT_SNAPSHOT_ERROR, WEBKIT_SNAPSHOT_ERROR_FAILED_TO_CREATE,
3799             _("There was an error creating the snapshot"));
3800         return;
3801     }
3802
3803     g_task_return_pointer(task.get(), webImage->bitmap().createCairoSurface().leakRef(), reinterpret_cast<GDestroyNotify>(cairo_surface_destroy));
3804 }
3805
3806 static inline unsigned webKitSnapshotOptionsToSnapshotOptions(WebKitSnapshotOptions options)
3807 {
3808     SnapshotOptions snapshotOptions = 0;
3809
3810     if (!(options & WEBKIT_SNAPSHOT_OPTIONS_INCLUDE_SELECTION_HIGHLIGHTING))
3811         snapshotOptions |= SnapshotOptionsExcludeSelectionHighlighting;
3812
3813     return snapshotOptions;
3814 }
3815
3816 static inline SnapshotRegion toSnapshotRegion(WebKitSnapshotRegion region)
3817 {
3818     switch (region) {
3819     case WEBKIT_SNAPSHOT_REGION_VISIBLE:
3820         return SnapshotRegionVisible;
3821     case WEBKIT_SNAPSHOT_REGION_FULL_DOCUMENT:
3822         return SnapshotRegionFullDocument;
3823     default:
3824         ASSERT_NOT_REACHED();
3825         return SnapshotRegionVisible;
3826     }
3827 }
3828
3829 static inline uint64_t generateSnapshotCallbackID()
3830 {
3831     static uint64_t uniqueCallbackID = 1;
3832     return uniqueCallbackID++;
3833 }
3834
3835 /**
3836  * webkit_web_view_get_snapshot:
3837  * @web_view: a #WebKitWebView
3838  * @region: the #WebKitSnapshotRegion for this snapshot
3839  * @options: #WebKitSnapshotOptions for the snapshot
3840  * @cancellable: (allow-none): a #GCancellable
3841  * @callback: (scope async): a #GAsyncReadyCallback
3842  * @user_data: (closure): user data
3843  *
3844  * Asynchronously retrieves a snapshot of @web_view for @region.
3845  * @options specifies how the snapshot should be rendered.
3846  *
3847  * When the operation is finished, @callback will be called. You must
3848  * call webkit_web_view_get_snapshot_finish() to get the result of the
3849  * operation.
3850  */
3851 void webkit_web_view_get_snapshot(WebKitWebView* webView, WebKitSnapshotRegion region, WebKitSnapshotOptions options, GCancellable* cancellable, GAsyncReadyCallback callback, gpointer userData)
3852 {
3853     g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
3854
3855     API::Dictionary::MapType message;
3856     uint64_t callbackID = generateSnapshotCallbackID();
3857     message.set(String::fromUTF8("SnapshotOptions"), API::UInt64::create(static_cast<uint64_t>(webKitSnapshotOptionsToSnapshotOptions(options))));
3858     message.set(String::fromUTF8("SnapshotRegion"), API::UInt64::create(static_cast<uint64_t>(toSnapshotRegion(region))));
3859     message.set(String::fromUTF8("CallbackID"), API::UInt64::create(callbackID));
3860     message.set(String::fromUTF8("TransparentBackground"), API::Boolean::create(options & WEBKIT_SNAPSHOT_OPTIONS_TRANSPARENT_BACKGROUND));
3861
3862     webView->priv->snapshotResultsMap.set(callbackID, adoptGRef(g_task_new(webView, cancellable, callback, userData)));
3863     getPage(webView).postMessageToInjectedBundle(String::fromUTF8("GetSnapshot"), API::Dictionary::create(WTFMove(message)).ptr());
3864 }
3865
3866 /**
3867  * webkit_web_view_get_snapshot_finish:
3868  * @web_view: a #WebKitWebView
3869  * @result: a #GAsyncResult
3870  * @error: return location for error or %NULL to ignore
3871  *
3872  * Finishes an asynchronous operation started with webkit_web_view_get_snapshot().
3873  *
3874  * Returns: (transfer full): a #cairo_surface_t with the retrieved snapshot or %NULL in error.
3875  */
3876 cairo_surface_t* webkit_web_view_get_snapshot_finish(WebKitWebView* webView, GAsyncResult* result, GError** error)
3877 {
3878     g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0);
3879     g_return_val_if_fail(g_task_is_valid(result, webView), 0);
3880
3881     return static_cast<cairo_surface_t*>(g_task_propagate_pointer(G_TASK(result), error));
3882 }
3883 #endif
3884
3885 void webkitWebViewWebProcessTerminated(WebKitWebView* webView, WebKitWebProcessTerminationReason reason)
3886 {
3887 #if PLATFORM(GTK)
3888     if (reason == WEBKIT_WEB_PROCESS_CRASHED) {
3889         gboolean returnValue;
3890         g_signal_emit(webView, signals[WEB_PROCESS_CRASHED], 0, &returnValue);