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