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