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