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