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