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