1/* 2 * Copyright (C) 2011 Igalia S.L. 3 * 4 * This library is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Library General Public 6 * License as published by the Free Software Foundation; either 7 * version 2 of the License, or (at your option) any later version. 8 * 9 * This library is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * Library General Public License for more details. 13 * 14 * You should have received a copy of the GNU Library General Public License 15 * along with this library; see the file COPYING.LIB. If not, write to 16 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 17 * Boston, MA 02110-1301, USA. 18 */ 19 20#include "config.h" 21#include "WebKitWebContext.h" 22 23#include "APIString.h" 24#include "WebBatteryManagerProxy.h" 25#include "WebCertificateInfo.h" 26#include "WebCookieManagerProxy.h" 27#include "WebGeolocationManagerProxy.h" 28#include "WebKitBatteryProvider.h" 29#include "WebKitCertificateInfoPrivate.h" 30#include "WebKitCookieManagerPrivate.h" 31#include "WebKitDownloadClient.h" 32#include "WebKitDownloadPrivate.h" 33#include "WebKitFaviconDatabasePrivate.h" 34#include "WebKitGeolocationProvider.h" 35#include "WebKitInjectedBundleClient.h" 36#include "WebKitPluginPrivate.h" 37#include "WebKitPrivate.h" 38#include "WebKitRequestManagerClient.h" 39#include "WebKitSecurityManagerPrivate.h" 40#include "WebKitTextChecker.h" 41#include "WebKitURISchemeRequestPrivate.h" 42#include "WebKitUserContentManagerPrivate.h" 43#include "WebKitWebContextPrivate.h" 44#include "WebKitWebViewBasePrivate.h" 45#include "WebKitWebViewGroupPrivate.h" 46#include "WebResourceCacheManagerProxy.h" 47#include <WebCore/FileSystem.h> 48#include <WebCore/IconDatabase.h> 49#include <WebCore/Language.h> 50#include <memory> 51#include <wtf/HashMap.h> 52#include <wtf/NeverDestroyed.h> 53#include <wtf/PassRefPtr.h> 54#include <wtf/RefCounted.h> 55#include <wtf/gobject/GRefPtr.h> 56#include <wtf/gobject/GUniquePtr.h> 57#include <wtf/text/CString.h> 58 59using namespace WebKit; 60 61/** 62 * SECTION: WebKitWebContext 63 * @Short_description: Manages aspects common to all #WebKitWebView<!-- -->s 64 * @Title: WebKitWebContext 65 * 66 * The #WebKitWebContext manages all aspects common to all 67 * #WebKitWebView<!-- -->s. 68 * 69 * You can define the #WebKitCacheModel and #WebKitProcessModel with 70 * webkit_web_context_set_cache_model() and 71 * webkit_web_context_set_process_model(), depending on the needs of 72 * your application. You can access the #WebKitCookieManager or the 73 * #WebKitSecurityManager to specify the behaviour of your application 74 * regarding cookies and security, using 75 * webkit_web_context_get_cookie_manager() and 76 * webkit_web_context_get_security_manager() for that. 77 * 78 * It is also possible to change your preferred language or enable 79 * spell checking, using webkit_web_context_set_preferred_languages(), 80 * webkit_web_context_set_spell_checking_languages() and 81 * webkit_web_context_set_spell_checking_enabled(). 82 * 83 * You can use webkit_web_context_register_uri_scheme() to register 84 * custom URI schemes, and manage several other settings. 85 * 86 */ 87 88enum { 89 DOWNLOAD_STARTED, 90 INITIALIZE_WEB_EXTENSIONS, 91 92 LAST_SIGNAL 93}; 94 95class WebKitURISchemeHandler: public RefCounted<WebKitURISchemeHandler> { 96public: 97 WebKitURISchemeHandler() 98 : m_callback(0) 99 , m_userData(0) 100 , m_destroyNotify(0) 101 { 102 } 103 WebKitURISchemeHandler(WebKitURISchemeRequestCallback callback, void* userData, GDestroyNotify destroyNotify) 104 : m_callback(callback) 105 , m_userData(userData) 106 , m_destroyNotify(destroyNotify) 107 { 108 } 109 110 ~WebKitURISchemeHandler() 111 { 112 if (m_destroyNotify) 113 m_destroyNotify(m_userData); 114 } 115 116 bool hasCallback() 117 { 118 return m_callback; 119 } 120 121 void performCallback(WebKitURISchemeRequest* request) 122 { 123 ASSERT(m_callback); 124 125 m_callback(request, m_userData); 126 } 127 128private: 129 WebKitURISchemeRequestCallback m_callback; 130 void* m_userData; 131 GDestroyNotify m_destroyNotify; 132}; 133 134typedef HashMap<String, RefPtr<WebKitURISchemeHandler> > URISchemeHandlerMap; 135typedef HashMap<uint64_t, GRefPtr<WebKitURISchemeRequest> > URISchemeRequestMap; 136 137struct _WebKitWebContextPrivate { 138 RefPtr<WebContext> context; 139 140 GRefPtr<WebKitCookieManager> cookieManager; 141 GRefPtr<WebKitFaviconDatabase> faviconDatabase; 142 GRefPtr<WebKitSecurityManager> securityManager; 143 RefPtr<WebSoupCustomProtocolRequestManager> requestManager; 144 URISchemeHandlerMap uriSchemeHandlers; 145 URISchemeRequestMap uriSchemeRequests; 146#if ENABLE(GEOLOCATION) 147 RefPtr<WebKitGeolocationProvider> geolocationProvider; 148#endif 149#if ENABLE(BATTERY_STATUS) 150 RefPtr<WebKitBatteryProvider> batteryProvider; 151#endif 152#if ENABLE(SPELLCHECK) 153 std::unique_ptr<WebKitTextChecker> textChecker; 154#endif 155 CString faviconDatabaseDirectory; 156 WebKitTLSErrorsPolicy tlsErrorsPolicy; 157 158 HashMap<uint64_t, WebKitWebView*> webViews; 159 GRefPtr<WebKitWebViewGroup> defaultWebViewGroup; 160 161 CString webExtensionsDirectory; 162 GRefPtr<GVariant> webExtensionsInitializationUserData; 163}; 164 165static guint signals[LAST_SIGNAL] = { 0, }; 166 167WEBKIT_DEFINE_TYPE(WebKitWebContext, webkit_web_context, G_TYPE_OBJECT) 168 169static inline WebKit::ProcessModel toProcessModel(WebKitProcessModel webKitProcessModel) 170{ 171 switch (webKitProcessModel) { 172 case WEBKIT_PROCESS_MODEL_SHARED_SECONDARY_PROCESS: 173 return ProcessModelSharedSecondaryProcess; 174 case WEBKIT_PROCESS_MODEL_MULTIPLE_SECONDARY_PROCESSES: 175 return ProcessModelMultipleSecondaryProcesses; 176 default: 177 ASSERT_NOT_REACHED(); 178 return ProcessModelSharedSecondaryProcess; 179 } 180} 181 182static inline WebKitProcessModel toWebKitProcessModel(WebKit::ProcessModel processModel) 183{ 184 switch (processModel) { 185 case ProcessModelSharedSecondaryProcess: 186 return WEBKIT_PROCESS_MODEL_SHARED_SECONDARY_PROCESS; 187 case ProcessModelMultipleSecondaryProcesses: 188 return WEBKIT_PROCESS_MODEL_MULTIPLE_SECONDARY_PROCESSES; 189 default: 190 ASSERT_NOT_REACHED(); 191 return WEBKIT_PROCESS_MODEL_SHARED_SECONDARY_PROCESS; 192 } 193} 194 195static void webkit_web_context_class_init(WebKitWebContextClass* webContextClass) 196{ 197 GObjectClass* gObjectClass = G_OBJECT_CLASS(webContextClass); 198 199 /** 200 * WebKitWebContext::download-started: 201 * @context: the #WebKitWebContext 202 * @download: the #WebKitDownload associated with this event 203 * 204 * This signal is emitted when a new download request is made. 205 */ 206 signals[DOWNLOAD_STARTED] = 207 g_signal_new("download-started", 208 G_TYPE_FROM_CLASS(gObjectClass), 209 G_SIGNAL_RUN_LAST, 210 0, 0, 0, 211 g_cclosure_marshal_VOID__OBJECT, 212 G_TYPE_NONE, 1, 213 WEBKIT_TYPE_DOWNLOAD); 214 215 /** 216 * WebKitWebContext::initialize-web-extensions: 217 * @context: the #WebKitWebContext 218 * 219 * This signal is emitted when a new web process is about to be 220 * launched. It signals the most appropriate moment to use 221 * webkit_web_context_set_web_extensions_initialization_user_data() 222 * and webkit_web_context_set_web_extensions_directory(). 223 * 224 * Since: 2.4 225 */ 226 signals[INITIALIZE_WEB_EXTENSIONS] = 227 g_signal_new("initialize-web-extensions", 228 G_TYPE_FROM_CLASS(gObjectClass), 229 G_SIGNAL_RUN_LAST, 230 0, nullptr, nullptr, 231 g_cclosure_marshal_VOID__VOID, 232 G_TYPE_NONE, 0); 233} 234 235static CString injectedBundleDirectory() 236{ 237 const char* bundleDirectory = g_getenv("WEBKIT_INJECTED_BUNDLE_PATH"); 238 if (bundleDirectory && g_file_test(bundleDirectory, G_FILE_TEST_IS_DIR)) 239 return bundleDirectory; 240 241 static const char* injectedBundlePath = LIBDIR G_DIR_SEPARATOR_S "webkit2gtk-" WEBKITGTK_API_VERSION_STRING 242 G_DIR_SEPARATOR_S "injected-bundle" G_DIR_SEPARATOR_S; 243 return injectedBundlePath; 244} 245 246static CString injectedBundleFilename() 247{ 248 GUniquePtr<char> bundleFilename(g_build_filename(injectedBundleDirectory().data(), "libwebkit2gtkinjectedbundle.so", NULL)); 249 return bundleFilename.get(); 250} 251 252static gpointer createDefaultWebContext(gpointer) 253{ 254 static GRefPtr<WebKitWebContext> webContext = adoptGRef(WEBKIT_WEB_CONTEXT(g_object_new(WEBKIT_TYPE_WEB_CONTEXT, NULL))); 255 WebKitWebContextPrivate* priv = webContext->priv; 256 257 WebContextConfiguration webContextConfiguration; 258 webContextConfiguration.injectedBundlePath = WebCore::filenameToString(injectedBundleFilename().data()); 259 WebContext::applyPlatformSpecificConfigurationDefaults(webContextConfiguration); 260 priv->context = WebContext::create(WTF::move(webContextConfiguration)); 261 262 priv->requestManager = webContext->priv->context->supplement<WebSoupCustomProtocolRequestManager>(); 263 priv->context->setCacheModel(CacheModelPrimaryWebBrowser); 264 priv->tlsErrorsPolicy = WEBKIT_TLS_ERRORS_POLICY_IGNORE; 265 266 attachInjectedBundleClientToContext(webContext.get()); 267 attachDownloadClientToContext(webContext.get()); 268 attachRequestManagerClientToContext(webContext.get()); 269 270#if ENABLE(GEOLOCATION) 271 priv->geolocationProvider = WebKitGeolocationProvider::create(priv->context->supplement<WebGeolocationManagerProxy>()); 272#endif 273#if ENABLE(BATTERY_STATUS) 274 priv->batteryProvider = WebKitBatteryProvider::create(priv->context->supplement<WebBatteryManagerProxy>()); 275#endif 276#if ENABLE(SPELLCHECK) 277 priv->textChecker = WebKitTextChecker::create(); 278#endif 279 return webContext.get(); 280} 281 282/** 283 * webkit_web_context_get_default: 284 * 285 * Gets the default web context 286 * 287 * Returns: (transfer none): a #WebKitWebContext 288 */ 289WebKitWebContext* webkit_web_context_get_default(void) 290{ 291 static GOnce onceInit = G_ONCE_INIT; 292 return WEBKIT_WEB_CONTEXT(g_once(&onceInit, createDefaultWebContext, 0)); 293} 294 295/** 296 * webkit_web_context_set_cache_model: 297 * @context: the #WebKitWebContext 298 * @cache_model: a #WebKitCacheModel 299 * 300 * Specifies a usage model for WebViews, which WebKit will use to 301 * determine its caching behavior. All web views follow the cache 302 * model. This cache model determines the RAM and disk space to use 303 * for caching previously viewed content . 304 * 305 * Research indicates that users tend to browse within clusters of 306 * documents that hold resources in common, and to revisit previously 307 * visited documents. WebKit and the frameworks below it include 308 * built-in caches that take advantage of these patterns, 309 * substantially improving document load speed in browsing 310 * situations. The WebKit cache model controls the behaviors of all of 311 * these caches, including various WebCore caches. 312 * 313 * Browsers can improve document load speed substantially by 314 * specifying %WEBKIT_CACHE_MODEL_WEB_BROWSER. Applications without a 315 * browsing interface can reduce memory usage substantially by 316 * specifying %WEBKIT_CACHE_MODEL_DOCUMENT_VIEWER. The default value is 317 * %WEBKIT_CACHE_MODEL_WEB_BROWSER. 318 */ 319void webkit_web_context_set_cache_model(WebKitWebContext* context, WebKitCacheModel model) 320{ 321 CacheModel cacheModel; 322 323 g_return_if_fail(WEBKIT_IS_WEB_CONTEXT(context)); 324 325 switch (model) { 326 case WEBKIT_CACHE_MODEL_DOCUMENT_VIEWER: 327 cacheModel = CacheModelDocumentViewer; 328 break; 329 case WEBKIT_CACHE_MODEL_WEB_BROWSER: 330 cacheModel = CacheModelPrimaryWebBrowser; 331 break; 332 case WEBKIT_CACHE_MODEL_DOCUMENT_BROWSER: 333 cacheModel = CacheModelDocumentBrowser; 334 break; 335 default: 336 g_assert_not_reached(); 337 } 338 339 if (cacheModel != context->priv->context->cacheModel()) 340 context->priv->context->setCacheModel(cacheModel); 341} 342 343/** 344 * webkit_web_context_get_cache_model: 345 * @context: the #WebKitWebContext 346 * 347 * Returns the current cache model. For more information about this 348 * value check the documentation of the function 349 * webkit_web_context_set_cache_model(). 350 * 351 * Returns: the current #WebKitCacheModel 352 */ 353WebKitCacheModel webkit_web_context_get_cache_model(WebKitWebContext* context) 354{ 355 g_return_val_if_fail(WEBKIT_IS_WEB_CONTEXT(context), WEBKIT_CACHE_MODEL_WEB_BROWSER); 356 357 switch (context->priv->context->cacheModel()) { 358 case CacheModelDocumentViewer: 359 return WEBKIT_CACHE_MODEL_DOCUMENT_VIEWER; 360 case CacheModelPrimaryWebBrowser: 361 return WEBKIT_CACHE_MODEL_WEB_BROWSER; 362 case CacheModelDocumentBrowser: 363 return WEBKIT_CACHE_MODEL_DOCUMENT_BROWSER; 364 default: 365 g_assert_not_reached(); 366 } 367 368 return WEBKIT_CACHE_MODEL_WEB_BROWSER; 369} 370 371/** 372 * webkit_web_context_clear_cache: 373 * @context: a #WebKitWebContext 374 * 375 * Clears all resources currently cached. 376 * See also webkit_web_context_set_cache_model(). 377 */ 378void webkit_web_context_clear_cache(WebKitWebContext* context) 379{ 380 g_return_if_fail(WEBKIT_IS_WEB_CONTEXT(context)); 381 382 context->priv->context->supplement<WebResourceCacheManagerProxy>()->clearCacheForAllOrigins(AllResourceCaches); 383} 384 385typedef HashMap<DownloadProxy*, GRefPtr<WebKitDownload> > DownloadsMap; 386 387static DownloadsMap& downloadsMap() 388{ 389 static NeverDestroyed<DownloadsMap> downloads; 390 return downloads; 391} 392 393/** 394 * webkit_web_context_download_uri: 395 * @context: a #WebKitWebContext 396 * @uri: the URI to download 397 * 398 * Requests downloading of the specified URI string. The download operation 399 * will not be associated to any #WebKitWebView, if you are interested in 400 * starting a download from a particular #WebKitWebView use 401 * webkit_web_view_download_uri() instead. 402 * 403 * Returns: (transfer full): a new #WebKitDownload representing the 404 * the download operation. 405 */ 406WebKitDownload* webkit_web_context_download_uri(WebKitWebContext* context, const gchar* uri) 407{ 408 g_return_val_if_fail(WEBKIT_IS_WEB_CONTEXT(context), 0); 409 g_return_val_if_fail(uri, 0); 410 411 return webkitWebContextStartDownload(context, uri, 0); 412} 413 414/** 415 * webkit_web_context_get_cookie_manager: 416 * @context: a #WebKitWebContext 417 * 418 * Get the #WebKitCookieManager of @context. 419 * 420 * Returns: (transfer none): the #WebKitCookieManager of @context. 421 */ 422WebKitCookieManager* webkit_web_context_get_cookie_manager(WebKitWebContext* context) 423{ 424 g_return_val_if_fail(WEBKIT_IS_WEB_CONTEXT(context), 0); 425 426 WebKitWebContextPrivate* priv = context->priv; 427 if (!priv->cookieManager) 428 priv->cookieManager = adoptGRef(webkitCookieManagerCreate(priv->context->supplement<WebCookieManagerProxy>())); 429 430 return priv->cookieManager.get(); 431} 432 433static void ensureFaviconDatabase(WebKitWebContext* context) 434{ 435 WebKitWebContextPrivate* priv = context->priv; 436 if (priv->faviconDatabase) 437 return; 438 439 priv->faviconDatabase = adoptGRef(webkitFaviconDatabaseCreate(priv->context->iconDatabase())); 440} 441 442/** 443 * webkit_web_context_set_favicon_database_directory: 444 * @context: a #WebKitWebContext 445 * @path: (allow-none): an absolute path to the icon database 446 * directory or %NULL to use the defaults 447 * 448 * Set the directory path to be used to store the favicons database 449 * for @context on disk. Passing %NULL as @path means using the 450 * default directory for the platform (see g_get_user_data_dir()). 451 * 452 * Calling this method also means enabling the favicons database for 453 * its use from the applications, so that's why it's expected to be 454 * called only once. Further calls for the same instance of 455 * #WebKitWebContext won't cause any effect. 456 */ 457void webkit_web_context_set_favicon_database_directory(WebKitWebContext* context, const gchar* path) 458{ 459 g_return_if_fail(WEBKIT_IS_WEB_CONTEXT(context)); 460 461 WebKitWebContextPrivate* priv = context->priv; 462 WebIconDatabase* iconDatabase = priv->context->iconDatabase(); 463 if (iconDatabase->isOpen()) 464 return; 465 466 ensureFaviconDatabase(context); 467 468 // Use default if 0 is passed as parameter. 469 String directoryPath = WebCore::filenameToString(path); 470 priv->faviconDatabaseDirectory = directoryPath.isEmpty() 471 ? priv->context->iconDatabasePath().utf8() 472 : directoryPath.utf8(); 473 474 // Build the full path to the icon database file on disk. 475 GUniquePtr<gchar> faviconDatabasePath(g_build_filename(priv->faviconDatabaseDirectory.data(), 476 WebCore::IconDatabase::defaultDatabaseFilename().utf8().data(), nullptr)); 477 478 // Setting the path will cause the icon database to be opened. 479 priv->context->setIconDatabasePath(WebCore::filenameToString(faviconDatabasePath.get())); 480} 481 482/** 483 * webkit_web_context_get_favicon_database_directory: 484 * @context: a #WebKitWebContext 485 * 486 * Get the directory path being used to store the favicons database 487 * for @context, or %NULL if 488 * webkit_web_context_set_favicon_database_directory() hasn't been 489 * called yet. 490 * 491 * This function will always return the same path after having called 492 * webkit_web_context_set_favicon_database_directory() for the first 493 * time. 494 * 495 * Returns: (transfer none): the path of the directory of the favicons 496 * database associated with @context, or %NULL. 497 */ 498const gchar* webkit_web_context_get_favicon_database_directory(WebKitWebContext *context) 499{ 500 g_return_val_if_fail(WEBKIT_IS_WEB_CONTEXT(context), 0); 501 502 WebKitWebContextPrivate* priv = context->priv; 503 if (priv->faviconDatabaseDirectory.isNull()) 504 return 0; 505 506 return priv->faviconDatabaseDirectory.data(); 507} 508 509/** 510 * webkit_web_context_get_favicon_database: 511 * @context: a #WebKitWebContext 512 * 513 * Get the #WebKitFaviconDatabase associated with @context. 514 * 515 * To initialize the database you need to call 516 * webkit_web_context_set_favicon_database_directory(). 517 * 518 * Returns: (transfer none): the #WebKitFaviconDatabase of @context. 519 */ 520WebKitFaviconDatabase* webkit_web_context_get_favicon_database(WebKitWebContext* context) 521{ 522 g_return_val_if_fail(WEBKIT_IS_WEB_CONTEXT(context), 0); 523 524 ensureFaviconDatabase(context); 525 return context->priv->faviconDatabase.get(); 526} 527 528/** 529 * webkit_web_context_get_security_manager: 530 * @context: a #WebKitWebContext 531 * 532 * Get the #WebKitSecurityManager of @context. 533 * 534 * Returns: (transfer none): the #WebKitSecurityManager of @context. 535 */ 536WebKitSecurityManager* webkit_web_context_get_security_manager(WebKitWebContext* context) 537{ 538 g_return_val_if_fail(WEBKIT_IS_WEB_CONTEXT(context), 0); 539 540 WebKitWebContextPrivate* priv = context->priv; 541 if (!priv->securityManager) 542 priv->securityManager = adoptGRef(webkitSecurityManagerCreate(context)); 543 544 return priv->securityManager.get(); 545} 546 547/** 548 * webkit_web_context_set_additional_plugins_directory: 549 * @context: a #WebKitWebContext 550 * @directory: the directory to add 551 * 552 * Set an additional directory where WebKit will look for plugins. 553 */ 554void webkit_web_context_set_additional_plugins_directory(WebKitWebContext* context, const char* directory) 555{ 556 g_return_if_fail(WEBKIT_IS_WEB_CONTEXT(context)); 557 g_return_if_fail(directory); 558 559 context->priv->context->setAdditionalPluginsDirectory(WebCore::filenameToString(directory)); 560} 561 562static void destroyPluginList(GList* plugins) 563{ 564 g_list_free_full(plugins, g_object_unref); 565} 566 567static void webkitWebContextGetPluginThread(GTask* task, gpointer object, gpointer /* taskData */, GCancellable*) 568{ 569 Vector<PluginModuleInfo> plugins = WEBKIT_WEB_CONTEXT(object)->priv->context->pluginInfoStore().plugins(); 570 GList* returnValue = 0; 571 for (size_t i = 0; i < plugins.size(); ++i) 572 returnValue = g_list_prepend(returnValue, webkitPluginCreate(plugins[i])); 573 g_task_return_pointer(task, returnValue, reinterpret_cast<GDestroyNotify>(destroyPluginList)); 574} 575 576/** 577 * webkit_web_context_get_plugins: 578 * @context: a #WebKitWebContext 579 * @cancellable: (allow-none): a #GCancellable or %NULL to ignore 580 * @callback: (scope async): a #GAsyncReadyCallback to call when the request is satisfied 581 * @user_data: (closure): the data to pass to callback function 582 * 583 * Asynchronously get the list of installed plugins. 584 * 585 * When the operation is finished, @callback will be called. You can then call 586 * webkit_web_context_get_plugins_finish() to get the result of the operation. 587 */ 588void webkit_web_context_get_plugins(WebKitWebContext* context, GCancellable* cancellable, GAsyncReadyCallback callback, gpointer userData) 589{ 590 g_return_if_fail(WEBKIT_IS_WEB_CONTEXT(context)); 591 592 GRefPtr<GTask> task = adoptGRef(g_task_new(context, cancellable, callback, userData)); 593 g_task_run_in_thread(task.get(), webkitWebContextGetPluginThread); 594} 595 596/** 597 * webkit_web_context_get_plugins_finish: 598 * @context: a #WebKitWebContext 599 * @result: a #GAsyncResult 600 * @error: return location for error or %NULL to ignore 601 * 602 * Finish an asynchronous operation started with webkit_web_context_get_plugins. 603 * 604 * Returns: (element-type WebKitPlugin) (transfer full): a #GList of #WebKitPlugin. You must free the #GList with 605 * g_list_free() and unref the #WebKitPlugin<!-- -->s with g_object_unref() when you're done with them. 606 */ 607GList* webkit_web_context_get_plugins_finish(WebKitWebContext* context, GAsyncResult* result, GError** error) 608{ 609 g_return_val_if_fail(WEBKIT_IS_WEB_CONTEXT(context), 0); 610 g_return_val_if_fail(g_task_is_valid(result, context), 0); 611 612 return static_cast<GList*>(g_task_propagate_pointer(G_TASK(result), error)); 613} 614 615/** 616 * webkit_web_context_register_uri_scheme: 617 * @context: a #WebKitWebContext 618 * @scheme: the network scheme to register 619 * @callback: (scope async): a #WebKitURISchemeRequestCallback 620 * @user_data: data to pass to callback function 621 * @user_data_destroy_func: destroy notify for @user_data 622 * 623 * Register @scheme in @context, so that when an URI request with @scheme is made in the 624 * #WebKitWebContext, the #WebKitURISchemeRequestCallback registered will be called with a 625 * #WebKitURISchemeRequest. 626 * It is possible to handle URI scheme requests asynchronously, by calling g_object_ref() on the 627 * #WebKitURISchemeRequest and calling webkit_uri_scheme_request_finish() later 628 * when the data of the request is available or 629 * webkit_uri_scheme_request_finish_error() in case of error. 630 * 631 * <informalexample><programlisting> 632 * static void 633 * about_uri_scheme_request_cb (WebKitURISchemeRequest *request, 634 * gpointer user_data) 635 * { 636 * GInputStream *stream; 637 * gsize stream_length; 638 * const gchar *path; 639 * 640 * path = webkit_uri_scheme_request_get_path (request); 641 * if (!g_strcmp0 (path, "plugins")) { 642 * /<!-- -->* Create a GInputStream with the contents of plugins about page, and set its length to stream_length *<!-- -->/ 643 * } else if (!g_strcmp0 (path, "memory")) { 644 * /<!-- -->* Create a GInputStream with the contents of memory about page, and set its length to stream_length *<!-- -->/ 645 * } else if (!g_strcmp0 (path, "applications")) { 646 * /<!-- -->* Create a GInputStream with the contents of applications about page, and set its length to stream_length *<!-- -->/ 647 * } else if (!g_strcmp0 (path, "example")) { 648 * gchar *contents; 649 * 650 * contents = g_strdup_printf ("<html><body><p>Example about page</p></body></html>"); 651 * stream_length = strlen (contents); 652 * stream = g_memory_input_stream_new_from_data (contents, stream_length, g_free); 653 * } else { 654 * GError *error; 655 * 656 * error = g_error_new (ABOUT_HANDLER_ERROR, ABOUT_HANDLER_ERROR_INVALID, "Invalid about:%s page.", path); 657 * webkit_uri_scheme_request_finish_error (request, error); 658 * g_error_free (error); 659 * return; 660 * } 661 * webkit_uri_scheme_request_finish (request, stream, stream_length, "text/html"); 662 * g_object_unref (stream); 663 * } 664 * </programlisting></informalexample> 665 */ 666void webkit_web_context_register_uri_scheme(WebKitWebContext* context, const char* scheme, WebKitURISchemeRequestCallback callback, gpointer userData, GDestroyNotify destroyNotify) 667{ 668 g_return_if_fail(WEBKIT_IS_WEB_CONTEXT(context)); 669 g_return_if_fail(scheme); 670 g_return_if_fail(callback); 671 672 RefPtr<WebKitURISchemeHandler> handler = adoptRef(new WebKitURISchemeHandler(callback, userData, destroyNotify)); 673 context->priv->uriSchemeHandlers.set(String::fromUTF8(scheme), handler.get()); 674 context->priv->requestManager->registerSchemeForCustomProtocol(String::fromUTF8(scheme)); 675} 676 677/** 678 * webkit_web_context_get_spell_checking_enabled: 679 * @context: a #WebKitWebContext 680 * 681 * Get whether spell checking feature is currently enabled. 682 * 683 * Returns: %TRUE If spell checking is enabled, or %FALSE otherwise. 684 */ 685gboolean webkit_web_context_get_spell_checking_enabled(WebKitWebContext* context) 686{ 687 g_return_val_if_fail(WEBKIT_IS_WEB_CONTEXT(context), FALSE); 688 689#if ENABLE(SPELLCHECK) 690 return context->priv->textChecker->isSpellCheckingEnabled(); 691#else 692 return false; 693#endif 694} 695 696/** 697 * webkit_web_context_set_spell_checking_enabled: 698 * @context: a #WebKitWebContext 699 * @enabled: Value to be set 700 * 701 * Enable or disable the spell checking feature. 702 */ 703void webkit_web_context_set_spell_checking_enabled(WebKitWebContext* context, gboolean enabled) 704{ 705 g_return_if_fail(WEBKIT_IS_WEB_CONTEXT(context)); 706 707#if ENABLE(SPELLCHECK) 708 context->priv->textChecker->setSpellCheckingEnabled(enabled); 709#endif 710} 711 712/** 713 * webkit_web_context_get_spell_checking_languages: 714 * @context: a #WebKitWebContext 715 * 716 * Get the the list of spell checking languages associated with 717 * @context, or %NULL if no languages have been previously set. 718 * 719 * See webkit_web_context_set_spell_checking_languages() for more 720 * details on the format of the languages in the list. 721 * 722 * Returns: (array zero-terminated=1) (element-type utf8) (transfer none): A %NULL-terminated 723 * array of languages if available, or %NULL otherwise. 724 */ 725const gchar* const* webkit_web_context_get_spell_checking_languages(WebKitWebContext* context) 726{ 727 g_return_val_if_fail(WEBKIT_IS_WEB_CONTEXT(context), 0); 728 729#if ENABLE(SPELLCHECK) 730 return context->priv->textChecker->getSpellCheckingLanguages(); 731#else 732 return 0; 733#endif 734} 735 736/** 737 * webkit_web_context_set_spell_checking_languages: 738 * @context: a #WebKitWebContext 739 * @languages: (array zero-terminated=1) (transfer none): a %NULL-terminated list of spell checking languages 740 * 741 * Set the list of spell checking languages to be used for spell 742 * checking. 743 * 744 * The locale string typically is in the form lang_COUNTRY, where lang 745 * is an ISO-639 language code, and COUNTRY is an ISO-3166 country code. 746 * For instance, sv_FI for Swedish as written in Finland or pt_BR 747 * for Portuguese as written in Brazil. 748 * 749 * You need to call this function with a valid list of languages at 750 * least once in order to properly enable the spell checking feature 751 * in WebKit. 752 */ 753void webkit_web_context_set_spell_checking_languages(WebKitWebContext* context, const gchar* const* languages) 754{ 755 g_return_if_fail(WEBKIT_IS_WEB_CONTEXT(context)); 756 g_return_if_fail(languages); 757 758#if ENABLE(SPELLCHECK) 759 context->priv->textChecker->setSpellCheckingLanguages(languages); 760#endif 761} 762 763/** 764 * webkit_web_context_set_preferred_languages: 765 * @context: a #WebKitWebContext 766 * @languages: (allow-none) (array zero-terminated=1) (element-type utf8) (transfer none): a %NULL-terminated list of language identifiers 767 * 768 * Set the list of preferred languages, sorted from most desirable 769 * to least desirable. The list will be used to build the "Accept-Language" 770 * header that will be included in the network requests started by 771 * the #WebKitWebContext. 772 */ 773void webkit_web_context_set_preferred_languages(WebKitWebContext* context, const gchar* const* languageList) 774{ 775 g_return_if_fail(WEBKIT_IS_WEB_CONTEXT(context)); 776 777 if (!languageList || !g_strv_length(const_cast<char**>(languageList))) 778 return; 779 780 Vector<String> languages; 781 for (size_t i = 0; languageList[i]; ++i) 782 languages.append(String::fromUTF8(languageList[i]).lower().replace("_", "-")); 783 784 WebCore::overrideUserPreferredLanguages(languages); 785 WebCore::languageDidChange(); 786} 787 788/** 789 * webkit_web_context_set_tls_errors_policy: 790 * @context: a #WebKitWebContext 791 * @policy: a #WebKitTLSErrorsPolicy 792 * 793 * Set the TLS errors policy of @context as @policy 794 */ 795void webkit_web_context_set_tls_errors_policy(WebKitWebContext* context, WebKitTLSErrorsPolicy policy) 796{ 797 g_return_if_fail(WEBKIT_IS_WEB_CONTEXT(context)); 798 799 if (context->priv->tlsErrorsPolicy == policy) 800 return; 801 802 context->priv->tlsErrorsPolicy = policy; 803 bool ignoreTLSErrors = policy == WEBKIT_TLS_ERRORS_POLICY_IGNORE; 804 if (context->priv->context->ignoreTLSErrors() != ignoreTLSErrors) 805 context->priv->context->setIgnoreTLSErrors(ignoreTLSErrors); 806} 807 808/** 809 * webkit_web_context_get_tls_errors_policy: 810 * @context: a #WebKitWebContext 811 * 812 * Get the TLS errors policy of @context 813 * 814 * Returns: a #WebKitTLSErrorsPolicy 815 */ 816WebKitTLSErrorsPolicy webkit_web_context_get_tls_errors_policy(WebKitWebContext* context) 817{ 818 g_return_val_if_fail(WEBKIT_IS_WEB_CONTEXT(context), WEBKIT_TLS_ERRORS_POLICY_IGNORE); 819 820 return context->priv->tlsErrorsPolicy; 821} 822 823/** 824 * webkit_web_context_set_web_extensions_directory: 825 * @context: a #WebKitWebContext 826 * @directory: the directory to add 827 * 828 * Set the directory where WebKit will look for Web Extensions. 829 * This method must be called before loading anything in this context, 830 * otherwise it will not have any effect. You can connect to 831 * #WebKitWebContext::initialize-web-extensions to call this method 832 * before anything is loaded. 833 */ 834void webkit_web_context_set_web_extensions_directory(WebKitWebContext* context, const char* directory) 835{ 836 g_return_if_fail(WEBKIT_IS_WEB_CONTEXT(context)); 837 g_return_if_fail(directory); 838 839 context->priv->webExtensionsDirectory = directory; 840} 841 842/** 843 * webkit_web_context_set_web_extensions_initialization_user_data: 844 * @context: a #WebKitWebContext 845 * @user_data: a #GVariant 846 * 847 * Set user data to be passed to Web Extensions on initialization. 848 * The data will be passed to the 849 * #WebKitWebExtensionInitializeWithUserDataFunction. 850 * This method must be called before loading anything in this context, 851 * otherwise it will not have any effect. You can connect to 852 * #WebKitWebContext::initialize-web-extensions to call this method 853 * before anything is loaded. 854 * 855 * Since: 2.4 856 */ 857void webkit_web_context_set_web_extensions_initialization_user_data(WebKitWebContext* context, GVariant* userData) 858{ 859 g_return_if_fail(WEBKIT_IS_WEB_CONTEXT(context)); 860 g_return_if_fail(userData); 861 862 context->priv->webExtensionsInitializationUserData = userData; 863} 864 865/** 866 * webkit_web_context_set_disk_cache_directory: 867 * @context: a #WebKitWebContext 868 * @directory: the directory to set 869 * 870 * Set the directory where disk cache files will be stored 871 * This method must be called before loading anything in this context, otherwise 872 * it will not have any effect. 873 */ 874void webkit_web_context_set_disk_cache_directory(WebKitWebContext* context, const char* directory) 875{ 876 g_return_if_fail(WEBKIT_IS_WEB_CONTEXT(context)); 877 g_return_if_fail(directory); 878 879 context->priv->context->setDiskCacheDirectory(WebCore::filenameToString(directory)); 880} 881 882/** 883 * webkit_web_context_prefetch_dns: 884 * @context: a #WebKitWebContext 885 * @hostname: a hostname to be resolved 886 * 887 * Resolve the domain name of the given @hostname in advance, so that if a URI 888 * of @hostname is requested the load will be performed more quickly. 889 */ 890void webkit_web_context_prefetch_dns(WebKitWebContext* context, const char* hostname) 891{ 892 g_return_if_fail(WEBKIT_IS_WEB_CONTEXT(context)); 893 g_return_if_fail(hostname); 894 895 ImmutableDictionary::MapType message; 896 message.set(String::fromUTF8("Hostname"), API::String::create(String::fromUTF8(hostname))); 897 context->priv->context->postMessageToInjectedBundle(String::fromUTF8("PrefetchDNS"), ImmutableDictionary::create(WTF::move(message)).get()); 898} 899 900/** 901 * webkit_web_context_allow_tls_certificate_for_host: 902 * @context: a #WebKitWebContext 903 * @info: a #WebKitCertificateInfo 904 * @host: the host for which a certificate is to be allowed 905 * 906 * Ignore further TLS errors on the @host for the certificate present in @info. 907 * 908 * Since: 2.4 909 */ 910void webkit_web_context_allow_tls_certificate_for_host(WebKitWebContext* context, WebKitCertificateInfo* info, const gchar* host) 911{ 912 g_return_if_fail(WEBKIT_IS_WEB_CONTEXT(context)); 913 g_return_if_fail(info); 914 g_return_if_fail(host); 915 916 RefPtr<WebCertificateInfo> webCertificateInfo = WebCertificateInfo::create(webkitCertificateInfoGetCertificateInfo(info)); 917 context->priv->context->allowSpecificHTTPSCertificateForHost(webCertificateInfo.get(), String::fromUTF8(host)); 918} 919 920/** 921 * webkit_web_context_set_process_model: 922 * @context: the #WebKitWebContext 923 * @process_model: a #WebKitProcessModel 924 * 925 * Specifies a process model for WebViews, which WebKit will use to 926 * determine how auxiliary processes are handled. The default setting 927 * (%WEBKIT_PROCESS_MODEL_SHARED_SECONDARY_PROCESS) is suitable for most 928 * applications which embed a small amount of WebViews, or are used to 929 * display documents which are considered safe — like local files. 930 * 931 * Applications which may potentially use a large amount of WebViews 932 * —for example a multi-tabbed web browser— may want to use 933 * %WEBKIT_PROCESS_MODEL_MULTIPLE_SECONDARY_PROCESSES, which will use 934 * one process per view most of the time, while still allowing for web 935 * views to share a process when needed (for example when different 936 * views interact with each other). Using this model, when a process 937 * hangs or crashes, only the WebViews using it stop working, while 938 * the rest of the WebViews in the application will still function 939 * normally. 940 * 941 * This method **must be called before any other functions**, 942 * as early as possible in your application. Calling it later will make 943 * your application crash. 944 * 945 * Since: 2.4 946 */ 947void webkit_web_context_set_process_model(WebKitWebContext* context, WebKitProcessModel processModel) 948{ 949 g_return_if_fail(WEBKIT_IS_WEB_CONTEXT(context)); 950 951 ProcessModel newProcessModel(toProcessModel(processModel)); 952 953 if (newProcessModel == context->priv->context->processModel()) 954 return; 955 956 context->priv->context->setUsesNetworkProcess(newProcessModel == ProcessModelMultipleSecondaryProcesses); 957 context->priv->context->setProcessModel(newProcessModel); 958} 959 960/** 961 * webkit_web_context_get_process_model: 962 * @context: the #WebKitWebContext 963 * 964 * Returns the current process model. For more information about this value 965 * see webkit_web_context_set_process_model(). 966 * 967 * Returns: the current #WebKitProcessModel 968 * 969 * Since: 2.4 970 */ 971WebKitProcessModel webkit_web_context_get_process_model(WebKitWebContext* context) 972{ 973 g_return_val_if_fail(WEBKIT_IS_WEB_CONTEXT(context), WEBKIT_PROCESS_MODEL_SHARED_SECONDARY_PROCESS); 974 975 return toWebKitProcessModel(context->priv->context->processModel()); 976} 977 978WebKitDownload* webkitWebContextGetOrCreateDownload(DownloadProxy* downloadProxy) 979{ 980 GRefPtr<WebKitDownload> download = downloadsMap().get(downloadProxy); 981 if (download) 982 return download.get(); 983 984 download = adoptGRef(webkitDownloadCreate(downloadProxy)); 985 downloadsMap().set(downloadProxy, download.get()); 986 return download.get(); 987} 988 989WebKitDownload* webkitWebContextStartDownload(WebKitWebContext* context, const char* uri, WebPageProxy* initiatingPage) 990{ 991 WebCore::ResourceRequest request(String::fromUTF8(uri)); 992 DownloadProxy* downloadProxy = context->priv->context->download(initiatingPage, request); 993 WebKitDownload* download = webkitDownloadCreateForRequest(downloadProxy, request); 994 downloadsMap().set(downloadProxy, download); 995 return download; 996} 997 998void webkitWebContextRemoveDownload(DownloadProxy* downloadProxy) 999{ 1000 downloadsMap().remove(downloadProxy); 1001} 1002 1003void webkitWebContextDownloadStarted(WebKitWebContext* context, WebKitDownload* download) 1004{ 1005 g_signal_emit(context, signals[DOWNLOAD_STARTED], 0, download); 1006} 1007 1008GVariant* webkitWebContextInitializeWebExtensions(WebKitWebContext* context) 1009{ 1010 g_signal_emit(context, signals[INITIALIZE_WEB_EXTENSIONS], 0); 1011 return g_variant_new("(msmv)", 1012 context->priv->webExtensionsDirectory.data(), 1013 context->priv->webExtensionsInitializationUserData.get()); 1014} 1015 1016WebContext* webkitWebContextGetContext(WebKitWebContext* context) 1017{ 1018 g_assert(WEBKIT_IS_WEB_CONTEXT(context)); 1019 1020 return context->priv->context.get(); 1021} 1022 1023WebSoupCustomProtocolRequestManager* webkitWebContextGetRequestManager(WebKitWebContext* context) 1024{ 1025 return context->priv->requestManager.get(); 1026} 1027 1028void webkitWebContextStartLoadingCustomProtocol(WebKitWebContext* context, uint64_t customProtocolID, API::URLRequest* urlRequest) 1029{ 1030 GRefPtr<WebKitURISchemeRequest> request = adoptGRef(webkitURISchemeRequestCreate(customProtocolID, context, urlRequest)); 1031 String scheme(String::fromUTF8(webkit_uri_scheme_request_get_scheme(request.get()))); 1032 RefPtr<WebKitURISchemeHandler> handler = context->priv->uriSchemeHandlers.get(scheme); 1033 ASSERT(handler.get()); 1034 if (!handler->hasCallback()) 1035 return; 1036 1037 context->priv->uriSchemeRequests.set(customProtocolID, request.get()); 1038 handler->performCallback(request.get()); 1039} 1040 1041void webkitWebContextStopLoadingCustomProtocol(WebKitWebContext* context, uint64_t customProtocolID) 1042{ 1043 GRefPtr<WebKitURISchemeRequest> request = context->priv->uriSchemeRequests.get(customProtocolID); 1044 if (!request.get()) 1045 return; 1046 webkitURISchemeRequestCancel(request.get()); 1047} 1048 1049void webkitWebContextDidFinishLoadingCustomProtocol(WebKitWebContext* context, uint64_t customProtocolID) 1050{ 1051 context->priv->uriSchemeRequests.remove(customProtocolID); 1052} 1053 1054void webkitWebContextCreatePageForWebView(WebKitWebContext* context, WebKitWebView* webView, WebKitWebViewGroup* webViewGroup, WebKitUserContentManager* userContentManager, WebKitWebView* relatedView) 1055{ 1056 WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(webView); 1057 WebPageGroup* pageGroup = webViewGroup ? webkitWebViewGroupGetPageGroup(webViewGroup) : 0; 1058 WebPageProxy* relatedPage = relatedView ? webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(relatedView)) : nullptr; 1059 WebUserContentControllerProxy* userContentControllerProxy = userContentManager ? webkitUserContentManagerGetUserContentControllerProxy(userContentManager) : nullptr; 1060 webkitWebViewBaseCreateWebPage(webViewBase, context->priv->context.get(), pageGroup, userContentControllerProxy, relatedPage); 1061 1062 WebPageProxy* page = webkitWebViewBaseGetPage(webViewBase); 1063 context->priv->webViews.set(page->pageID(), webView); 1064 1065 if (!pageGroup && !context->priv->defaultWebViewGroup) 1066 context->priv->defaultWebViewGroup = adoptGRef(webkitWebViewGroupCreate(&page->pageGroup())); 1067} 1068 1069void webkitWebContextWebViewDestroyed(WebKitWebContext* context, WebKitWebView* webView) 1070{ 1071 WebPageProxy* page = webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(webView)); 1072 context->priv->webViews.remove(page->pageID()); 1073} 1074 1075WebKitWebView* webkitWebContextGetWebViewForPage(WebKitWebContext* context, WebPageProxy* page) 1076{ 1077 return page ? context->priv->webViews.get(page->pageID()) : 0; 1078} 1079 1080WebKitWebViewGroup* webkitWebContextGetDefaultWebViewGroup(WebKitWebContext* context) 1081{ 1082 return context->priv->defaultWebViewGroup.get(); 1083} 1084