2 * Copyright (C) 2011 Igalia S.L.
3 * Portions Copyright (c) 2011 Motorola Mobility, Inc. All rights reserved.
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
15 * You should have received a copy of the GNU Library General Public License
16 * along with this library; see the file COPYING.LIB. If not, write to
17 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
22 #include "WebKitWebView.h"
24 #include "WebContextMenuItem.h"
25 #include "WebContextMenuItemData.h"
26 #include "WebKitBackForwardListPrivate.h"
27 #include "WebKitContextMenuClient.h"
28 #include "WebKitContextMenuItemPrivate.h"
29 #include "WebKitContextMenuPrivate.h"
30 #include "WebKitEnumTypes.h"
31 #include "WebKitError.h"
32 #include "WebKitFormClient.h"
33 #include "WebKitFullscreenClient.h"
34 #include "WebKitHitTestResultPrivate.h"
35 #include "WebKitJavascriptResultPrivate.h"
36 #include "WebKitLoaderClient.h"
37 #include "WebKitMarshal.h"
38 #include "WebKitPolicyClient.h"
39 #include "WebKitPrintOperationPrivate.h"
40 #include "WebKitPrivate.h"
41 #include "WebKitResourceLoadClient.h"
42 #include "WebKitResponsePolicyDecision.h"
43 #include "WebKitScriptDialogPrivate.h"
44 #include "WebKitSettingsPrivate.h"
45 #include "WebKitUIClient.h"
46 #include "WebKitURIResponsePrivate.h"
47 #include "WebKitWebContextPrivate.h"
48 #include "WebKitWebInspectorPrivate.h"
49 #include "WebKitWebResourcePrivate.h"
50 #include "WebKitWebViewBasePrivate.h"
51 #include "WebKitWebViewPrivate.h"
52 #include "WebKitWindowPropertiesPrivate.h"
53 #include "WebPageProxy.h"
54 #include <JavaScriptCore/APICast.h>
55 #include <WebCore/DragIcon.h>
56 #include <WebCore/GOwnPtrGtk.h>
57 #include <WebCore/GtkUtilities.h>
58 #include <glib/gi18n-lib.h>
59 #include <wtf/gobject/GOwnPtr.h>
60 #include <wtf/gobject/GRefPtr.h>
61 #include <wtf/text/CString.h>
63 using namespace WebKit;
64 using namespace WebCore;
84 RESOURCE_LOAD_STARTED,
92 CONTEXT_MENU_DISMISSED,
104 PROP_ESTIMATED_LOAD_PROGRESS,
109 typedef HashMap<uint64_t, GRefPtr<WebKitWebResource> > LoadingResourcesMap;
110 typedef HashMap<String, GRefPtr<WebKitWebResource> > ResourcesMap;
112 struct _WebKitWebViewPrivate {
113 WebKitWebContext* context;
115 CString customTextEncoding;
116 double estimatedLoadProgress;
119 bool waitingForMainResource;
120 gulong mainResourceResponseHandlerID;
121 WebKitLoadEvent lastDelayedEvent;
123 GRefPtr<WebKitBackForwardList> backForwardList;
124 GRefPtr<WebKitSettings> settings;
125 GRefPtr<WebKitWindowProperties> windowProperties;
127 GRefPtr<GMainLoop> modalLoop;
129 GRefPtr<WebKitHitTestResult> mouseTargetHitTestResult;
130 unsigned mouseTargetModifiers;
132 GRefPtr<WebKitFindController> findController;
133 JSGlobalContextRef javascriptGlobalContext;
135 GRefPtr<WebKitWebResource> mainResource;
136 LoadingResourcesMap loadingResourcesMap;
137 ResourcesMap subresourcesMap;
139 GRefPtr<WebKitWebInspector> inspector;
142 static guint signals[LAST_SIGNAL] = { 0, };
144 G_DEFINE_TYPE(WebKitWebView, webkit_web_view, WEBKIT_TYPE_WEB_VIEW_BASE)
146 static gboolean webkitWebViewLoadFail(WebKitWebView* webView, WebKitLoadEvent, const char* failingURI, GError* error)
148 if (g_error_matches(error, WEBKIT_NETWORK_ERROR, WEBKIT_NETWORK_ERROR_CANCELLED)
149 || g_error_matches(error, WEBKIT_POLICY_ERROR, WEBKIT_POLICY_ERROR_FRAME_LOAD_INTERRUPTED_BY_POLICY_CHANGE)
150 || g_error_matches(error, WEBKIT_PLUGIN_ERROR, WEBKIT_PLUGIN_ERROR_WILL_HANDLE_LOAD))
153 GOwnPtr<char> htmlString(g_strdup_printf("<html><body>%s</body></html>", error->message));
154 webkit_web_view_load_alternate_html(webView, htmlString.get(), failingURI, 0);
159 static GtkWidget* webkitWebViewCreate(WebKitWebView*)
164 static GtkWidget* webkitWebViewCreateJavaScriptDialog(WebKitWebView* webView, GtkMessageType type, GtkButtonsType buttons, int defaultResponse, const char* message)
166 GtkWidget* parent = gtk_widget_get_toplevel(GTK_WIDGET(webView));
167 GtkWidget* dialog = gtk_message_dialog_new(widgetIsOnscreenToplevelWindow(parent) ? GTK_WINDOW(parent) : 0,
168 GTK_DIALOG_DESTROY_WITH_PARENT, type, buttons, "%s", message);
169 GOwnPtr<char> title(g_strdup_printf("JavaScript - %s", webkit_web_view_get_uri(webView)));
170 gtk_window_set_title(GTK_WINDOW(dialog), title.get());
171 gtk_dialog_set_default_response(GTK_DIALOG(dialog), defaultResponse);
176 static gboolean webkitWebViewScriptDialog(WebKitWebView* webView, WebKitScriptDialog* scriptDialog)
178 GtkWidget* dialog = 0;
180 switch (scriptDialog->type) {
181 case WEBKIT_SCRIPT_DIALOG_ALERT:
182 dialog = webkitWebViewCreateJavaScriptDialog(webView, GTK_MESSAGE_WARNING, GTK_BUTTONS_CLOSE, GTK_RESPONSE_CLOSE, scriptDialog->message.data());
183 gtk_dialog_run(GTK_DIALOG(dialog));
185 case WEBKIT_SCRIPT_DIALOG_CONFIRM:
186 dialog = webkitWebViewCreateJavaScriptDialog(webView, GTK_MESSAGE_QUESTION, GTK_BUTTONS_OK_CANCEL, GTK_RESPONSE_OK, scriptDialog->message.data());
187 scriptDialog->confirmed = gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK;
189 case WEBKIT_SCRIPT_DIALOG_PROMPT:
190 dialog = webkitWebViewCreateJavaScriptDialog(webView, GTK_MESSAGE_QUESTION, GTK_BUTTONS_OK_CANCEL, GTK_RESPONSE_OK, scriptDialog->message.data());
191 GtkWidget* entry = gtk_entry_new();
192 gtk_entry_set_text(GTK_ENTRY(entry), scriptDialog->defaultText.data());
193 gtk_container_add(GTK_CONTAINER(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), entry);
194 gtk_entry_set_activates_default(GTK_ENTRY(entry), TRUE);
195 gtk_widget_show(entry);
196 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
197 scriptDialog->text = gtk_entry_get_text(GTK_ENTRY(entry));
201 gtk_widget_destroy(dialog);
206 static gboolean webkitWebViewDecidePolicy(WebKitWebView* webView, WebKitPolicyDecision* decision, WebKitPolicyDecisionType decisionType)
208 if (decisionType != WEBKIT_POLICY_DECISION_TYPE_RESPONSE) {
209 webkit_policy_decision_use(decision);
213 WebKitURIResponse* response = webkit_response_policy_decision_get_response(WEBKIT_RESPONSE_POLICY_DECISION(decision));
214 const ResourceResponse resourceResponse = webkitURIResponseGetResourceResponse(response);
215 if (resourceResponse.isAttachment()) {
216 webkit_policy_decision_download(decision);
220 if (webkit_web_view_can_show_mime_type(webView, webkit_uri_response_get_mime_type(response)))
221 webkit_policy_decision_use(decision);
223 webkit_policy_decision_ignore(decision);
228 static gboolean webkitWebViewPermissionRequest(WebKitWebView*, WebKitPermissionRequest* request)
230 webkit_permission_request_deny(request);
234 static void allowModalDialogsChanged(WebKitSettings* settings, GParamSpec*, WebKitWebView* webView)
236 WebPageProxy* page = webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(webView));
239 page->setCanRunModal(webkit_settings_get_allow_modal_dialogs(settings));
242 static void zoomTextOnlyChanged(WebKitSettings* settings, GParamSpec*, WebKitWebView* webView)
244 WKPageRef wkPage = toAPI(webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(webView)));
245 gboolean zoomTextOnly = webkit_settings_get_zoom_text_only(settings);
246 gdouble pageZoomLevel = zoomTextOnly ? 1 : WKPageGetTextZoomFactor(wkPage);
247 gdouble textZoomLevel = zoomTextOnly ? WKPageGetPageZoomFactor(wkPage) : 1;
248 WKPageSetPageAndTextZoomFactors(wkPage, pageZoomLevel, textZoomLevel);
251 static void userAgentChanged(WebKitSettings* settings, GParamSpec*, WebKitWebView* webView)
253 WKRetainPtr<WKStringRef> userAgent = adoptWK(WKStringCreateWithUTF8CString(webkit_settings_get_user_agent(settings)));
254 WKPageSetCustomUserAgent(toAPI(webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(webView))), userAgent.get());
257 static void webkitWebViewSetSettings(WebKitWebView* webView, WebKitSettings* settings, WKPageRef wkPage)
259 webView->priv->settings = settings;
260 webkitSettingsAttachSettingsToPage(webView->priv->settings.get(), wkPage);
261 g_signal_connect(settings, "notify::allow-modal-dialogs", G_CALLBACK(allowModalDialogsChanged), webView);
262 g_signal_connect(settings, "notify::zoom-text-only", G_CALLBACK(zoomTextOnlyChanged), webView);
263 g_signal_connect(settings, "notify::user-agent", G_CALLBACK(userAgentChanged), webView);
266 static void webkitWebViewDisconnectSettingsSignalHandlers(WebKitWebView* webView)
268 WebKitSettings* settings = webView->priv->settings.get();
269 g_signal_handlers_disconnect_by_func(settings, reinterpret_cast<gpointer>(allowModalDialogsChanged), webView);
270 g_signal_handlers_disconnect_by_func(settings, reinterpret_cast<gpointer>(zoomTextOnlyChanged), webView);
271 g_signal_handlers_disconnect_by_func(settings, reinterpret_cast<gpointer>(userAgentChanged), webView);
274 static void webkitWebViewDisconnectMainResourceResponseChangedSignalHandler(WebKitWebView* webView)
276 WebKitWebViewPrivate* priv = webView->priv;
277 if (priv->mainResourceResponseHandlerID)
278 g_signal_handler_disconnect(priv->mainResource.get(), priv->mainResourceResponseHandlerID);
279 priv->mainResourceResponseHandlerID = 0;
282 static void fileChooserDialogResponseCallback(GtkDialog* dialog, gint responseID, WebKitFileChooserRequest* request)
284 GRefPtr<WebKitFileChooserRequest> adoptedRequest = adoptGRef(request);
285 if (responseID == GTK_RESPONSE_ACCEPT) {
286 GOwnPtr<GSList> filesList(gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(dialog)));
287 GRefPtr<GPtrArray> filesArray = adoptGRef(g_ptr_array_new());
288 for (GSList* file = filesList.get(); file; file = g_slist_next(file))
289 g_ptr_array_add(filesArray.get(), file->data);
290 g_ptr_array_add(filesArray.get(), 0);
291 webkit_file_chooser_request_select_files(adoptedRequest.get(), reinterpret_cast<const gchar* const*>(filesArray->pdata));
293 webkit_file_chooser_request_cancel(adoptedRequest.get());
295 gtk_widget_destroy(GTK_WIDGET(dialog));
298 static gboolean webkitWebViewRunFileChooser(WebKitWebView* webView, WebKitFileChooserRequest* request)
300 GtkWidget* toplevel = gtk_widget_get_toplevel(GTK_WIDGET(webView));
301 if (!widgetIsOnscreenToplevelWindow(toplevel))
304 gboolean allowsMultipleSelection = webkit_file_chooser_request_get_select_multiple(request);
305 GtkWidget* dialog = gtk_file_chooser_dialog_new(allowsMultipleSelection ? _("Select Files") : _("Select File"),
306 toplevel ? GTK_WINDOW(toplevel) : 0,
307 GTK_FILE_CHOOSER_ACTION_OPEN,
308 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
309 GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
312 if (GtkFileFilter* filter = webkit_file_chooser_request_get_mime_types_filter(request))
313 gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(dialog), filter);
314 gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog), allowsMultipleSelection);
316 if (const gchar* const* selectedFiles = webkit_file_chooser_request_get_selected_files(request))
317 gtk_file_chooser_select_filename(GTK_FILE_CHOOSER(dialog), selectedFiles[0]);
319 g_signal_connect(dialog, "response", G_CALLBACK(fileChooserDialogResponseCallback), g_object_ref(request));
320 gtk_widget_show(dialog);
325 static void webkitWebViewConstructed(GObject* object)
327 if (G_OBJECT_CLASS(webkit_web_view_parent_class)->constructed)
328 G_OBJECT_CLASS(webkit_web_view_parent_class)->constructed(object);
330 WebKitWebView* webView = WEBKIT_WEB_VIEW(object);
331 WebKitWebViewPrivate* priv = webView->priv;
332 WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(webView);
334 webkitWebViewBaseCreateWebPage(webViewBase, webkitWebContextGetWKContext(priv->context), 0);
336 attachLoaderClientToView(webView);
337 attachUIClientToView(webView);
338 attachPolicyClientToPage(webView);
339 attachResourceLoadClientToView(webView);
340 attachFullScreenClientToView(webView);
341 attachContextMenuClientToView(webView);
342 attachFormClientToView(webView);
344 WebPageProxy* page = webkitWebViewBaseGetPage(webViewBase);
345 priv->backForwardList = adoptGRef(webkitBackForwardListCreate(WKPageGetBackForwardList(toAPI(page))));
347 GRefPtr<WebKitSettings> settings = adoptGRef(webkit_settings_new());
348 webkitWebViewSetSettings(webView, settings.get(), toAPI(page));
351 static void webkitWebViewSetProperty(GObject* object, guint propId, const GValue* value, GParamSpec* paramSpec)
353 WebKitWebView* webView = WEBKIT_WEB_VIEW(object);
356 case PROP_WEB_CONTEXT: {
357 gpointer webContext = g_value_get_object(value);
358 webView->priv->context = webContext ? WEBKIT_WEB_CONTEXT(webContext) : webkit_web_context_get_default();
361 case PROP_ZOOM_LEVEL:
362 webkit_web_view_set_zoom_level(webView, g_value_get_double(value));
365 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propId, paramSpec);
369 static void webkitWebViewGetProperty(GObject* object, guint propId, GValue* value, GParamSpec* paramSpec)
371 WebKitWebView* webView = WEBKIT_WEB_VIEW(object);
374 case PROP_WEB_CONTEXT:
375 g_value_take_object(value, webView->priv->context);
378 g_value_set_string(value, webView->priv->title.data());
380 case PROP_ESTIMATED_LOAD_PROGRESS:
381 g_value_set_double(value, webkit_web_view_get_estimated_load_progress(webView));
384 g_value_set_string(value, webkit_web_view_get_uri(webView));
386 case PROP_ZOOM_LEVEL:
387 g_value_set_double(value, webkit_web_view_get_zoom_level(webView));
390 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propId, paramSpec);
394 static void webkitWebViewFinalize(GObject* object)
396 WebKitWebView* webView = WEBKIT_WEB_VIEW(object);
397 WebKitWebViewPrivate* priv = webView->priv;
399 if (priv->javascriptGlobalContext)
400 JSGlobalContextRelease(priv->javascriptGlobalContext);
402 // For modal dialogs, make sure the main loop is stopped when finalizing the webView.
403 if (priv->modalLoop && g_main_loop_is_running(priv->modalLoop.get()))
404 g_main_loop_quit(priv->modalLoop.get());
406 webkitWebViewDisconnectMainResourceResponseChangedSignalHandler(webView);
407 webkitWebViewDisconnectSettingsSignalHandlers(webView);
409 priv->~WebKitWebViewPrivate();
410 G_OBJECT_CLASS(webkit_web_view_parent_class)->finalize(object);
413 static void webkit_web_view_init(WebKitWebView* webView)
415 WebKitWebViewPrivate* priv = G_TYPE_INSTANCE_GET_PRIVATE(webView, WEBKIT_TYPE_WEB_VIEW, WebKitWebViewPrivate);
416 webView->priv = priv;
417 new (priv) WebKitWebViewPrivate();
419 webView->priv->windowProperties = adoptGRef(webkitWindowPropertiesCreate());
422 static gboolean webkitWebViewAccumulatorObjectHandled(GSignalInvocationHint*, GValue* returnValue, const GValue* handlerReturn, gpointer)
424 void* object = g_value_get_object(handlerReturn);
426 g_value_set_object(returnValue, object);
431 static void webkit_web_view_class_init(WebKitWebViewClass* webViewClass)
433 GObjectClass* gObjectClass = G_OBJECT_CLASS(webViewClass);
435 gObjectClass->constructed = webkitWebViewConstructed;
436 gObjectClass->set_property = webkitWebViewSetProperty;
437 gObjectClass->get_property = webkitWebViewGetProperty;
438 gObjectClass->finalize = webkitWebViewFinalize;
440 webViewClass->load_failed = webkitWebViewLoadFail;
441 webViewClass->create = webkitWebViewCreate;
442 webViewClass->script_dialog = webkitWebViewScriptDialog;
443 webViewClass->decide_policy = webkitWebViewDecidePolicy;
444 webViewClass->permission_request = webkitWebViewPermissionRequest;
445 webViewClass->run_file_chooser = webkitWebViewRunFileChooser;
447 g_type_class_add_private(webViewClass, sizeof(WebKitWebViewPrivate));
450 * WebKitWebView:web-context:
452 * The #WebKitWebContext of the view.
454 g_object_class_install_property(gObjectClass,
456 g_param_spec_object("web-context",
458 _("The web context for the view"),
459 WEBKIT_TYPE_WEB_CONTEXT,
460 static_cast<GParamFlags>(WEBKIT_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)));
463 * WebKitWebView:title:
465 * The main frame document title of this #WebKitWebView. If
466 * the title has not been received yet, it will be %NULL.
468 g_object_class_install_property(gObjectClass,
470 g_param_spec_string("title",
472 _("Main frame document title"),
474 WEBKIT_PARAM_READABLE));
477 * WebKitWebView:estimated-load-progress:
479 * An estimate of the percent completion for the current loading operation.
480 * This value will range from 0.0 to 1.0 and, once a load completes,
481 * will remain at 1.0 until a new load starts, at which point it
482 * will be reset to 0.0.
483 * The value is an estimate based on the total number of bytes expected
484 * to be received for a document, including all its possible subresources
485 * and child documents.
487 g_object_class_install_property(gObjectClass,
488 PROP_ESTIMATED_LOAD_PROGRESS,
489 g_param_spec_double("estimated-load-progress",
490 _("Estimated Load Progress"),
491 _("An estimate of the percent completion for a document load"),
493 WEBKIT_PARAM_READABLE));
497 * The current active URI of the #WebKitWebView.
498 * See webkit_web_view_get_uri() for more details.
500 g_object_class_install_property(gObjectClass,
502 g_param_spec_string("uri",
504 _("The current active URI of the view"),
506 WEBKIT_PARAM_READABLE));
509 * WebKitWebView::load-changed:
510 * @web_view: the #WebKitWebView on which the signal is emitted
511 * @load_event: the #WebKitLoadEvent
513 * Emitted when the a load operation in @web_view changes.
514 * The signal is always emitted with %WEBKIT_LOAD_STARTED when a
515 * new load request is made and %WEBKIT_LOAD_FINISHED when the load
516 * finishes successfully or due to an error. When the ongoing load
517 * operation fails #WebKitWebView::load-failed signal is emitted
518 * before #WebKitWebView::load-changed is emitted with
519 * %WEBKIT_LOAD_FINISHED.
520 * If a redirection is received from the server, this signal is emitted
521 * with %WEBKIT_LOAD_REDIRECTED after the initial emission with
522 * %WEBKIT_LOAD_STARTED and before %WEBKIT_LOAD_COMMITTED.
523 * When the page content starts arriving the signal is emitted with
524 * %WEBKIT_LOAD_COMMITTED event.
526 * You can handle this signal and use a switch to track any ongoing
529 * <informalexample><programlisting>
530 * static void web_view_load_changed (WebKitWebView *web_view,
531 * WebKitLoadEvent load_event,
532 * gpointer user_data)
534 * switch (load_event) {
535 * case WEBKIT_LOAD_STARTED:
536 * /<!-- -->* New load, we have now a provisional URI *<!-- -->/
537 * provisional_uri = webkit_web_view_get_uri (web_view);
538 * /<!-- -->* Here we could start a spinner or update the
539 * <!-- -->* location bar with the provisional URI *<!-- -->/
541 * case WEBKIT_LOAD_REDIRECTED:
542 * redirected_uri = webkit_web_view_get_uri (web_view);
544 * case WEBKIT_LOAD_COMMITTED:
545 * /<!-- -->* The load is being performed. Current URI is
546 * <!-- -->* the final one and it won't change unless a new
547 * <!-- -->* load is requested or a navigation within the
548 * <!-- -->* same page is performed *<!-- -->/
549 * uri = webkit_web_view_get_uri (web_view);
551 * case WEBKIT_LOAD_FINISHED:
552 * /<!-- -->* Load finished, we can now stop the spinner *<!-- -->/
556 * </programlisting></informalexample>
558 signals[LOAD_CHANGED] =
559 g_signal_new("load-changed",
560 G_TYPE_FROM_CLASS(webViewClass),
562 G_STRUCT_OFFSET(WebKitWebViewClass, load_changed),
564 g_cclosure_marshal_VOID__ENUM,
566 WEBKIT_TYPE_LOAD_EVENT);
569 * WebKitWebView::load-failed:
570 * @web_view: the #WebKitWebView on which the signal is emitted
571 * @load_event: the #WebKitLoadEvent of the load operation
572 * @failing_uri: the URI that failed to load
573 * @error: the #GError that was triggered
575 * Emitted when an error occurs during a load operation.
576 * If the error happened when starting to load data for a page
577 * @load_event will be %WEBKIT_LOAD_STARTED. If it happened while
578 * loading a committed data source @load_event will be %WEBKIT_LOAD_COMMITTED.
579 * Since a load error causes the load operation to finish, the signal
580 * WebKitWebView::load-changed will always be emitted with
581 * %WEBKIT_LOAD_FINISHED event right after this one.
583 * By default, if the signal is not handled, a stock error page will be displayed.
584 * You need to handle the signal if you want to provide your own error page.
586 * Returns: %TRUE to stop other handlers from being invoked for the event.
587 * %FALSE to propagate the event further.
589 signals[LOAD_FAILED] =
590 g_signal_new("load-failed",
591 G_TYPE_FROM_CLASS(webViewClass),
593 G_STRUCT_OFFSET(WebKitWebViewClass, load_failed),
594 g_signal_accumulator_true_handled, 0,
595 webkit_marshal_BOOLEAN__ENUM_STRING_POINTER,
597 WEBKIT_TYPE_LOAD_EVENT,
602 * WebKitWebView:zoom-level:
604 * The zoom level of the #WebKitWebView content.
605 * See webkit_web_view_set_zoom_level() for more details.
607 g_object_class_install_property(gObjectClass,
609 g_param_spec_double("zoom-level",
611 "The zoom level of the view content",
613 WEBKIT_PARAM_READWRITE));
616 * WebKitWebView::create:
617 * @web_view: the #WebKitWebView on which the signal is emitted
619 * Emitted when the creation of a new #WebKitWebView is requested.
620 * If this signal is handled the signal handler should return the
621 * newly created #WebKitWebView.
623 * The new #WebKitWebView should not be displayed to the user
624 * until the #WebKitWebView::ready-to-show signal is emitted.
626 * Returns: (transfer full): a newly allocated #WebKitWebView widget
627 * or %NULL to propagate the event further.
630 g_signal_new("create",
631 G_TYPE_FROM_CLASS(webViewClass),
633 G_STRUCT_OFFSET(WebKitWebViewClass, create),
634 webkitWebViewAccumulatorObjectHandled, 0,
635 webkit_marshal_OBJECT__VOID,
639 * WebKitWebView::ready-to-show:
640 * @web_view: the #WebKitWebView on which the signal is emitted
642 * Emitted after #WebKitWebView::create on the newly created #WebKitWebView
643 * when it should be displayed to the user. When this signal is emitted
644 * all the information about how the window should look, including
645 * size, position, whether the location, status and scrollbars
646 * should be displayed, is already set on the #WebKitWindowProperties
647 * of @web_view. See also webkit_web_view_get_window_properties().
649 signals[READY_TO_SHOW] =
650 g_signal_new("ready-to-show",
651 G_TYPE_FROM_CLASS(webViewClass),
653 G_STRUCT_OFFSET(WebKitWebViewClass, ready_to_show),
655 g_cclosure_marshal_VOID__VOID,
659 * WebKitWebView::run-as-modal:
660 * @web_view: the #WebKitWebView on which the signal is emitted
662 * Emitted after #WebKitWebView::ready-to-show on the newly
663 * created #WebKitWebView when JavaScript code calls
664 * <function>window.showModalDialog</function>. The purpose of
665 * this signal is to allow the client application to prepare the
666 * new view to behave as modal. Once the signal is emitted a new
667 * mainloop will be run to block user interaction in the parent
668 * #WebKitWebView until the new dialog is closed.
670 signals[RUN_AS_MODAL] =
671 g_signal_new("run-as-modal",
672 G_TYPE_FROM_CLASS(webViewClass),
674 G_STRUCT_OFFSET(WebKitWebViewClass, run_as_modal),
676 g_cclosure_marshal_VOID__VOID,
680 * WebKitWebView::close:
681 * @webView: the #WebKitWebView on which the signal is emitted
683 * Emitted when closing a #WebKitWebView is requested. This occurs when a
684 * call is made from JavaScript's <function>window.close</function> function.
685 * It is the owner's responsibility to handle this signal to hide or
686 * destroy the #WebKitWebView, if necessary.
689 g_signal_new("close",
690 G_TYPE_FROM_CLASS(webViewClass),
692 G_STRUCT_OFFSET(WebKitWebViewClass, close),
694 g_cclosure_marshal_VOID__VOID,
698 * WebKitWebView::script-dialog:
699 * @web_view: the #WebKitWebView on which the signal is emitted
700 * @dialog: the #WebKitScriptDialog to show
702 * Emitted when JavaScript code calls <function>window.alert</function>,
703 * <function>window.confirm</function> or <function>window.prompt</function>.
704 * The @dialog parameter should be used to build the dialog.
705 * If the signal is not handled a different dialog will be built and shown depending
706 * on the dialog type:
709 * %WEBKIT_SCRIPT_DIALOG_ALERT: message dialog with a single Close button.
712 * %WEBKIT_SCRIPT_DIALOG_CONFIRM: message dialog with OK and Cancel buttons.
715 * %WEBKIT_SCRIPT_DIALOG_PROMPT: message dialog with OK and Cancel buttons and
716 * a text entry with the default text.
720 * Returns: %TRUE to stop other handlers from being invoked for the event.
721 * %FALSE to propagate the event further.
723 signals[SCRIPT_DIALOG] =
724 g_signal_new("script-dialog",
725 G_TYPE_FROM_CLASS(webViewClass),
727 G_STRUCT_OFFSET(WebKitWebViewClass, script_dialog),
728 g_signal_accumulator_true_handled, 0,
729 webkit_marshal_BOOLEAN__BOXED,
731 WEBKIT_TYPE_SCRIPT_DIALOG | G_SIGNAL_TYPE_STATIC_SCOPE);
734 * WebKitWebView::decide-policy:
735 * @web_view: the #WebKitWebView on which the signal is emitted
736 * @decision: the #WebKitPolicyDecision
737 * @decision_type: a #WebKitPolicyDecisionType denoting the type of @decision
739 * This signal is emitted when WebKit is requesting the client to decide a policy
740 * decision, such as whether to navigate to a page, open a new window or whether or
741 * not to download a resource. The #WebKitNavigationPolicyDecision passed in the
742 * @decision argument is a generic type, but should be casted to a more
743 * specific type when making the decision. For example:
745 * <informalexample><programlisting>
747 * decide_policy_cb (WebKitWebView *web_view,
748 * WebKitPolicyDecision *decision,
749 * WebKitPolicyDecisionType type)
752 * case WEBKIT_POLICY_DECISION_TYPE_NAVIGATION_ACTION:
753 * WebKitNavigationPolicyDecision *navigation_decision = WEBKIT_NAVIGATION_POLICY_DECISION (decision);
754 * /<!-- -->* Make a policy decision here. *<!-- -->/
756 * case WEBKIT_POLICY_DECISION_TYPE_NEW_WINDOW_ACTION:
757 * WebKitNavigationPolicyDecision *navigation_decision = WEBKIT_NAVIGATION_POLICY_DECISION (decision);
758 * /<!-- -->* Make a policy decision here. *<!-- -->/
760 * case WEBKIT_POLICY_DECISION_TYPE_RESPONSE:
761 * WebKitResponsePolicyDecision *response = WEBKIT_RESPONSE_POLICY_DECISION (decision);
762 * /<!-- -->* Make a policy decision here. *<!-- -->/
765 * /<!-- -->* Making no decision results in webkit_policy_decision_use(). *<!-- -->/
770 * </programlisting></informalexample>
772 * It is possible to make policy decision asynchronously, by simply calling g_object_ref()
773 * on the @decision argument and returning %TRUE to block the default signal handler.
774 * If the last reference is removed on a #WebKitPolicyDecision and no decision has been
775 * made explicitly, webkit_policy_decision_use() will be the default policy decision. The
776 * default signal handler will simply call webkit_policy_decision_use(). Only the first
777 * policy decision chosen for a given #WebKitPolicyDecision will have any affect.
779 * Returns: %TRUE to stop other handlers from being invoked for the event.
780 * %FALSE to propagate the event further.
783 signals[DECIDE_POLICY] =
784 g_signal_new("decide-policy",
785 G_TYPE_FROM_CLASS(webViewClass),
787 G_STRUCT_OFFSET(WebKitWebViewClass, decide_policy),
788 g_signal_accumulator_true_handled, 0 /* accumulator data */,
789 webkit_marshal_BOOLEAN__OBJECT_ENUM,
790 G_TYPE_BOOLEAN, 2, /* number of parameters */
791 WEBKIT_TYPE_POLICY_DECISION,
792 WEBKIT_TYPE_POLICY_DECISION_TYPE);
795 * WebKitWebView::permission-request:
796 * @web_view: the #WebKitWebView on which the signal is emitted
797 * @request: the #WebKitPermissionRequest
799 * This signal is emitted when WebKit is requesting the client to
800 * decide about a permission request, such as allowing the browser
801 * to switch to fullscreen mode, sharing its location or similar
804 * A possible way to use this signal could be through a dialog
805 * allowing the user decide what to do with the request:
807 * <informalexample><programlisting>
808 * static gboolean permission_request_cb (WebKitWebView *web_view,
809 * WebKitPermissionRequest *request,
810 * GtkWindow *parent_window)
812 * GtkWidget *dialog = gtk_message_dialog_new (parent_window,
814 * GTK_MESSAGE_QUESTION,
815 * GTK_BUTTONS_YES_NO,
816 * "Allow Permission Request?");
817 * gtk_widget_show (dialog);
818 * gint result = gtk_dialog_run (GTK_DIALOG (dialog));
821 * case GTK_RESPONSE_YES:
822 * webkit_permission_request_allow (request);
825 * webkit_permission_request_deny (request);
828 * gtk_widget_destroy (dialog);
832 * </programlisting></informalexample>
834 * It is possible to handle permission requests asynchronously, by
835 * simply calling g_object_ref() on the @request argument and
836 * returning %TRUE to block the default signal handler. If the
837 * last reference is removed on a #WebKitPermissionRequest and the
838 * request has not been handled, webkit_permission_request_deny()
839 * will be the default action.
841 * By default, if the signal is not handled,
842 * webkit_permission_request_deny() will be called over the
843 * #WebKitPermissionRequest.
845 * Returns: %TRUE to stop other handlers from being invoked for the event.
846 * %FALSE to propagate the event further.
849 signals[PERMISSION_REQUEST] =
850 g_signal_new("permission-request",
851 G_TYPE_FROM_CLASS(webViewClass),
853 G_STRUCT_OFFSET(WebKitWebViewClass, permission_request),
854 g_signal_accumulator_true_handled, 0 /* accumulator data */,
855 webkit_marshal_BOOLEAN__OBJECT,
856 G_TYPE_BOOLEAN, 1, /* number of parameters */
857 WEBKIT_TYPE_PERMISSION_REQUEST);
859 * WebKitWebView::mouse-target-changed:
860 * @web_view: the #WebKitWebView on which the signal is emitted
861 * @hit_test_result: a #WebKitHitTestResult
862 * @modifiers: a bitmask of #GdkModifierType
864 * This signal is emitted when the mouse cursor moves over an
865 * element such as a link, image or a media element. To determine
866 * what type of element the mouse cursor is over, a Hit Test is performed
867 * on the current mouse coordinates and the result is passed in the
868 * @hit_test_result argument. The @modifiers argument is a bitmask of
869 * #GdkModifierType flags indicating the state of modifier keys.
870 * The signal is emitted again when the mouse is moved out of the
871 * current element with a new @hit_test_result.
873 signals[MOUSE_TARGET_CHANGED] =
874 g_signal_new("mouse-target-changed",
875 G_TYPE_FROM_CLASS(webViewClass),
877 G_STRUCT_OFFSET(WebKitWebViewClass, mouse_target_changed),
879 webkit_marshal_VOID__OBJECT_UINT,
881 WEBKIT_TYPE_HIT_TEST_RESULT,
884 * WebKitWebView::print:
885 * @web_view: the #WebKitWebView on which the signal is emitted
886 * @print_operation: the #WebKitPrintOperation that will handle the print request
888 * Emitted when printing is requested on @web_view, usually by a javascript call,
889 * before the print dialog is shown. This signal can be used to set the initial
890 * print settings and page setup of @print_operation to be used as default values in
891 * the print dialog. You can call webkit_print_operation_set_print_settings() and
892 * webkit_print_operation_set_page_setup() and then return %FALSE to propagate the
893 * event so that the print dialog is shown.
895 * You can connect to this signal and return %TRUE to cancel the print operation
896 * or implement your own print dialog.
898 * Returns: %TRUE to stop other handlers from being invoked for the event.
899 * %FALSE to propagate the event further.
902 g_signal_new("print",
903 G_TYPE_FROM_CLASS(webViewClass),
905 G_STRUCT_OFFSET(WebKitWebViewClass, print),
906 g_signal_accumulator_true_handled, 0,
907 webkit_marshal_BOOLEAN__OBJECT,
909 WEBKIT_TYPE_PRINT_OPERATION);
912 * WebKitWebView::resource-load-started:
913 * @web_view: the #WebKitWebView on which the signal is emitted
914 * @resource: a #WebKitWebResource
915 * @request: a #WebKitURIRequest
917 * Emitted when a new resource is going to be loaded. The @request parameter
918 * contains the #WebKitURIRequest that will be sent to the server.
919 * You can monitor the load operation by connecting to the different signals
922 signals[RESOURCE_LOAD_STARTED] =
923 g_signal_new("resource-load-started",
924 G_TYPE_FROM_CLASS(webViewClass),
926 G_STRUCT_OFFSET(WebKitWebViewClass, resource_load_started),
928 webkit_marshal_VOID__OBJECT_OBJECT,
930 WEBKIT_TYPE_WEB_RESOURCE,
931 WEBKIT_TYPE_URI_REQUEST);
934 * WebKitWebView::enter-fullscreen:
935 * @web_view: the #WebKitWebView on which the signal is emitted.
937 * Emitted when JavaScript code calls
938 * <function>element.webkitRequestFullScreen</function>. If the
939 * signal is not handled the #WebKitWebView will proceed to full screen
940 * its top level window. This signal can be used by client code to
941 * request permission to the user prior doing the full screen
942 * transition and eventually prepare the top-level window
943 * (e.g. hide some widgets that would otherwise be part of the
944 * full screen window).
946 * Returns: %TRUE to stop other handlers from being invoked for the event.
947 * %FALSE to continue emission of the event.
949 signals[ENTER_FULLSCREEN] =
950 g_signal_new("enter-fullscreen",
951 G_TYPE_FROM_CLASS(webViewClass),
953 G_STRUCT_OFFSET(WebKitWebViewClass, enter_fullscreen),
954 g_signal_accumulator_true_handled, 0,
955 webkit_marshal_BOOLEAN__VOID,
959 * WebKitWebView::leave-fullscreen:
960 * @web_view: the #WebKitWebView on which the signal is emitted.
962 * Emitted when the #WebKitWebView is about to restore its top level
963 * window out of its full screen state. This signal can be used by
964 * client code to restore widgets hidden during the
965 * #WebKitWebView::enter-fullscreen stage for instance.
967 * Returns: %TRUE to stop other handlers from being invoked for the event.
968 * %FALSE to continue emission of the event.
970 signals[LEAVE_FULLSCREEN] =
971 g_signal_new("leave-fullscreen",
972 G_TYPE_FROM_CLASS(webViewClass),
974 G_STRUCT_OFFSET(WebKitWebViewClass, leave_fullscreen),
975 g_signal_accumulator_true_handled, 0,
976 webkit_marshal_BOOLEAN__VOID,
979 * WebKitWebView::run-file-chooser:
980 * @web_view: the #WebKitWebView on which the signal is emitted
981 * @request: a #WebKitFileChooserRequest
983 * This signal is emitted when the user interacts with a <input
984 * type='file' /> HTML element, requesting from WebKit to show
985 * a dialog to select one or more files to be uploaded. To let the
986 * application know the details of the file chooser, as well as to
987 * allow the client application to either cancel the request or
988 * perform an actual selection of files, the signal will pass an
989 * instance of the #WebKitFileChooserRequest in the @request
992 * The default signal handler will asynchronously run a regular
993 * #GtkFileChooserDialog for the user to interact with.
995 * Returns: %TRUE to stop other handlers from being invoked for the event.
996 * %FALSE to propagate the event further.
999 signals[RUN_FILE_CHOOSER] =
1000 g_signal_new("run-file-chooser",
1001 G_TYPE_FROM_CLASS(webViewClass),
1003 G_STRUCT_OFFSET(WebKitWebViewClass, run_file_chooser),
1004 g_signal_accumulator_true_handled, 0 /* accumulator data */,
1005 webkit_marshal_BOOLEAN__OBJECT,
1006 G_TYPE_BOOLEAN, 1, /* number of parameters */
1007 WEBKIT_TYPE_FILE_CHOOSER_REQUEST);
1010 * WebKitWebView::context-menu:
1011 * @web_view: the #WebKitWebView on which the signal is emitted
1012 * @context_menu: the proposed #WebKitContextMenu
1013 * @event: the #GdkEvent that triggered the context menu
1014 * @hit_test_result: a #WebKitHitTestResult
1016 * Emmited when a context menu is about to be displayed to give the application
1017 * a chance to customize the proposed menu, prevent the menu from being displayed
1018 * or build its own context menu.
1021 * To customize the proposed menu you can use webkit_context_menu_prepend(),
1022 * webkit_context_menu_append() or webkit_context_menu_insert() to add new
1023 * #WebKitContextMenuItem<!-- -->s to @context_menu, webkit_context_menu_move_item()
1024 * to reorder existing items, or webkit_context_menu_remove() to remove an
1025 * existing item. The signal handler should return %FALSE, and the menu represented
1026 * by @context_menu will be shown.
1027 * </para></listitem>
1029 * To prevent the menu from being displayed you can just connect to this signal
1030 * and return %TRUE so that the proposed menu will not be shown.
1031 * </para></listitem>
1033 * To build your own menu, you can remove all items from the proposed menu with
1034 * webkit_context_menu_remove_all(), add your own items and return %FALSE so
1035 * that the menu will be shown. You can also ignore the proposed #WebKitContextMenu,
1036 * build your own #GtkMenu and return %TRUE to prevent the proposed menu from being shown.
1037 * </para></listitem>
1039 * If you just want the default menu to be shown always, simply don't connect to this
1040 * signal because showing the proposed context menu is the default behaviour.
1041 * </para></listitem>
1044 * If the signal handler returns %FALSE the context menu represented by @context_menu
1045 * will be shown, if it return %TRUE the context menu will not be shown.
1047 * The proposed #WebKitContextMenu passed in @context_menu argument is only valid
1048 * during the signal emission.
1050 * Returns: %TRUE to stop other handlers from being invoked for the event.
1051 * %FALSE to propagate the event further.
1053 signals[CONTEXT_MENU] =
1054 g_signal_new("context-menu",
1055 G_TYPE_FROM_CLASS(webViewClass),
1057 G_STRUCT_OFFSET(WebKitWebViewClass, context_menu),
1058 g_signal_accumulator_true_handled, 0,
1059 webkit_marshal_BOOLEAN__OBJECT_BOXED_OBJECT,
1061 WEBKIT_TYPE_CONTEXT_MENU,
1062 GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE,
1063 WEBKIT_TYPE_HIT_TEST_RESULT);
1066 * WebKitWebView::context-menu-dismissed:
1067 * @web_view: the #WebKitWebView on which the signal is emitted
1069 * Emitted after #WebKitWebView::context-menu signal, if the context menu is shown,
1070 * to notify that the context menu is dismissed.
1072 signals[CONTEXT_MENU_DISMISSED] =
1073 g_signal_new("context-menu-dismissed",
1074 G_TYPE_FROM_CLASS(webViewClass),
1076 G_STRUCT_OFFSET(WebKitWebViewClass, context_menu_dismissed),
1078 g_cclosure_marshal_VOID__VOID,
1082 * WebKitWebView::submit-form:
1083 * @web_view: the #WebKitWebView on which the signal is emitted
1084 * @request: a #WebKitFormSubmissionRequest
1086 * This signal is emitted when a form is about to be submitted. The @request
1087 * argument passed contains information about the text fields of the form. This
1088 * is typically used to store login information that can be used later to
1089 * pre-fill the form.
1090 * The form will not be submitted until webkit_form_submission_request_submit() is called.
1092 * It is possible to handle the form submission request asynchronously, by
1093 * simply calling g_object_ref() on the @request argument and calling
1094 * webkit_form_submission_request_submit() when done to continue with the form submission.
1095 * If the last reference is removed on a #WebKitFormSubmissionRequest and the
1096 * form has not been submitted, webkit_form_submission_request_submit() will be called.
1098 signals[SUBMIT_FORM] =
1099 g_signal_new("submit-form",
1100 G_TYPE_FROM_CLASS(webViewClass),
1102 G_STRUCT_OFFSET(WebKitWebViewClass, submit_form),
1104 g_cclosure_marshal_VOID__OBJECT,
1106 WEBKIT_TYPE_FORM_SUBMISSION_REQUEST);
1109 static void setCertificateToMainResource(WebKitWebView* webView)
1111 WebKitWebViewPrivate* priv = webView->priv;
1112 ASSERT(priv->mainResource.get());
1114 webkitURIResponseSetCertificateInfo(webkit_web_resource_get_response(priv->mainResource.get()),
1115 WKFrameGetCertificateInfo(webkitWebResourceGetFrame(priv->mainResource.get())));
1118 static void webkitWebViewEmitLoadChanged(WebKitWebView* webView, WebKitLoadEvent loadEvent)
1120 if (loadEvent == WEBKIT_LOAD_FINISHED) {
1121 webView->priv->waitingForMainResource = false;
1122 webkitWebViewDisconnectMainResourceResponseChangedSignalHandler(webView);
1124 webkitWebViewUpdateURI(webView);
1125 g_signal_emit(webView, signals[LOAD_CHANGED], 0, loadEvent);
1128 static void webkitWebViewEmitDelayedLoadEvents(WebKitWebView* webView)
1130 WebKitWebViewPrivate* priv = webView->priv;
1131 if (!priv->waitingForMainResource)
1133 ASSERT(priv->lastDelayedEvent == WEBKIT_LOAD_COMMITTED || priv->lastDelayedEvent == WEBKIT_LOAD_FINISHED);
1135 if (priv->lastDelayedEvent == WEBKIT_LOAD_FINISHED)
1136 webkitWebViewEmitLoadChanged(webView, WEBKIT_LOAD_COMMITTED);
1137 webkitWebViewEmitLoadChanged(webView, priv->lastDelayedEvent);
1138 priv->waitingForMainResource = false;
1141 void webkitWebViewLoadChanged(WebKitWebView* webView, WebKitLoadEvent loadEvent)
1143 if (loadEvent == WEBKIT_LOAD_STARTED) {
1144 // Finish a possible previous load waiting for main resource.
1145 webkitWebViewEmitDelayedLoadEvents(webView);
1147 webView->priv->loadingResourcesMap.clear();
1148 webView->priv->mainResource = 0;
1149 webView->priv->waitingForMainResource = false;
1150 } else if (loadEvent == WEBKIT_LOAD_COMMITTED) {
1151 webView->priv->subresourcesMap.clear();
1152 if (!webView->priv->mainResource) {
1153 // When a page is loaded from the history cache, the main resource load callbacks
1154 // are called when the main frame load is finished. We want to make sure there's a
1155 // main resource available when load has been committed, so we delay the emission of
1156 // load-changed signal until main resource object has been created.
1157 webView->priv->waitingForMainResource = true;
1159 setCertificateToMainResource(webView);
1162 if (webView->priv->waitingForMainResource)
1163 webView->priv->lastDelayedEvent = loadEvent;
1165 webkitWebViewEmitLoadChanged(webView, loadEvent);
1168 void webkitWebViewLoadFailed(WebKitWebView* webView, WebKitLoadEvent loadEvent, const char* failingURI, GError *error)
1170 gboolean returnValue;
1171 g_signal_emit(webView, signals[LOAD_FAILED], 0, loadEvent, failingURI, error, &returnValue);
1172 g_signal_emit(webView, signals[LOAD_CHANGED], 0, WEBKIT_LOAD_FINISHED);
1175 void webkitWebViewSetTitle(WebKitWebView* webView, const CString& title)
1177 WebKitWebViewPrivate* priv = webView->priv;
1178 if (priv->title == title)
1181 priv->title = title;
1182 g_object_notify(G_OBJECT(webView), "title");
1185 void webkitWebViewSetEstimatedLoadProgress(WebKitWebView* webView, double estimatedLoadProgress)
1187 if (webView->priv->estimatedLoadProgress == estimatedLoadProgress)
1190 webView->priv->estimatedLoadProgress = estimatedLoadProgress;
1191 g_object_notify(G_OBJECT(webView), "estimated-load-progress");
1194 void webkitWebViewUpdateURI(WebKitWebView* webView)
1196 WebPageProxy* page = webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(webView));
1197 WKRetainPtr<WKURLRef> wkURL(AdoptWK, WKPageCopyActiveURL(toAPI(page)));
1200 activeURI = toImpl(wkURL.get())->string().utf8();
1202 if (webView->priv->activeURI == activeURI)
1205 webView->priv->activeURI = activeURI;
1206 g_object_notify(G_OBJECT(webView), "uri");
1209 WKPageRef webkitWebViewCreateNewPage(WebKitWebView* webView, WKDictionaryRef wkWindowFeatures)
1211 WebKitWebView* newWebView;
1212 g_signal_emit(webView, signals[CREATE], 0, &newWebView);
1216 webkitWindowPropertiesUpdateFromWKWindowFeatures(newWebView->priv->windowProperties.get(), wkWindowFeatures);
1218 return static_cast<WKPageRef>(WKRetain(toAPI(webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(newWebView)))));
1221 void webkitWebViewReadyToShowPage(WebKitWebView* webView)
1223 g_signal_emit(webView, signals[READY_TO_SHOW], 0, NULL);
1226 void webkitWebViewRunAsModal(WebKitWebView* webView)
1228 g_signal_emit(webView, signals[RUN_AS_MODAL], 0, NULL);
1230 webView->priv->modalLoop = adoptGRef(g_main_loop_new(0, FALSE));
1231 gdk_threads_leave();
1232 g_main_loop_run(webView->priv->modalLoop.get());
1233 gdk_threads_enter();
1236 void webkitWebViewClosePage(WebKitWebView* webView)
1238 g_signal_emit(webView, signals[CLOSE], 0, NULL);
1241 void webkitWebViewRunJavaScriptAlert(WebKitWebView* webView, const CString& message)
1243 WebKitScriptDialog dialog(WEBKIT_SCRIPT_DIALOG_ALERT, message);
1244 gboolean returnValue;
1245 g_signal_emit(webView, signals[SCRIPT_DIALOG], 0, &dialog, &returnValue);
1248 bool webkitWebViewRunJavaScriptConfirm(WebKitWebView* webView, const CString& message)
1250 WebKitScriptDialog dialog(WEBKIT_SCRIPT_DIALOG_CONFIRM, message);
1251 gboolean returnValue;
1252 g_signal_emit(webView, signals[SCRIPT_DIALOG], 0, &dialog, &returnValue);
1253 return dialog.confirmed;
1256 WKStringRef webkitWebViewRunJavaScriptPrompt(WebKitWebView* webView, const CString& message, const CString& defaultText)
1258 WebKitScriptDialog dialog(WEBKIT_SCRIPT_DIALOG_PROMPT, message, defaultText);
1259 gboolean returnValue;
1260 g_signal_emit(webView, signals[SCRIPT_DIALOG], 0, &dialog, &returnValue);
1261 return dialog.text.isNull() ? 0 : WKStringCreateWithUTF8CString(dialog.text.data());
1264 void webkitWebViewMakePolicyDecision(WebKitWebView* webView, WebKitPolicyDecisionType type, WebKitPolicyDecision* decision)
1266 gboolean returnValue;
1267 g_signal_emit(webView, signals[DECIDE_POLICY], 0, decision, type, &returnValue);
1270 void webkitWebViewMakePermissionRequest(WebKitWebView* webView, WebKitPermissionRequest* request)
1272 gboolean returnValue;
1273 g_signal_emit(webView, signals[PERMISSION_REQUEST], 0, request, &returnValue);
1276 void webkitWebViewMouseTargetChanged(WebKitWebView* webView, WKHitTestResultRef wkHitTestResult, unsigned modifiers)
1278 webkitWebViewBaseSetTooltipArea(WEBKIT_WEB_VIEW_BASE(webView), toImpl(wkHitTestResult)->elementBoundingBox());
1280 WebKitWebViewPrivate* priv = webView->priv;
1281 if (priv->mouseTargetHitTestResult
1282 && priv->mouseTargetModifiers == modifiers
1283 && webkitHitTestResultCompare(priv->mouseTargetHitTestResult.get(), wkHitTestResult))
1286 priv->mouseTargetModifiers = modifiers;
1287 priv->mouseTargetHitTestResult = adoptGRef(webkitHitTestResultCreate(wkHitTestResult));
1288 g_signal_emit(webView, signals[MOUSE_TARGET_CHANGED], 0, priv->mouseTargetHitTestResult.get(), modifiers);
1291 void webkitWebViewPrintFrame(WebKitWebView* webView, WKFrameRef wkFrame)
1293 GRefPtr<WebKitPrintOperation> printOperation = adoptGRef(webkit_print_operation_new(webView));
1294 gboolean returnValue;
1295 g_signal_emit(webView, signals[PRINT], 0, printOperation.get(), &returnValue);
1299 WebKitPrintOperationResponse response = webkitPrintOperationRunDialogForFrame(printOperation.get(), 0, toImpl(wkFrame));
1300 if (response == WEBKIT_PRINT_OPERATION_RESPONSE_CANCEL)
1302 g_signal_connect(printOperation.leakRef(), "finished", G_CALLBACK(g_object_unref), 0);
1305 static void mainResourceResponseChangedCallback(WebKitWebResource*, GParamSpec*, WebKitWebView* webView)
1307 webkitWebViewDisconnectMainResourceResponseChangedSignalHandler(webView);
1308 setCertificateToMainResource(webView);
1309 webkitWebViewEmitDelayedLoadEvents(webView);
1312 static void waitForMainResourceResponseIfWaitingForResource(WebKitWebView* webView)
1314 WebKitWebViewPrivate* priv = webView->priv;
1315 if (!priv->waitingForMainResource)
1318 webkitWebViewDisconnectMainResourceResponseChangedSignalHandler(webView);
1319 priv->mainResourceResponseHandlerID =
1320 g_signal_connect(priv->mainResource.get(), "notify::response", G_CALLBACK(mainResourceResponseChangedCallback), webView);
1323 void webkitWebViewResourceLoadStarted(WebKitWebView* webView, WKFrameRef wkFrame, uint64_t resourceIdentifier, WebKitURIRequest* request)
1325 WebKitWebViewPrivate* priv = webView->priv;
1326 bool isMainResource = WKFrameIsMainFrame(wkFrame) && !priv->mainResource;
1327 WebKitWebResource* resource = webkitWebResourceCreate(wkFrame, request, isMainResource);
1328 if (isMainResource) {
1329 priv->mainResource = resource;
1330 waitForMainResourceResponseIfWaitingForResource(webView);
1332 priv->loadingResourcesMap.set(resourceIdentifier, adoptGRef(resource));
1333 g_signal_emit(webView, signals[RESOURCE_LOAD_STARTED], 0, resource, request);
1336 WebKitWebResource* webkitWebViewGetLoadingWebResource(WebKitWebView* webView, uint64_t resourceIdentifier)
1338 GRefPtr<WebKitWebResource> resource = webView->priv->loadingResourcesMap.get(resourceIdentifier);
1339 ASSERT(resource.get());
1340 return resource.get();
1343 void webkitWebViewRemoveLoadingWebResource(WebKitWebView* webView, uint64_t resourceIdentifier)
1345 WebKitWebViewPrivate* priv = webView->priv;
1346 ASSERT(priv->loadingResourcesMap.contains(resourceIdentifier));
1347 priv->loadingResourcesMap.remove(resourceIdentifier);
1350 WebKitWebResource* webkitWebViewResourceLoadFinished(WebKitWebView* webView, uint64_t resourceIdentifier)
1352 WebKitWebViewPrivate* priv = webView->priv;
1353 WebKitWebResource* resource = webkitWebViewGetLoadingWebResource(webView, resourceIdentifier);
1354 if (resource != priv->mainResource)
1355 priv->subresourcesMap.set(String::fromUTF8(webkit_web_resource_get_uri(resource)), resource);
1356 webkitWebViewRemoveLoadingWebResource(webView, resourceIdentifier);
1360 bool webkitWebViewEnterFullScreen(WebKitWebView* webView)
1362 gboolean returnValue;
1363 g_signal_emit(webView, signals[ENTER_FULLSCREEN], 0, &returnValue);
1364 return !returnValue;
1367 bool webkitWebViewLeaveFullScreen(WebKitWebView* webView)
1369 gboolean returnValue;
1370 g_signal_emit(webView, signals[LEAVE_FULLSCREEN], 0, &returnValue);
1371 return !returnValue;
1374 void webkitWebViewRunFileChooserRequest(WebKitWebView* webView, WebKitFileChooserRequest* request)
1376 gboolean returnValue;
1377 g_signal_emit(webView, signals[RUN_FILE_CHOOSER], 0, request, &returnValue);
1380 static bool webkitWebViewShouldShowInputMethodsMenu(WebKitWebView* webView)
1382 GtkSettings* settings = gtk_widget_get_settings(GTK_WIDGET(webView));
1386 gboolean showInputMethodMenu;
1387 g_object_get(settings, "gtk-show-input-method-menu", &showInputMethodMenu, NULL);
1388 return showInputMethodMenu;
1391 static int getUnicodeMenuItemPosition(WebKitContextMenu* contextMenu)
1393 GList* items = webkit_context_menu_get_items(contextMenu);
1396 for (iter = items, i = 0; iter; iter = g_list_next(iter), ++i) {
1397 WebKitContextMenuItem* item = WEBKIT_CONTEXT_MENU_ITEM(iter->data);
1399 if (webkit_context_menu_item_is_separator(item))
1401 if (webkit_context_menu_item_get_stock_action(item) == WEBKIT_CONTEXT_MENU_ACTION_UNICODE)
1407 static void webkitWebViewCreateAndAppendInputMethodsMenuItem(WebKitWebView* webView, WebKitContextMenu* contextMenu)
1409 if (!webkitWebViewShouldShowInputMethodsMenu(webView))
1412 // Place the im context menu item right before the unicode menu item
1414 int unicodeMenuItemPosition = getUnicodeMenuItemPosition(contextMenu);
1415 if (unicodeMenuItemPosition == -1)
1416 webkit_context_menu_append(contextMenu, webkit_context_menu_item_new_separator());
1418 GtkIMContext* imContext = webkitWebViewBaseGetIMContext(WEBKIT_WEB_VIEW_BASE(webView));
1419 GtkMenu* imContextMenu = GTK_MENU(gtk_menu_new());
1420 gtk_im_multicontext_append_menuitems(GTK_IM_MULTICONTEXT(imContext), GTK_MENU_SHELL(imContextMenu));
1421 WebKitContextMenuItem* menuItem = webkit_context_menu_item_new_from_stock_action(WEBKIT_CONTEXT_MENU_ACTION_INPUT_METHODS);
1422 webkitContextMenuItemSetSubMenuFromGtkMenu(menuItem, imContextMenu);
1423 webkit_context_menu_insert(contextMenu, menuItem, unicodeMenuItemPosition);
1426 static void contextMenuDismissed(GtkMenuShell*, WebKitWebView* webView)
1428 g_signal_emit(webView, signals[CONTEXT_MENU_DISMISSED], 0, NULL);
1431 void webkitWebViewPopulateContextMenu(WebKitWebView* webView, WKArrayRef wkProposedMenu, WKHitTestResultRef wkHitTestResult)
1433 WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(webView);
1434 WebContextMenuProxyGtk* contextMenuProxy = webkitWebViewBaseGetActiveContextMenuProxy(webViewBase);
1435 ASSERT(contextMenuProxy);
1437 GRefPtr<WebKitContextMenu> contextMenu = adoptGRef(webkitContextMenuCreate(wkProposedMenu));
1438 if (WKHitTestResultIsContentEditable(wkHitTestResult))
1439 webkitWebViewCreateAndAppendInputMethodsMenuItem(webView, contextMenu.get());
1441 GRefPtr<WebKitHitTestResult> hitTestResult = adoptGRef(webkitHitTestResultCreate(wkHitTestResult));
1442 GOwnPtr<GdkEvent> contextMenuEvent(webkitWebViewBaseTakeContextMenuEvent(webViewBase));
1444 gboolean returnValue;
1445 g_signal_emit(webView, signals[CONTEXT_MENU], 0, contextMenu.get(), contextMenuEvent.get(), hitTestResult.get(), &returnValue);
1449 Vector<ContextMenuItem> contextMenuItems;
1450 webkitContextMenuPopulate(contextMenu.get(), contextMenuItems);
1451 contextMenuProxy->populate(contextMenuItems);
1453 g_signal_connect(contextMenuProxy->gtkMenu(), "deactivate", G_CALLBACK(contextMenuDismissed), webView);
1455 // Clear the menu to make sure it's useless after signal emission.
1456 webkit_context_menu_remove_all(contextMenu.get());
1459 void webkitWebViewSubmitFormRequest(WebKitWebView* webView, WebKitFormSubmissionRequest* request)
1461 g_signal_emit(webView, signals[SUBMIT_FORM], 0, request);
1465 * webkit_web_view_new:
1467 * Creates a new #WebKitWebView with the default #WebKitWebContext.
1468 * See also webkit_web_view_new_with_context().
1470 * Returns: The newly created #WebKitWebView widget
1472 GtkWidget* webkit_web_view_new()
1474 return webkit_web_view_new_with_context(webkit_web_context_get_default());
1478 * webkit_web_view_new_with_context:
1479 * @context: the #WebKitWebContext to be used by the #WebKitWebView
1481 * Creates a new #WebKitWebView with the given #WebKitWebContext.
1483 * Returns: The newly created #WebKitWebView widget
1485 GtkWidget* webkit_web_view_new_with_context(WebKitWebContext* context)
1487 g_return_val_if_fail(WEBKIT_IS_WEB_CONTEXT(context), 0);
1489 return GTK_WIDGET(g_object_new(WEBKIT_TYPE_WEB_VIEW, "web-context", context, NULL));
1493 * webkit_web_view_get_context:
1494 * @web_view: a #WebKitWebView
1496 * Gets the web context of @web_view.
1498 * Returns: (transfer none): the #WebKitWebContext of the view
1500 WebKitWebContext* webkit_web_view_get_context(WebKitWebView *webView)
1502 g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0);
1504 return webView->priv->context;
1508 * webkit_web_view_load_uri:
1509 * @web_view: a #WebKitWebView
1510 * @uri: an URI string
1512 * Requests loading of the specified URI string.
1513 * You can monitor the load operation by connecting to
1514 * #WebKitWebView::load-changed signal.
1516 void webkit_web_view_load_uri(WebKitWebView* webView, const gchar* uri)
1518 g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
1519 g_return_if_fail(uri);
1521 WKRetainPtr<WKURLRef> url(AdoptWK, WKURLCreateWithUTF8CString(uri));
1522 WebPageProxy* page = webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(webView));
1523 WKPageLoadURL(toAPI(page), url.get());
1524 webkitWebViewUpdateURI(webView);
1528 * webkit_web_view_load_html:
1529 * @web_view: a #WebKitWebView
1530 * @content: The HTML string to load
1531 * @base_uri: (allow-none): The base URI for relative locations or %NULL
1533 * Load the given @content string with the specified @base_uri.
1534 * If @base_uri is not %NULL, relative URLs in the @content will be
1535 * resolved against @base_uri and absolute local paths must be children of the @base_uri.
1536 * For security reasons absolute local paths that are not children of @base_uri
1537 * will cause the web process to terminate.
1538 * If you need to include URLs in @content that are local paths in a different
1539 * directory than @base_uri you can build a data URI for them. When @base_uri is %NULL,
1540 * it defaults to "about:blank". The mime type of the document will be "text/html".
1541 * You can monitor the load operation by connecting to #WebKitWebView::load-changed signal.
1543 void webkit_web_view_load_html(WebKitWebView* webView, const gchar* content, const gchar* baseURI)
1545 g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
1546 g_return_if_fail(content);
1548 WebPageProxy* page = webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(webView));
1549 WKRetainPtr<WKStringRef> contentRef(AdoptWK, WKStringCreateWithUTF8CString(content));
1550 WKRetainPtr<WKURLRef> baseURIRef = baseURI ? adoptWK(WKURLCreateWithUTF8CString(baseURI)) : 0;
1551 WKPageLoadHTMLString(toAPI(page), contentRef.get(), baseURIRef.get());
1555 * webkit_web_view_load_alternate_html:
1556 * @web_view: a #WebKitWebView
1557 * @content: the new content to display as the main page of the @web_view
1558 * @content_uri: the URI for the alternate page content
1559 * @base_uri: (allow-none): the base URI for relative locations or %NULL
1561 * Load the given @content string for the URI @content_uri.
1562 * This allows clients to display page-loading errors in the #WebKitWebView itself.
1563 * When this method is called from #WebKitWebView::load-failed signal to show an
1564 * error page, the the back-forward list is maintained appropriately.
1565 * For everything else this method works the same way as webkit_web_view_load_html().
1567 void webkit_web_view_load_alternate_html(WebKitWebView* webView, const gchar* content, const gchar* contentURI, const gchar* baseURI)
1569 g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
1570 g_return_if_fail(content);
1571 g_return_if_fail(contentURI);
1573 WKRetainPtr<WKStringRef> htmlString(AdoptWK, WKStringCreateWithUTF8CString(content));
1574 WKRetainPtr<WKURLRef> contentURL(AdoptWK, WKURLCreateWithUTF8CString(contentURI));
1575 WKRetainPtr<WKURLRef> baseURL = baseURI ? adoptWK(WKURLCreateWithUTF8CString(baseURI)) : 0;
1576 WebPageProxy* page = webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(webView));
1577 WKPageLoadAlternateHTMLString(toAPI(page), htmlString.get(), baseURL.get(), contentURL.get());
1578 webkitWebViewUpdateURI(webView);
1582 * webkit_web_view_load_plain_text:
1583 * @web_view: a #WebKitWebView
1584 * @plain_text: The plain text to load
1586 * Load the specified @plain_text string into @web_view. The mime type of
1587 * document will be "text/plain". You can monitor the load
1588 * operation by connecting to #WebKitWebView::load-changed signal.
1590 void webkit_web_view_load_plain_text(WebKitWebView* webView, const gchar* plainText)
1592 g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
1593 g_return_if_fail(plainText);
1595 WebPageProxy* page = webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(webView));
1596 WKRetainPtr<WKStringRef> plainTextRef(AdoptWK, WKStringCreateWithUTF8CString(plainText));
1597 WKPageLoadPlainTextString(toAPI(page), plainTextRef.get());
1601 * webkit_web_view_load_request:
1602 * @web_view: a #WebKitWebView
1603 * @request: a #WebKitURIRequest to load
1605 * Requests loading of the specified #WebKitURIRequest.
1606 * You can monitor the load operation by connecting to
1607 * #WebKitWebView::load-changed signal.
1609 void webkit_web_view_load_request(WebKitWebView* webView, WebKitURIRequest* request)
1611 g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
1612 g_return_if_fail(WEBKIT_IS_URI_REQUEST(request));
1614 WKRetainPtr<WKURLRef> wkURL(AdoptWK, WKURLCreateWithUTF8CString(webkit_uri_request_get_uri(request)));
1615 WKRetainPtr<WKURLRequestRef> wkRequest(AdoptWK, WKURLRequestCreateWithWKURL(wkURL.get()));
1616 WebPageProxy* page = webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(webView));
1617 WKPageLoadURLRequest(toAPI(page), wkRequest.get());
1618 webkitWebViewUpdateURI(webView);
1622 * webkit_web_view_get_title:
1623 * @web_view: a #WebKitWebView
1625 * Gets the value of the #WebKitWebView:title property.
1626 * You can connect to notify::title signal of @web_view to
1627 * be notified when the title has been received.
1629 * Returns: The main frame document title of @web_view.
1631 const gchar* webkit_web_view_get_title(WebKitWebView* webView)
1633 g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0);
1635 return webView->priv->title.data();
1639 * webkit_web_view_reload:
1640 * @web_view: a #WebKitWebView
1642 * Reloads the current contents of @web_view.
1643 * See also webkit_web_view_reload_bypass_cache().
1645 void webkit_web_view_reload(WebKitWebView* webView)
1647 g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
1649 WKPageReload(toAPI(webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(webView))));
1650 webkitWebViewUpdateURI(webView);
1654 * webkit_web_view_reload_bypass_cache:
1655 * @web_view: a #WebKitWebView
1657 * Reloads the current contents of @web_view without
1658 * using any cached data.
1660 void webkit_web_view_reload_bypass_cache(WebKitWebView* webView)
1662 g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
1664 WKPageReloadFromOrigin(toAPI(webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(webView))));
1665 webkitWebViewUpdateURI(webView);
1669 * webkit_web_view_stop_loading:
1670 * @web_view: a #WebKitWebView
1672 * Stops any ongoing loading operation in @web_view.
1673 * This method does nothing if no content is being loaded.
1674 * If there is a loading operation in progress, it will be cancelled and
1675 * #WebKitWebView::load-failed signal will be emitted with
1676 * %WEBKIT_NETWORK_ERROR_CANCELLED error.
1678 void webkit_web_view_stop_loading(WebKitWebView* webView)
1680 g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
1682 WKPageStopLoading(toAPI(webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(webView))));
1686 * webkit_web_view_go_back:
1687 * @web_view: a #WebKitWebView
1689 * Loads the previous history item.
1690 * You can monitor the load operation by connecting to
1691 * #WebKitWebView::load-changed signal.
1693 void webkit_web_view_go_back(WebKitWebView* webView)
1695 g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
1697 WKPageGoBack(toAPI(webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(webView))));
1698 webkitWebViewUpdateURI(webView);
1702 * webkit_web_view_can_go_back:
1703 * @web_view: a #WebKitWebView
1705 * Determines whether @web_view has a previous history item.
1707 * Returns: %TRUE if able to move back or %FALSE otherwise.
1709 gboolean webkit_web_view_can_go_back(WebKitWebView* webView)
1711 g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), FALSE);
1713 return WKPageCanGoBack(toAPI(webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(webView))));
1717 * webkit_web_view_go_forward:
1718 * @web_view: a #WebKitWebView
1720 * Loads the next history item.
1721 * You can monitor the load operation by connecting to
1722 * #WebKitWebView::load-changed signal.
1724 void webkit_web_view_go_forward(WebKitWebView* webView)
1726 g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
1728 WKPageGoForward(toAPI(webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(webView))));
1729 webkitWebViewUpdateURI(webView);
1733 * webkit_web_view_can_go_forward:
1734 * @web_view: a #WebKitWebView
1736 * Determines whether @web_view has a next history item.
1738 * Returns: %TRUE if able to move forward or %FALSE otherwise.
1740 gboolean webkit_web_view_can_go_forward(WebKitWebView* webView)
1742 g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), FALSE);
1744 return WKPageCanGoForward(toAPI(webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(webView))));
1748 * webkit_web_view_get_uri:
1749 * @web_view: a #WebKitWebView
1751 * Returns the current active URI of @web_view. The active URI might change during
1756 * When nothing has been loaded yet on @web_view the active URI is %NULL.
1757 * </para></listitem>
1759 * When a new load operation starts the active URI is the requested URI:
1762 * If the load operation was started by webkit_web_view_load_uri(),
1763 * the requested URI is the given one.
1764 * </para></listitem>
1766 * If the load operation was started by webkit_web_view_load_html(),
1767 * the requested URI is "about:blank".
1768 * </para></listitem>
1770 * If the load operation was started by webkit_web_view_load_alternate_html(),
1771 * the requested URI is content URI provided.
1772 * </para></listitem>
1774 * If the load operation was started by webkit_web_view_go_back() or
1775 * webkit_web_view_go_forward(), the requested URI is the original URI
1776 * of the previous/next item in the #WebKitBackForwardList of @web_view.
1777 * </para></listitem>
1779 * If the load operation was started by
1780 * webkit_web_view_go_to_back_forward_list_item(), the requested URI
1781 * is the opriginal URI of the given #WebKitBackForwardListItem.
1782 * </para></listitem>
1784 * </para></listitem>
1786 * If there is a server redirection during the load operation,
1787 * the active URI is the redirected URI. When the signal
1788 * #WebKitWebView::load-changed is emitted with %WEBKIT_LOAD_REDIRECTED
1789 * event, the active URI is already updated to the redirected URI.
1790 * </para></listitem>
1792 * When the signal #WebKitWebView::load-changed is emitted
1793 * with %WEBKIT_LOAD_COMMITTED event, the active URI is the final
1794 * one and it will not change unless a new load operation is started
1795 * or a navigation action within the same page is performed.
1796 * </para></listitem>
1799 * You can monitor the active URI by connecting to the notify::uri
1800 * signal of @web_view.
1802 * Returns: the current active URI of @web_view or %NULL
1803 * if nothing has been loaded yet.
1805 const gchar* webkit_web_view_get_uri(WebKitWebView* webView)
1807 g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0);
1809 return webView->priv->activeURI.data();
1813 * webkit_web_view_get_custom_charset:
1814 * @web_view: a #WebKitWebView
1816 * Returns the current custom character encoding name of @web_view.
1818 * Returns: the current custom character encoding name or %NULL if no
1819 * custom character encoding has been set.
1821 const gchar* webkit_web_view_get_custom_charset(WebKitWebView* webView)
1823 g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0);
1825 WebPageProxy* page = webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(webView));
1826 WKRetainPtr<WKStringRef> wkCustomEncoding(AdoptWK, WKPageCopyCustomTextEncodingName(toAPI(page)));
1827 if (WKStringIsEmpty(wkCustomEncoding.get()))
1830 webView->priv->customTextEncoding = toImpl(wkCustomEncoding.get())->string().utf8();
1831 return webView->priv->customTextEncoding.data();
1835 * webkit_web_view_set_custom_charset:
1836 * @web_view: a #WebKitWebView
1837 * @charset: (allow-none): a character encoding name or %NULL
1839 * Sets the current custom character encoding override of @web_view. The custom
1840 * character encoding will override any text encoding detected via HTTP headers or
1841 * META tags. Calling this method will stop any current load operation and reload the
1842 * current page. Setting the custom character encoding to %NULL removes the character
1843 * encoding override.
1845 void webkit_web_view_set_custom_charset(WebKitWebView* webView, const gchar* charset)
1847 g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
1849 WebPageProxy* page = webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(webView));
1850 WKRetainPtr<WKStringRef> wkEncodingName = charset ? adoptWK(WKStringCreateWithUTF8CString(charset)) : 0;
1851 WKPageSetCustomTextEncodingName(toAPI(page), wkEncodingName.get());
1855 * webkit_web_view_get_estimated_load_progress:
1856 * @web_view: a #WebKitWebView
1858 * Gets the value of the #WebKitWebView:estimated-load-progress property.
1859 * You can monitor the estimated progress of a load operation by
1860 * connecting to the notify::estimated-load-progress signal of @web_view.
1862 * Returns: an estimate of the of the percent complete for a document
1863 * load as a range from 0.0 to 1.0.
1865 gdouble webkit_web_view_get_estimated_load_progress(WebKitWebView* webView)
1867 g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0);
1868 return webView->priv->estimatedLoadProgress;
1872 * webkit_web_view_get_back_forward_list:
1873 * @web_view: a #WebKitWebView
1875 * Obtains the #WebKitBackForwardList associated with the given #WebKitWebView. The
1876 * #WebKitBackForwardList is owned by the #WebKitWebView.
1878 * Returns: (transfer none): the #WebKitBackForwardList
1880 WebKitBackForwardList* webkit_web_view_get_back_forward_list(WebKitWebView* webView)
1882 g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0);
1884 return webView->priv->backForwardList.get();
1888 * webkit_web_view_go_to_back_forward_list_item:
1889 * @web_view: a #WebKitWebView
1890 * @list_item: a #WebKitBackForwardListItem
1892 * Loads the specific history item @list_item.
1893 * You can monitor the load operation by connecting to
1894 * #WebKitWebView::load-changed signal.
1896 void webkit_web_view_go_to_back_forward_list_item(WebKitWebView* webView, WebKitBackForwardListItem* listItem)
1898 g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
1899 g_return_if_fail(WEBKIT_IS_BACK_FORWARD_LIST_ITEM(listItem));
1901 WKPageGoToBackForwardListItem(toAPI(webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(webView))),
1902 webkitBackForwardListItemGetWKItem(listItem));
1903 webkitWebViewUpdateURI(webView);
1907 * webkit_web_view_set_settings:
1908 * @web_view: a #WebKitWebView
1909 * @settings: a #WebKitSettings
1911 * Sets the #WebKitSettings to be applied to @web_view. The
1912 * existing #WebKitSettings of @web_view will be replaced by
1913 * @settings. New settings are applied immediately on @web_view.
1914 * The same #WebKitSettings object can be shared
1915 * by multiple #WebKitWebView<!-- -->s.
1917 void webkit_web_view_set_settings(WebKitWebView* webView, WebKitSettings* settings)
1919 g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
1920 g_return_if_fail(WEBKIT_IS_SETTINGS(settings));
1922 if (webView->priv->settings == settings)
1925 webkitWebViewDisconnectSettingsSignalHandlers(webView);
1926 webkitWebViewSetSettings(webView, settings, toAPI(webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(webView))));
1930 * webkit_web_view_get_settings:
1931 * @web_view: a #WebKitWebView
1933 * Gets the #WebKitSettings currently applied to @web_view.
1934 * If no other #WebKitSettings have been explicitly applied to
1935 * @web_view with webkit_web_view_set_settings(), the default
1936 * #WebKitSettings will be returned. This method always returns
1937 * a valid #WebKitSettings object.
1938 * To modify any of the @web_view settings, you can either create
1939 * a new #WebKitSettings object with webkit_settings_new(), setting
1940 * the desired preferences, and then replace the existing @web_view
1941 * settings with webkit_web_view_set_settings() or get the existing
1942 * @web_view settings and update it directly. #WebKitSettings objects
1943 * can be shared by multiple #WebKitWebView<!-- -->s, so modifying
1944 * the settings of a #WebKitWebView would affect other
1945 * #WebKitWebView<!-- -->s using the same #WebKitSettings.
1947 * Returns: (transfer none): the #WebKitSettings attached to @web_view
1949 WebKitSettings* webkit_web_view_get_settings(WebKitWebView* webView)
1951 g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0);
1953 return webView->priv->settings.get();
1957 * webkit_web_view_get_window_properties:
1958 * @web_view: a #WebKitWebView
1960 * Get the #WebKitWindowProperties object containing the properties
1961 * that the window containing @web_view should have.
1963 * Returns: (transfer none): the #WebKitWindowProperties of @web_view
1965 WebKitWindowProperties* webkit_web_view_get_window_properties(WebKitWebView* webView)
1967 g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0);
1969 return webView->priv->windowProperties.get();
1973 * webkit_web_view_set_zoom_level:
1974 * @web_view: a #WebKitWebView
1975 * @zoom_level: the zoom level
1977 * Set the zoom level of @web_view, i.e. the factor by which the
1978 * view contents are scaled with respect to their original size.
1980 void webkit_web_view_set_zoom_level(WebKitWebView* webView, gdouble zoomLevel)
1982 g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
1984 if (webkit_web_view_get_zoom_level(webView) == zoomLevel)
1987 WKPageRef wkPage = toAPI(webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(webView)));
1988 if (webkit_settings_get_zoom_text_only(webView->priv->settings.get()))
1989 WKPageSetTextZoomFactor(wkPage, zoomLevel);
1991 WKPageSetPageZoomFactor(wkPage, zoomLevel);
1992 g_object_notify(G_OBJECT(webView), "zoom-level");
1996 * webkit_web_view_get_zoom_level:
1997 * @web_view: a #WebKitWebView
1999 * Get the zoom level of @web_view, i.e. the factor by which the
2000 * view contents are scaled with respect to their original size.
2002 * Returns: the current zoom level of @web_view
2004 gdouble webkit_web_view_get_zoom_level(WebKitWebView* webView)
2006 g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 1);
2008 WKPageRef wkPage = toAPI(webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(webView)));
2009 gboolean zoomTextOnly = webkit_settings_get_zoom_text_only(webView->priv->settings.get());
2010 return zoomTextOnly ? WKPageGetTextZoomFactor(wkPage) : WKPageGetPageZoomFactor(wkPage);
2013 struct ValidateEditingCommandAsyncData {
2015 GRefPtr<GCancellable> cancellable;
2017 WEBKIT_DEFINE_ASYNC_DATA_STRUCT(ValidateEditingCommandAsyncData)
2019 static void didValidateCommand(WKStringRef command, bool isEnabled, int32_t state, WKErrorRef, void* context)
2021 GRefPtr<GSimpleAsyncResult> result = adoptGRef(G_SIMPLE_ASYNC_RESULT(context));
2022 ValidateEditingCommandAsyncData* data = static_cast<ValidateEditingCommandAsyncData*>(g_simple_async_result_get_op_res_gpointer(result.get()));
2024 if (g_cancellable_set_error_if_cancelled(data->cancellable.get(), &error))
2025 g_simple_async_result_take_error(result.get(), error);
2027 data->isEnabled = isEnabled;
2028 g_simple_async_result_complete(result.get());
2032 * webkit_web_view_can_execute_editing_command:
2033 * @web_view: a #WebKitWebView
2034 * @command: the command to check
2035 * @cancellable: (allow-none): a #GCancellable or %NULL to ignore
2036 * @callback: (scope async): a #GAsyncReadyCallback to call when the request is satisfied
2037 * @user_data: (closure): the data to pass to callback function
2039 * Asynchronously execute the given editing command.
2041 * When the operation is finished, @callback will be called. You can then call
2042 * webkit_web_view_can_execute_editing_command_finish() to get the result of the operation.
2044 void webkit_web_view_can_execute_editing_command(WebKitWebView* webView, const char* command, GCancellable* cancellable, GAsyncReadyCallback callback, gpointer userData)
2046 g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
2047 g_return_if_fail(command);
2049 GSimpleAsyncResult* result = g_simple_async_result_new(G_OBJECT(webView), callback, userData,
2050 reinterpret_cast<gpointer>(webkit_web_view_can_execute_editing_command));
2051 ValidateEditingCommandAsyncData* data = createValidateEditingCommandAsyncData();
2052 data->cancellable = cancellable;
2053 g_simple_async_result_set_op_res_gpointer(result, data, reinterpret_cast<GDestroyNotify>(destroyValidateEditingCommandAsyncData));
2055 WebPageProxy* page = webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(webView));
2056 WKRetainPtr<WKStringRef> wkCommand(AdoptWK, WKStringCreateWithUTF8CString(command));
2057 WKPageValidateCommand(toAPI(page), wkCommand.get(), result, didValidateCommand);
2061 * webkit_web_view_can_execute_editing_command_finish:
2062 * @web_view: a #WebKitWebView
2063 * @result: a #GAsyncResult
2064 * @error: return location for error or %NULL to ignore
2066 * Finish an asynchronous operation started with webkit_web_view_can_execute_editing_command().
2068 * Returns: %TRUE if the editing command can be executed or %FALSE otherwise
2070 gboolean webkit_web_view_can_execute_editing_command_finish(WebKitWebView* webView, GAsyncResult* result, GError** error)
2072 g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), FALSE);
2073 g_return_val_if_fail(G_IS_ASYNC_RESULT(result), FALSE);
2075 GSimpleAsyncResult* simple = G_SIMPLE_ASYNC_RESULT(result);
2076 g_warn_if_fail(g_simple_async_result_get_source_tag(simple) == webkit_web_view_can_execute_editing_command);
2078 if (g_simple_async_result_propagate_error(simple, error))
2081 ValidateEditingCommandAsyncData* data = static_cast<ValidateEditingCommandAsyncData*>(g_simple_async_result_get_op_res_gpointer(simple));
2082 return data->isEnabled;
2086 * webkit_web_view_execute_editing_command:
2087 * @web_view: a #WebKitWebView
2088 * @command: the command to execute
2090 * Request to execute the given @command for @web_view. You can use
2091 * webkit_web_view_can_execute_editing_command() to check whether
2092 * it's possible to execute the command.
2094 void webkit_web_view_execute_editing_command(WebKitWebView* webView, const char* command)
2096 g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
2097 g_return_if_fail(command);
2099 WebPageProxy* page = webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(webView));
2100 WKRetainPtr<WKStringRef> wkCommand(AdoptWK, WKStringCreateWithUTF8CString(command));
2101 WKPageExecuteCommand(toAPI(page), wkCommand.get());
2105 * webkit_web_view_get_find_controller:
2106 * @web_view: the #WebKitWebView
2108 * Gets the #WebKitFindController that will allow the caller to query
2109 * the #WebKitWebView for the text to look for.
2111 * Returns: (transfer none): the #WebKitFindController associated to
2112 * this particular #WebKitWebView.
2114 WebKitFindController* webkit_web_view_get_find_controller(WebKitWebView* webView)
2116 g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0);
2118 if (!webView->priv->findController)
2119 webView->priv->findController = adoptGRef(WEBKIT_FIND_CONTROLLER(g_object_new(WEBKIT_TYPE_FIND_CONTROLLER, "web-view", webView, NULL)));
2121 return webView->priv->findController.get();
2125 * webkit_web_view_get_javascript_global_context:
2126 * @web_view: a #WebKitWebView
2128 * Get the global JavaScript context used by @web_view to deserialize the
2129 * result values of scripts executed with webkit_web_view_run_javascript().
2131 * Returns: the <function>JSGlobalContextRef</function> used by @web_view to deserialize
2132 * the result values of scripts.
2134 JSGlobalContextRef webkit_web_view_get_javascript_global_context(WebKitWebView* webView)
2136 g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0);
2138 if (!webView->priv->javascriptGlobalContext)
2139 webView->priv->javascriptGlobalContext = JSGlobalContextCreate(0);
2140 return webView->priv->javascriptGlobalContext;
2143 struct RunJavaScriptAsyncData {
2144 ~RunJavaScriptAsyncData()
2147 webkit_javascript_result_unref(scriptResult);
2150 WebKitJavascriptResult* scriptResult;
2151 GRefPtr<GCancellable> cancellable;
2153 WEBKIT_DEFINE_ASYNC_DATA_STRUCT(RunJavaScriptAsyncData)
2155 static void webkitWebViewRunJavaScriptCallback(WKSerializedScriptValueRef wkSerializedScriptValue, WKErrorRef, void* context)
2157 GRefPtr<GSimpleAsyncResult> result = adoptGRef(G_SIMPLE_ASYNC_RESULT(context));
2158 RunJavaScriptAsyncData* data = static_cast<RunJavaScriptAsyncData*>(g_simple_async_result_get_op_res_gpointer(result.get()));
2160 if (g_cancellable_set_error_if_cancelled(data->cancellable.get(), &error))
2161 g_simple_async_result_take_error(result.get(), error);
2162 else if (wkSerializedScriptValue) {
2163 GRefPtr<WebKitWebView> webView = adoptGRef(WEBKIT_WEB_VIEW(g_async_result_get_source_object(G_ASYNC_RESULT(result.get()))));
2164 data->scriptResult = webkitJavascriptResultCreate(webView.get(), wkSerializedScriptValue);
2166 g_set_error_literal(&error, WEBKIT_JAVASCRIPT_ERROR, WEBKIT_JAVASCRIPT_ERROR_SCRIPT_FAILED, _("An exception was raised in JavaScript"));
2167 g_simple_async_result_take_error(result.get(), error);
2169 g_simple_async_result_complete(result.get());
2173 * webkit_web_view_run_javascript:
2174 * @web_view: a #WebKitWebView
2175 * @script: the script to run
2176 * @cancellable: (allow-none): a #GCancellable or %NULL to ignore
2177 * @callback: (scope async): a #GAsyncReadyCallback to call when the script finished
2178 * @user_data: (closure): the data to pass to callback function
2180 * Asynchronously run @script in the context of the current page in @web_view.
2182 * When the operation is finished, @callback will be called. You can then call
2183 * webkit_web_view_run_javascript_finish() to get the result of the operation.
2185 void webkit_web_view_run_javascript(WebKitWebView* webView, const gchar* script, GCancellable* cancellable, GAsyncReadyCallback callback, gpointer userData)
2187 g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
2188 g_return_if_fail(script);
2190 WKPageRef wkPage = toAPI(webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(webView)));
2191 WKRetainPtr<WKStringRef> wkScript = adoptWK(WKStringCreateWithUTF8CString(script));
2192 GSimpleAsyncResult* result = g_simple_async_result_new(G_OBJECT(webView), callback, userData,
2193 reinterpret_cast<gpointer>(webkit_web_view_run_javascript));
2194 RunJavaScriptAsyncData* data = createRunJavaScriptAsyncData();
2195 data->cancellable = cancellable;
2196 g_simple_async_result_set_op_res_gpointer(result, data, reinterpret_cast<GDestroyNotify>(destroyRunJavaScriptAsyncData));
2197 WKPageRunJavaScriptInMainFrame(wkPage, wkScript.get(), result, webkitWebViewRunJavaScriptCallback);
2201 * webkit_web_view_run_javascript_finish:
2202 * @web_view: a #WebKitWebView
2203 * @result: a #GAsyncResult
2204 * @error: return location for error or %NULL to ignore
2206 * Finish an asynchronous operation started with webkit_web_view_run_javascript().
2208 * This is an example of using webkit_web_view_run_javascript() with a script returning
2211 * <informalexample><programlisting>
2213 * web_view_javascript_finished (GObject *object,
2214 * GAsyncResult *result,
2215 * gpointer user_data)
2217 * WebKitJavascriptResult *js_result;
2219 * JSGlobalContextRef context;
2220 * GError *error = NULL;
2222 * js_result = webkit_web_view_run_javascript_finish (WEBKIT_WEB_VIEW (object), result, &error);
2224 * g_warning ("Error running javascript: %s", error->message);
2225 * g_error_free (error);
2229 * context = webkit_javascript_result_get_global_context (js_result);
2230 * value = webkit_javascript_result_get_value (js_result);
2231 * if (JSValueIsString (context, value)) {
2232 * JSStringRef js_str_value;
2236 * js_str_value = JSValueToStringCopy (context, value, NULL);
2237 * str_length = JSStringGetMaximumUTF8CStringSize (js_str_value);
2238 * str_value = (gchar *)g_malloc (str_length);
2239 * JSStringGetUTF8CString (js_str_value, str_value, str_length);
2240 * JSStringRelease (js_str_value);
2241 * g_print ("Script result: %s\n", str_value);
2242 * g_free (str_value);
2244 * g_warning ("Error running javascript: unexpected return value");
2246 * webkit_javascript_result_unref (js_result);
2250 * web_view_get_link_url (WebKitWebView *web_view,
2251 * const gchar *link_id)
2255 * script = g_strdup_printf ("window.document.getElementById('%s').href;", link_id);
2256 * webkit_web_view_run_javascript (web_view, script, NULL, web_view_javascript_finished, NULL);
2259 * </programlisting></informalexample>
2261 * Returns: (transfer full): a #WebKitJavascriptResult with the result of the last executed statement in @script
2262 * or %NULL in case of error
2264 WebKitJavascriptResult* webkit_web_view_run_javascript_finish(WebKitWebView* webView, GAsyncResult* result, GError** error)
2266 g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0);
2267 g_return_val_if_fail(G_IS_ASYNC_RESULT(result), 0);
2269 GSimpleAsyncResult* simpleResult = G_SIMPLE_ASYNC_RESULT(result);
2270 g_warn_if_fail(g_simple_async_result_get_source_tag(simpleResult) == webkit_web_view_run_javascript);
2272 if (g_simple_async_result_propagate_error(simpleResult, error))
2275 RunJavaScriptAsyncData* data = static_cast<RunJavaScriptAsyncData*>(g_simple_async_result_get_op_res_gpointer(simpleResult));
2276 return data->scriptResult ? webkit_javascript_result_ref(data->scriptResult) : 0;
2280 * webkit_web_view_get_main_resource:
2281 * @web_view: a #WebKitWebView
2283 * Return the main resource of @web_view.
2284 * See also webkit_web_view_get_subresources():
2286 * Returns: (transfer none): the main #WebKitWebResource of the view
2287 * or %NULL if nothing has been loaded.
2289 WebKitWebResource* webkit_web_view_get_main_resource(WebKitWebView* webView)
2291 g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0);
2293 return webView->priv->mainResource.get();
2297 * webkit_web_view_get_subresources:
2298 * @web_view: a #WebKitWebView
2300 * Return the list of subresources of @web_view.
2301 * See also webkit_web_view_get_main_resource().
2303 * Returns: (element-type WebKitWebResource) (transfer container): a list of #WebKitWebResource.
2305 GList* webkit_web_view_get_subresources(WebKitWebView* webView)
2307 g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0);
2309 GList* subresources = 0;
2310 WebKitWebViewPrivate* priv = webView->priv;
2311 ResourcesMap::const_iterator end = priv->subresourcesMap.end();
2312 for (ResourcesMap::const_iterator it = priv->subresourcesMap.begin(); it != end; ++it)
2313 subresources = g_list_prepend(subresources, it->second.get());
2315 return g_list_reverse(subresources);
2319 * webkit_web_view_get_inspector:
2320 * @web_view: a #WebKitWebView
2322 * Get the #WebKitWebInspector associated to @web_view
2324 * Returns: (transfer none): the #WebKitWebInspector of @web_view
2326 WebKitWebInspector* webkit_web_view_get_inspector(WebKitWebView* webView)
2328 g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0);
2330 if (!webView->priv->inspector) {
2331 WebPageProxy* page = webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(webView));
2332 webView->priv->inspector = adoptGRef(webkitWebInspectorCreate(toAPI(page->inspector())));
2335 return webView->priv->inspector.get();
2339 * webkit_web_view_can_show_mime_type:
2340 * @web_view: a #WebKitWebView
2341 * @mime_type: a MIME type
2343 * Whether or not a MIME type can be displayed in @web_view.
2345 * Returns: %TRUE if the MIME type @mime_type can be displayed or %FALSE otherwise
2347 gboolean webkit_web_view_can_show_mime_type(WebKitWebView* webView, const char* mimeType)
2349 g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), FALSE);
2350 g_return_val_if_fail(mimeType, FALSE);
2352 WebPageProxy* page = webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(webView));
2353 return page->canShowMIMEType(String::fromUTF8(mimeType));
2356 struct ViewSaveAsyncData {
2357 WKRetainPtr<WKDataRef> wkData;
2358 GRefPtr<GFile> file;
2359 GRefPtr<GCancellable> cancellable;
2361 WEBKIT_DEFINE_ASYNC_DATA_STRUCT(ViewSaveAsyncData)
2363 static void fileReplaceContentsCallback(GObject* object, GAsyncResult* result, gpointer data)
2365 GFile* file = G_FILE(object);
2366 GRefPtr<GSimpleAsyncResult> savedToFileResult = adoptGRef(G_SIMPLE_ASYNC_RESULT(data));
2369 if (!g_file_replace_contents_finish(file, result, 0, &error))
2370 g_simple_async_result_take_error(savedToFileResult.get(), error);
2372 g_simple_async_result_complete(savedToFileResult.get());
2375 static void getContentsAsMHTMLDataCallback(WKDataRef wkData, WKErrorRef, void* context)
2377 GRefPtr<GSimpleAsyncResult> result = adoptGRef(G_SIMPLE_ASYNC_RESULT(context));
2378 ViewSaveAsyncData* data = static_cast<ViewSaveAsyncData*>(g_simple_async_result_get_op_res_gpointer(result.get()));
2381 if (g_cancellable_set_error_if_cancelled(data->cancellable.get(), &error))
2382 g_simple_async_result_take_error(result.get(), error);
2384 // We need to retain the data until the asyncronous process
2385 // initiated by the user has finished completely.
2386 data->wkData = wkData;
2388 // If we are saving to a file we need to write the data on disk before finishing.
2389 if (g_simple_async_result_get_source_tag(result.get()) == webkit_web_view_save_to_file) {
2390 ASSERT(G_IS_FILE(data->file.get()));
2391 g_file_replace_contents_async(data->file.get(), reinterpret_cast<const gchar*>(WKDataGetBytes(data->wkData.get())), WKDataGetSize(data->wkData.get()), 0, FALSE, G_FILE_CREATE_REPLACE_DESTINATION,
2392 data->cancellable.get(), fileReplaceContentsCallback, g_object_ref(result.get()));
2397 g_simple_async_result_complete(result.get());
2401 * webkit_web_view_save:
2402 * @web_view: a #WebKitWebView
2403 * @save_mode: the #WebKitSaveMode specifying how the web page should be saved.
2404 * @cancellable: (allow-none): a #GCancellable or %NULL to ignore
2405 * @callback: (scope async): a #GAsyncReadyCallback to call when the request is satisfied
2406 * @user_data: (closure): the data to pass to callback function
2408 * Asynchronously save the current web page associated to the
2409 * #WebKitWebView into a self-contained format using the mode
2410 * specified in @save_mode.
2412 * When the operation is finished, @callback will be called. You can
2413 * then call webkit_web_view_save_finish() to get the result of the
2416 void webkit_web_view_save(WebKitWebView* webView, WebKitSaveMode saveMode, GCancellable* cancellable, GAsyncReadyCallback callback, gpointer userData)
2418 g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
2420 // We only support MHTML at the moment.
2421 g_return_if_fail(saveMode == WEBKIT_SAVE_MODE_MHTML);
2423 GSimpleAsyncResult* result = g_simple_async_result_new(G_OBJECT(webView), callback, userData,
2424 reinterpret_cast<gpointer>(webkit_web_view_save));
2425 ViewSaveAsyncData* data = createViewSaveAsyncData();
2426 data->cancellable = cancellable;
2427 g_simple_async_result_set_op_res_gpointer(result, data, reinterpret_cast<GDestroyNotify>(destroyViewSaveAsyncData));
2429 WKPageRef wkPage = toAPI(webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(webView)));
2430 WKPageGetContentsAsMHTMLData(wkPage, false, result, getContentsAsMHTMLDataCallback);
2434 * webkit_web_view_save_finish:
2435 * @web_view: a #WebKitWebView
2436 * @result: a #GAsyncResult
2437 * @error: return location for error or %NULL to ignore
2439 * Finish an asynchronous operation started with webkit_web_view_save().
2441 * Returns: (transfer full): a #GInputStream with the result of saving
2442 * the current web page or %NULL in case of error.
2444 GInputStream* webkit_web_view_save_finish(WebKitWebView* webView, GAsyncResult* result, GError** error)
2446 g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), 0);
2447 g_return_val_if_fail(G_IS_ASYNC_RESULT(result), 0);
2449 GSimpleAsyncResult* simple = G_SIMPLE_ASYNC_RESULT(result);
2450 g_warn_if_fail(g_simple_async_result_get_source_tag(simple) == webkit_web_view_save);
2452 if (g_simple_async_result_propagate_error(simple, error))
2455 GInputStream* dataStream = g_memory_input_stream_new();
2456 ViewSaveAsyncData* data = static_cast<ViewSaveAsyncData*>(g_simple_async_result_get_op_res_gpointer(simple));
2457 gsize length = WKDataGetSize(data->wkData.get());
2459 g_memory_input_stream_add_data(G_MEMORY_INPUT_STREAM(dataStream), g_memdup(WKDataGetBytes(data->wkData.get()), length), length, g_free);
2465 * webkit_web_view_save_to_file:
2466 * @web_view: a #WebKitWebView
2467 * @file: the #GFile where the current web page should be saved to.
2468 * @save_mode: the #WebKitSaveMode specifying how the web page should be saved.
2469 * @cancellable: (allow-none): a #GCancellable or %NULL to ignore
2470 * @callback: (scope async): a #GAsyncReadyCallback to call when the request is satisfied
2471 * @user_data: (closure): the data to pass to callback function
2473 * Asynchronously save the current web page associated to the
2474 * #WebKitWebView into a self-contained format using the mode
2475 * specified in @save_mode and writing it to @file.
2477 * When the operation is finished, @callback will be called. You can
2478 * then call webkit_web_view_save_to_file_finish() to get the result of the
2481 void webkit_web_view_save_to_file(WebKitWebView* webView, GFile* file, WebKitSaveMode saveMode, GCancellable* cancellable, GAsyncReadyCallback callback, gpointer userData)
2483 g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView));
2484 g_return_if_fail(G_IS_FILE(file));
2486 // We only support MHTML at the moment.
2487 g_return_if_fail(saveMode == WEBKIT_SAVE_MODE_MHTML);
2489 GSimpleAsyncResult* result = g_simple_async_result_new(G_OBJECT(webView), callback, userData,
2490 reinterpret_cast<gpointer>(webkit_web_view_save_to_file));
2491 ViewSaveAsyncData* data = createViewSaveAsyncData();
2493 data->cancellable = cancellable;
2494 g_simple_async_result_set_op_res_gpointer(result, data, reinterpret_cast<GDestroyNotify>(destroyViewSaveAsyncData));
2496 WKPageRef wkPage = toAPI(webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(webView)));
2497 WKPageGetContentsAsMHTMLData(wkPage, false, result, getContentsAsMHTMLDataCallback);
2501 * webkit_web_view_save_to_file_finish:
2502 * @web_view: a #WebKitWebView
2503 * @result: a #GAsyncResult
2504 * @error: return location for error or %NULL to ignore
2506 * Finish an asynchronous operation started with webkit_web_view_save_to_file().
2508 * Returns: %TRUE if the web page was successfully saved to a file or %FALSE otherwise.
2510 gboolean webkit_web_view_save_to_file_finish(WebKitWebView* webView, GAsyncResult* result, GError** error)
2512 g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), FALSE);
2513 g_return_val_if_fail(G_IS_ASYNC_RESULT(result), FALSE);
2515 GSimpleAsyncResult* simple = G_SIMPLE_ASYNC_RESULT(result);
2516 g_warn_if_fail(g_simple_async_result_get_source_tag(simple) == webkit_web_view_save_to_file);
2518 if (g_simple_async_result_propagate_error(simple, error))