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