7d5853ef60f387b7c00ced42af373c331f02f8cf
[WebKit.git] / Source / WebKit / UIProcess / API / glib / 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 "APIAutomationClient.h"
24 #include "APICustomProtocolManagerClient.h"
25 #include "APIDownloadClient.h"
26 #include "APIInjectedBundleClient.h"
27 #include "APIPageConfiguration.h"
28 #include "APIProcessPoolConfiguration.h"
29 #include "APIString.h"
30 #include "TextChecker.h"
31 #include "TextCheckerState.h"
32 #include "WebAutomationSession.h"
33 #include "WebCertificateInfo.h"
34 #include "WebGeolocationManagerProxy.h"
35 #include "WebKitAutomationSessionPrivate.h"
36 #include "WebKitCustomProtocolManagerClient.h"
37 #include "WebKitDownloadClient.h"
38 #include "WebKitDownloadPrivate.h"
39 #include "WebKitFaviconDatabasePrivate.h"
40 #include "WebKitGeolocationProvider.h"
41 #include "WebKitInjectedBundleClient.h"
42 #include "WebKitNetworkProxySettingsPrivate.h"
43 #include "WebKitNotificationProvider.h"
44 #include "WebKitPluginPrivate.h"
45 #include "WebKitPrivate.h"
46 #include "WebKitSecurityManagerPrivate.h"
47 #include "WebKitSecurityOriginPrivate.h"
48 #include "WebKitSettingsPrivate.h"
49 #include "WebKitURISchemeRequestPrivate.h"
50 #include "WebKitUserContentManagerPrivate.h"
51 #include "WebKitWebContextPrivate.h"
52 #include "WebKitWebViewPrivate.h"
53 #include "WebKitWebsiteDataManagerPrivate.h"
54 #include "WebNotificationManagerProxy.h"
55 #include "WebsiteDataType.h"
56 #include <JavaScriptCore/RemoteInspector.h>
57 #include <WebCore/FileSystem.h>
58 #include <glib/gi18n-lib.h>
59 #include <libintl.h>
60 #include <memory>
61 #include <wtf/HashMap.h>
62 #include <wtf/Language.h>
63 #include <wtf/NeverDestroyed.h>
64 #include <wtf/RefCounted.h>
65 #include <wtf/RefPtr.h>
66 #include <wtf/glib/GRefPtr.h>
67 #include <wtf/glib/GUniquePtr.h>
68 #include <wtf/glib/WTFGType.h>
69 #include <wtf/text/CString.h>
70
71 #if PLATFORM(GTK)
72 #include "WebKitRemoteInspectorProtocolHandler.h"
73 #endif
74
75 using namespace WebKit;
76
77 /**
78  * SECTION: WebKitWebContext
79  * @Short_description: Manages aspects common to all #WebKitWebView<!-- -->s
80  * @Title: WebKitWebContext
81  *
82  * The #WebKitWebContext manages all aspects common to all
83  * #WebKitWebView<!-- -->s.
84  *
85  * You can define the #WebKitCacheModel and #WebKitProcessModel with
86  * webkit_web_context_set_cache_model() and
87  * webkit_web_context_set_process_model(), depending on the needs of
88  * your application. You can access the #WebKitSecurityManager to specify
89  * the behaviour of your application regarding security using
90  * webkit_web_context_get_security_manager().
91  *
92  * It is also possible to change your preferred language or enable
93  * spell checking, using webkit_web_context_set_preferred_languages(),
94  * webkit_web_context_set_spell_checking_languages() and
95  * webkit_web_context_set_spell_checking_enabled().
96  *
97  * You can use webkit_web_context_register_uri_scheme() to register
98  * custom URI schemes, and manage several other settings.
99  *
100  * TLS certificate validation failure is now treated as a transport
101  * error by default. To handle TLS failures differently, you can
102  * connect to #WebKitWebView::load-failed-with-tls-errors.
103  * Alternatively, you can use webkit_web_context_set_tls_errors_policy()
104  * to set the policy %WEBKIT_TLS_ERRORS_POLICY_IGNORE; however, this is
105  * not appropriate for Internet applications.
106  *
107  */
108
109 enum {
110     PROP_0,
111
112     PROP_LOCAL_STORAGE_DIRECTORY,
113     PROP_WEBSITE_DATA_MANAGER
114 };
115
116 enum {
117     DOWNLOAD_STARTED,
118     INITIALIZE_WEB_EXTENSIONS,
119     INITIALIZE_NOTIFICATION_PERMISSIONS,
120     AUTOMATION_STARTED,
121
122     LAST_SIGNAL
123 };
124
125 class WebKitURISchemeHandler: public RefCounted<WebKitURISchemeHandler> {
126 public:
127     WebKitURISchemeHandler(WebKitURISchemeRequestCallback callback, void* userData, GDestroyNotify destroyNotify)
128         : m_callback(callback)
129         , m_userData(userData)
130         , m_destroyNotify(destroyNotify)
131     {
132     }
133
134     ~WebKitURISchemeHandler()
135     {
136         if (m_destroyNotify)
137             m_destroyNotify(m_userData);
138     }
139
140     bool hasCallback()
141     {
142         return m_callback;
143     }
144
145     void performCallback(WebKitURISchemeRequest* request)
146     {
147         ASSERT(m_callback);
148
149         m_callback(request, m_userData);
150     }
151
152 private:
153     WebKitURISchemeRequestCallback m_callback { nullptr };
154     void* m_userData { nullptr };
155     GDestroyNotify m_destroyNotify { nullptr };
156 };
157
158 typedef HashMap<String, RefPtr<WebKitURISchemeHandler> > URISchemeHandlerMap;
159 typedef HashMap<uint64_t, GRefPtr<WebKitURISchemeRequest> > URISchemeRequestMap;
160
161 class WebKitAutomationClient;
162
163 struct _WebKitWebContextPrivate {
164     RefPtr<WebProcessPool> processPool;
165     bool clientsDetached;
166
167     GRefPtr<WebKitFaviconDatabase> faviconDatabase;
168     GRefPtr<WebKitSecurityManager> securityManager;
169     URISchemeHandlerMap uriSchemeHandlers;
170     URISchemeRequestMap uriSchemeRequests;
171 #if ENABLE(GEOLOCATION)
172     std::unique_ptr<WebKitGeolocationProvider> geolocationProvider;
173 #endif
174     std::unique_ptr<WebKitNotificationProvider> notificationProvider;
175     GRefPtr<WebKitWebsiteDataManager> websiteDataManager;
176
177     CString faviconDatabaseDirectory;
178     WebKitTLSErrorsPolicy tlsErrorsPolicy;
179     WebKitProcessModel processModel;
180     unsigned processCountLimit;
181
182     HashMap<uint64_t, WebKitWebView*> webViews;
183     unsigned ephemeralPageCount;
184
185     CString webExtensionsDirectory;
186     GRefPtr<GVariant> webExtensionsInitializationUserData;
187
188     CString localStorageDirectory;
189 #if ENABLE(REMOTE_INSPECTOR)
190 #if PLATFORM(GTK)
191     std::unique_ptr<RemoteInspectorProtocolHandler> remoteInspectorProtocolHandler;
192 #endif
193     std::unique_ptr<WebKitAutomationClient> automationClient;
194     GRefPtr<WebKitAutomationSession> automationSession;
195 #endif
196 };
197
198 static guint signals[LAST_SIGNAL] = { 0, };
199
200 #if ENABLE(REMOTE_INSPECTOR)
201 class WebKitAutomationClient final : Inspector::RemoteInspector::Client {
202 public:
203     explicit WebKitAutomationClient(WebKitWebContext* context)
204         : m_webContext(context)
205     {
206         Inspector::RemoteInspector::singleton().setClient(this);
207     }
208
209     ~WebKitAutomationClient()
210     {
211         Inspector::RemoteInspector::singleton().setClient(nullptr);
212     }
213
214 private:
215     bool remoteAutomationAllowed() const override { return true; }
216
217     String browserName() const override
218     {
219         if (!m_webContext->priv->automationSession)
220             return { };
221
222         return webkitAutomationSessionGetBrowserName(m_webContext->priv->automationSession.get());
223     }
224
225     String browserVersion() const override
226     {
227         if (!m_webContext->priv->automationSession)
228             return { };
229
230         return webkitAutomationSessionGetBrowserVersion(m_webContext->priv->automationSession.get());
231     }
232
233     void requestAutomationSession(const String& sessionIdentifier) override
234     {
235         ASSERT(!m_webContext->priv->automationSession);
236         m_webContext->priv->automationSession = adoptGRef(webkitAutomationSessionCreate(m_webContext, sessionIdentifier.utf8().data()));
237         g_signal_emit(m_webContext, signals[AUTOMATION_STARTED], 0, m_webContext->priv->automationSession.get());
238         m_webContext->priv->processPool->setAutomationSession(&webkitAutomationSessionGetSession(m_webContext->priv->automationSession.get()));
239     }
240
241     WebKitWebContext* m_webContext;
242 };
243 #endif // ENABLE(REMOTE_INSPECTOR)
244
245 WEBKIT_DEFINE_TYPE(WebKitWebContext, webkit_web_context, G_TYPE_OBJECT)
246
247 #if PLATFORM(GTK)
248 #define INJECTED_BUNDLE_FILENAME "libwebkit2gtkinjectedbundle.so"
249 #elif PLATFORM(WPE)
250 #define INJECTED_BUNDLE_FILENAME "libWPEInjectedBundle.so"
251 #endif
252
253 static const char* injectedBundleDirectory()
254 {
255 #if ENABLE(DEVELOPER_MODE)
256     const char* bundleDirectory = g_getenv("WEBKIT_INJECTED_BUNDLE_PATH");
257     if (bundleDirectory && g_file_test(bundleDirectory, G_FILE_TEST_IS_DIR))
258         return bundleDirectory;
259 #endif
260
261 #if PLATFORM(GTK)
262     static const char* injectedBundlePath = LIBDIR G_DIR_SEPARATOR_S "webkit2gtk-" WEBKITGTK_API_VERSION_STRING
263         G_DIR_SEPARATOR_S "injected-bundle" G_DIR_SEPARATOR_S;
264     return injectedBundlePath;
265 #elif PLATFORM(WPE)
266     // FIXME: Make it possible to use installed injected bundle in WPE.
267     return nullptr;
268 #endif
269 }
270
271 static void webkitWebContextGetProperty(GObject* object, guint propID, GValue* value, GParamSpec* paramSpec)
272 {
273     WebKitWebContext* context = WEBKIT_WEB_CONTEXT(object);
274
275     switch (propID) {
276     case PROP_LOCAL_STORAGE_DIRECTORY:
277         g_value_set_string(value, context->priv->localStorageDirectory.data());
278         break;
279     case PROP_WEBSITE_DATA_MANAGER:
280         g_value_set_object(value, webkit_web_context_get_website_data_manager(context));
281         break;
282     default:
283         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propID, paramSpec);
284     }
285 }
286
287 static void webkitWebContextSetProperty(GObject* object, guint propID, const GValue* value, GParamSpec* paramSpec)
288 {
289     WebKitWebContext* context = WEBKIT_WEB_CONTEXT(object);
290
291     switch (propID) {
292     case PROP_LOCAL_STORAGE_DIRECTORY:
293         context->priv->localStorageDirectory = g_value_get_string(value);
294         break;
295     case PROP_WEBSITE_DATA_MANAGER: {
296         gpointer manager = g_value_get_object(value);
297         context->priv->websiteDataManager = manager ? WEBKIT_WEBSITE_DATA_MANAGER(manager) : nullptr;
298         break;
299     }
300     default:
301         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propID, paramSpec);
302     }
303 }
304
305 static inline WebsiteDataStore::Configuration websiteDataStoreConfigurationForWebProcessPoolConfiguration(const API::ProcessPoolConfiguration& processPoolconfigurarion)
306 {
307     WebsiteDataStore::Configuration configuration;
308     configuration.applicationCacheDirectory = processPoolconfigurarion.applicationCacheDirectory();
309     configuration.networkCacheDirectory = processPoolconfigurarion.diskCacheDirectory();
310     configuration.webSQLDatabaseDirectory = processPoolconfigurarion.webSQLDatabaseDirectory();
311     configuration.localStorageDirectory = processPoolconfigurarion.localStorageDirectory();
312     configuration.mediaKeysStorageDirectory = processPoolconfigurarion.mediaKeysStorageDirectory();
313     configuration.resourceLoadStatisticsDirectory = processPoolconfigurarion.resourceLoadStatisticsDirectory();
314     return configuration;
315 }
316
317 static void webkitWebContextConstructed(GObject* object)
318 {
319     G_OBJECT_CLASS(webkit_web_context_parent_class)->constructed(object);
320
321     GUniquePtr<char> bundleFilename(g_build_filename(injectedBundleDirectory(), INJECTED_BUNDLE_FILENAME, nullptr));
322
323     API::ProcessPoolConfiguration configuration;
324     configuration.setInjectedBundlePath(WebCore::FileSystem::stringFromFileSystemRepresentation(bundleFilename.get()));
325     configuration.setMaximumProcessCount(1);
326     configuration.setDiskCacheSpeculativeValidationEnabled(true);
327
328     WebKitWebContext* webContext = WEBKIT_WEB_CONTEXT(object);
329     WebKitWebContextPrivate* priv = webContext->priv;
330     if (priv->websiteDataManager && !webkit_website_data_manager_is_ephemeral(priv->websiteDataManager.get())) {
331         configuration.setLocalStorageDirectory(WebCore::FileSystem::stringFromFileSystemRepresentation(webkit_website_data_manager_get_local_storage_directory(priv->websiteDataManager.get())));
332         configuration.setDiskCacheDirectory(WebCore::FileSystem::pathByAppendingComponent(WebCore::FileSystem::stringFromFileSystemRepresentation(webkit_website_data_manager_get_disk_cache_directory(priv->websiteDataManager.get())), networkCacheSubdirectory));
333         configuration.setApplicationCacheDirectory(WebCore::FileSystem::stringFromFileSystemRepresentation(webkit_website_data_manager_get_offline_application_cache_directory(priv->websiteDataManager.get())));
334         configuration.setIndexedDBDatabaseDirectory(WebCore::FileSystem::stringFromFileSystemRepresentation(webkit_website_data_manager_get_indexeddb_directory(priv->websiteDataManager.get())));
335         configuration.setWebSQLDatabaseDirectory(WebCore::FileSystem::stringFromFileSystemRepresentation(webkit_website_data_manager_get_websql_directory(priv->websiteDataManager.get())));
336         configuration.setResourceLoadStatisticsDirectory(WebCore::FileSystem::stringFromFileSystemRepresentation(webkit_website_data_manager_get_resource_load_statistics_directory(priv->websiteDataManager.get())));
337     } else if (!priv->localStorageDirectory.isNull())
338         configuration.setLocalStorageDirectory(WebCore::FileSystem::stringFromFileSystemRepresentation(priv->localStorageDirectory.data()));
339
340     priv->processPool = WebProcessPool::create(configuration);
341
342     if (!priv->websiteDataManager)
343         priv->websiteDataManager = adoptGRef(webkitWebsiteDataManagerCreate(websiteDataStoreConfigurationForWebProcessPoolConfiguration(configuration)));
344     priv->processPool->setPrimaryDataStore(webkitWebsiteDataManagerGetDataStore(priv->websiteDataManager.get()));
345
346     webkitWebsiteDataManagerAddProcessPool(priv->websiteDataManager.get(), *priv->processPool);
347
348     priv->tlsErrorsPolicy = WEBKIT_TLS_ERRORS_POLICY_FAIL;
349     priv->processPool->setIgnoreTLSErrors(false);
350
351 #if ENABLE(MEMORY_SAMPLER)
352     if (getenv("WEBKIT_SAMPLE_MEMORY"))
353         priv->processPool->startMemorySampler(0);
354 #endif
355
356     attachInjectedBundleClientToContext(webContext);
357     attachDownloadClientToContext(webContext);
358     attachCustomProtocolManagerClientToContext(webContext);
359
360 #if ENABLE(GEOLOCATION)
361     priv->geolocationProvider = std::make_unique<WebKitGeolocationProvider>(priv->processPool->supplement<WebGeolocationManagerProxy>());
362 #endif
363     priv->notificationProvider = std::make_unique<WebKitNotificationProvider>(priv->processPool->supplement<WebNotificationManagerProxy>(), webContext);
364 #if PLATFORM(GTK) && ENABLE(REMOTE_INSPECTOR)
365     priv->remoteInspectorProtocolHandler = std::make_unique<RemoteInspectorProtocolHandler>(webContext);
366 #endif
367 }
368
369 static void webkitWebContextDispose(GObject* object)
370 {
371     WebKitWebContextPrivate* priv = WEBKIT_WEB_CONTEXT(object)->priv;
372     if (!priv->clientsDetached) {
373         priv->clientsDetached = true;
374         priv->processPool->setInjectedBundleClient(nullptr);
375         priv->processPool->setDownloadClient(nullptr);
376         priv->processPool->setLegacyCustomProtocolManagerClient(nullptr);
377     }
378
379     if (priv->websiteDataManager) {
380         webkitWebsiteDataManagerRemoveProcessPool(priv->websiteDataManager.get(), *priv->processPool);
381         priv->websiteDataManager = nullptr;
382     }
383
384     G_OBJECT_CLASS(webkit_web_context_parent_class)->dispose(object);
385 }
386
387 static void webkit_web_context_class_init(WebKitWebContextClass* webContextClass)
388 {
389     GObjectClass* gObjectClass = G_OBJECT_CLASS(webContextClass);
390
391     bindtextdomain(GETTEXT_PACKAGE, LOCALEDIR);
392     bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
393
394     gObjectClass->get_property = webkitWebContextGetProperty;
395     gObjectClass->set_property = webkitWebContextSetProperty;
396     gObjectClass->constructed = webkitWebContextConstructed;
397     gObjectClass->dispose = webkitWebContextDispose;
398
399     /**
400      * WebKitWebContext:local-storage-directory:
401      *
402      * The directory where local storage data will be saved.
403      *
404      * Since: 2.8
405      *
406      * Deprecated: 2.10. Use #WebKitWebsiteDataManager:local-storage-directory instead.
407      */
408     g_object_class_install_property(
409         gObjectClass,
410         PROP_LOCAL_STORAGE_DIRECTORY,
411         g_param_spec_string(
412             "local-storage-directory",
413             _("Local Storage Directory"),
414             _("The directory where local storage data will be saved"),
415             nullptr,
416             static_cast<GParamFlags>(WEBKIT_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)));
417
418     /**
419      * WebKitWebContext:website-data-manager:
420      *
421      * The #WebKitWebsiteDataManager associated with this context.
422      *
423      * Since: 2.10
424      */
425     g_object_class_install_property(
426         gObjectClass,
427         PROP_WEBSITE_DATA_MANAGER,
428         g_param_spec_object(
429             "website-data-manager",
430             _("Website Data Manager"),
431             _("The WebKitWebsiteDataManager associated with this context"),
432             WEBKIT_TYPE_WEBSITE_DATA_MANAGER,
433             static_cast<GParamFlags>(WEBKIT_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)));
434
435     /**
436      * WebKitWebContext::download-started:
437      * @context: the #WebKitWebContext
438      * @download: the #WebKitDownload associated with this event
439      *
440      * This signal is emitted when a new download request is made.
441      */
442     signals[DOWNLOAD_STARTED] =
443         g_signal_new("download-started",
444             G_TYPE_FROM_CLASS(gObjectClass),
445             G_SIGNAL_RUN_LAST,
446             G_STRUCT_OFFSET(WebKitWebContextClass, download_started),
447             nullptr, nullptr,
448             g_cclosure_marshal_VOID__OBJECT,
449             G_TYPE_NONE, 1,
450             WEBKIT_TYPE_DOWNLOAD);
451
452     /**
453      * WebKitWebContext::initialize-web-extensions:
454      * @context: the #WebKitWebContext
455      *
456      * This signal is emitted when a new web process is about to be
457      * launched. It signals the most appropriate moment to use
458      * webkit_web_context_set_web_extensions_initialization_user_data()
459      * and webkit_web_context_set_web_extensions_directory().
460      *
461      * Since: 2.4
462      */
463     signals[INITIALIZE_WEB_EXTENSIONS] =
464         g_signal_new("initialize-web-extensions",
465             G_TYPE_FROM_CLASS(gObjectClass),
466             G_SIGNAL_RUN_LAST,
467             G_STRUCT_OFFSET(WebKitWebContextClass, initialize_web_extensions),
468             nullptr, nullptr,
469             g_cclosure_marshal_VOID__VOID,
470             G_TYPE_NONE, 0);
471
472     /**
473      * WebKitWebContext::initialize-notification-permissions:
474      * @context: the #WebKitWebContext
475      *
476      * This signal is emitted when a #WebKitWebContext needs to set
477      * initial notification permissions for a web process. It is emitted
478      * when a new web process is about to be launched, and signals the
479      * most appropriate moment to use
480      * webkit_web_context_initialize_notification_permissions(). If no
481      * notification permissions have changed since the last time this
482      * signal was emitted, then there is no need to call
483      * webkit_web_context_initialize_notification_permissions() again.
484      *
485      * Since: 2.16
486      */
487     signals[INITIALIZE_NOTIFICATION_PERMISSIONS] =
488         g_signal_new("initialize-notification-permissions",
489             G_TYPE_FROM_CLASS(gObjectClass),
490             G_SIGNAL_RUN_LAST,
491             G_STRUCT_OFFSET(WebKitWebContextClass, initialize_notification_permissions),
492             nullptr, nullptr,
493             g_cclosure_marshal_VOID__VOID,
494             G_TYPE_NONE, 0);
495
496     /**
497      * WebKitWebContext::automation-started:
498      * @context: the #WebKitWebContext
499      * @session: the #WebKitAutomationSession associated with this event
500      *
501      * This signal is emitted when a new automation request is made.
502      * Note that it will never be emitted if automation is not enabled in @context,
503      * see webkit_web_context_set_automation_allowed() for more details.
504      *
505      * Since: 2.18
506      */
507     signals[AUTOMATION_STARTED] =
508         g_signal_new("automation-started",
509             G_TYPE_FROM_CLASS(gObjectClass),
510             G_SIGNAL_RUN_LAST,
511             G_STRUCT_OFFSET(WebKitWebContextClass, automation_started),
512             nullptr, nullptr,
513             g_cclosure_marshal_VOID__OBJECT,
514             G_TYPE_NONE, 1,
515             WEBKIT_TYPE_AUTOMATION_SESSION);
516 }
517
518 static gpointer createDefaultWebContext(gpointer)
519 {
520     static GRefPtr<WebKitWebContext> webContext = adoptGRef(WEBKIT_WEB_CONTEXT(g_object_new(WEBKIT_TYPE_WEB_CONTEXT, nullptr)));
521     return webContext.get();
522 }
523
524 /**
525  * webkit_web_context_get_default:
526  *
527  * Gets the default web context
528  *
529  * Returns: (transfer none): a #WebKitWebContext
530  */
531 WebKitWebContext* webkit_web_context_get_default(void)
532 {
533     static GOnce onceInit = G_ONCE_INIT;
534     return WEBKIT_WEB_CONTEXT(g_once(&onceInit, createDefaultWebContext, 0));
535 }
536
537 /**
538  * webkit_web_context_new:
539  *
540  * Create a new #WebKitWebContext
541  *
542  * Returns: (transfer full): a newly created #WebKitWebContext
543  *
544  * Since: 2.8
545  */
546 WebKitWebContext* webkit_web_context_new(void)
547 {
548     return WEBKIT_WEB_CONTEXT(g_object_new(WEBKIT_TYPE_WEB_CONTEXT, nullptr));
549 }
550
551 /**
552  * webkit_web_context_new_ephemeral:
553  *
554  * Create a new ephemeral #WebKitWebContext. An ephemeral #WebKitWebContext is a context
555  * created with an ephemeral #WebKitWebsiteDataManager. This is just a convenient method
556  * to create ephemeral contexts without having to create your own #WebKitWebsiteDataManager.
557  * All #WebKitWebView<!-- -->s associated with this context will also be ephemeral. Websites will
558  * not store any data in the client storage.
559  * This is normally used to implement private instances.
560  *
561  * Returns: (transfer full): a new ephemeral #WebKitWebContext.
562  *
563  * Since: 2.16
564  */
565 WebKitWebContext* webkit_web_context_new_ephemeral()
566 {
567     GRefPtr<WebKitWebsiteDataManager> manager = adoptGRef(webkit_website_data_manager_new_ephemeral());
568     return WEBKIT_WEB_CONTEXT(g_object_new(WEBKIT_TYPE_WEB_CONTEXT, "website-data-manager", manager.get(), nullptr));
569 }
570
571 /**
572  * webkit_web_context_new_with_website_data_manager:
573  * @manager: a #WebKitWebsiteDataManager
574  *
575  * Create a new #WebKitWebContext with a #WebKitWebsiteDataManager.
576  *
577  * Returns: (transfer full): a newly created #WebKitWebContext
578  *
579  * Since: 2.10
580  */
581 WebKitWebContext* webkit_web_context_new_with_website_data_manager(WebKitWebsiteDataManager* manager)
582 {
583     g_return_val_if_fail(WEBKIT_IS_WEBSITE_DATA_MANAGER(manager), nullptr);
584
585     return WEBKIT_WEB_CONTEXT(g_object_new(WEBKIT_TYPE_WEB_CONTEXT, "website-data-manager", manager, nullptr));
586 }
587
588 /**
589  * webkit_web_context_get_website_data_manager:
590  * @context: the #WebKitWebContext
591  *
592  * Get the #WebKitWebsiteDataManager of @context.
593  *
594  * Returns: (transfer none): a #WebKitWebsiteDataManager
595  *
596  * Since: 2.10
597  */
598 WebKitWebsiteDataManager* webkit_web_context_get_website_data_manager(WebKitWebContext* context)
599 {
600     g_return_val_if_fail(WEBKIT_IS_WEB_CONTEXT(context), nullptr);
601
602     return context->priv->websiteDataManager.get();
603 }
604
605 /**
606  * webkit_web_context_is_ephemeral:
607  * @context: the #WebKitWebContext
608  *
609  * Get whether a #WebKitWebContext is ephemeral.
610  *
611  * Returns: %TRUE if @context is ephemeral or %FALSE otherwise.
612  *
613  * Since: 2.16
614  */
615 gboolean webkit_web_context_is_ephemeral(WebKitWebContext* context)
616 {
617     g_return_val_if_fail(WEBKIT_IS_WEB_CONTEXT(context), FALSE);
618
619     return webkit_website_data_manager_is_ephemeral(context->priv->websiteDataManager.get());
620 }
621
622 /**
623  * webkit_web_context_is_automation_allowed:
624  * @context: the #WebKitWebContext
625  *
626  * Get whether automation is allowed in @context.
627  * See also webkit_web_context_set_automation_allowed().
628  *
629  * Returns: %TRUE if automation is allowed or %FALSE otherwise.
630  *
631  * Since: 2.18
632  */
633 gboolean webkit_web_context_is_automation_allowed(WebKitWebContext* context)
634 {
635     g_return_val_if_fail(WEBKIT_IS_WEB_CONTEXT(context), FALSE);
636
637 #if ENABLE(REMOTE_INSPECTOR)
638     return !!context->priv->automationClient;
639 #else
640     return FALSE;
641 #endif
642 }
643
644 /**
645  * webkit_web_context_set_automation_allowed:
646  * @context: the #WebKitWebContext
647  * @allowed: value to set
648  *
649  * Set whether automation is allowed in @context. When automation is enabled the browser could
650  * be controlled by another process by requesting an automation session. When a new automation
651  * session is requested the signal #WebKitWebContext::automation-started is emitted.
652  * Automation is disabled by default, so you need to explicitly call this method passing %TRUE
653  * to enable it.
654  *
655  * Note that only one #WebKitWebContext can have automation enabled, so this will do nothing
656  * if there's another #WebKitWebContext with automation already enabled.
657  *
658  * Since: 2.18
659  */
660 void webkit_web_context_set_automation_allowed(WebKitWebContext* context, gboolean allowed)
661 {
662     g_return_if_fail(WEBKIT_IS_WEB_CONTEXT(context));
663
664     if (webkit_web_context_is_automation_allowed(context) == allowed)
665         return;
666 #if ENABLE(REMOTE_INSPECTOR)
667     if (allowed) {
668         if (Inspector::RemoteInspector::singleton().client()) {
669             g_warning("Not enabling automation on WebKitWebContext because there's another context with automation enabled, only one is allowed");
670             return;
671         }
672         context->priv->automationClient = std::make_unique<WebKitAutomationClient>(context);
673     } else
674         context->priv->automationClient = nullptr;
675 #endif
676 }
677
678 /**
679  * webkit_web_context_set_cache_model:
680  * @context: the #WebKitWebContext
681  * @cache_model: a #WebKitCacheModel
682  *
683  * Specifies a usage model for WebViews, which WebKit will use to
684  * determine its caching behavior. All web views follow the cache
685  * model. This cache model determines the RAM and disk space to use
686  * for caching previously viewed content .
687  *
688  * Research indicates that users tend to browse within clusters of
689  * documents that hold resources in common, and to revisit previously
690  * visited documents. WebKit and the frameworks below it include
691  * built-in caches that take advantage of these patterns,
692  * substantially improving document load speed in browsing
693  * situations. The WebKit cache model controls the behaviors of all of
694  * these caches, including various WebCore caches.
695  *
696  * Browsers can improve document load speed substantially by
697  * specifying %WEBKIT_CACHE_MODEL_WEB_BROWSER. Applications without a
698  * browsing interface can reduce memory usage substantially by
699  * specifying %WEBKIT_CACHE_MODEL_DOCUMENT_VIEWER. The default value is
700  * %WEBKIT_CACHE_MODEL_WEB_BROWSER.
701  */
702 void webkit_web_context_set_cache_model(WebKitWebContext* context, WebKitCacheModel model)
703 {
704     CacheModel cacheModel;
705
706     g_return_if_fail(WEBKIT_IS_WEB_CONTEXT(context));
707
708     switch (model) {
709     case WEBKIT_CACHE_MODEL_DOCUMENT_VIEWER:
710         cacheModel = CacheModelDocumentViewer;
711         break;
712     case WEBKIT_CACHE_MODEL_WEB_BROWSER:
713         cacheModel = CacheModelPrimaryWebBrowser;
714         break;
715     case WEBKIT_CACHE_MODEL_DOCUMENT_BROWSER:
716         cacheModel = CacheModelDocumentBrowser;
717         break;
718     default:
719         g_assert_not_reached();
720     }
721
722     if (cacheModel != context->priv->processPool->cacheModel())
723         context->priv->processPool->setCacheModel(cacheModel);
724 }
725
726 /**
727  * webkit_web_context_get_cache_model:
728  * @context: the #WebKitWebContext
729  *
730  * Returns the current cache model. For more information about this
731  * value check the documentation of the function
732  * webkit_web_context_set_cache_model().
733  *
734  * Returns: the current #WebKitCacheModel
735  */
736 WebKitCacheModel webkit_web_context_get_cache_model(WebKitWebContext* context)
737 {
738     g_return_val_if_fail(WEBKIT_IS_WEB_CONTEXT(context), WEBKIT_CACHE_MODEL_WEB_BROWSER);
739
740     switch (context->priv->processPool->cacheModel()) {
741     case CacheModelDocumentViewer:
742         return WEBKIT_CACHE_MODEL_DOCUMENT_VIEWER;
743     case CacheModelPrimaryWebBrowser:
744         return WEBKIT_CACHE_MODEL_WEB_BROWSER;
745     case CacheModelDocumentBrowser:
746         return WEBKIT_CACHE_MODEL_DOCUMENT_BROWSER;
747     default:
748         g_assert_not_reached();
749     }
750
751     return WEBKIT_CACHE_MODEL_WEB_BROWSER;
752 }
753
754 /**
755  * webkit_web_context_clear_cache:
756  * @context: a #WebKitWebContext
757  *
758  * Clears all resources currently cached.
759  * See also webkit_web_context_set_cache_model().
760  */
761 void webkit_web_context_clear_cache(WebKitWebContext* context)
762 {
763     g_return_if_fail(WEBKIT_IS_WEB_CONTEXT(context));
764
765     OptionSet<WebsiteDataType> websiteDataTypes;
766     websiteDataTypes |= WebsiteDataType::MemoryCache;
767     websiteDataTypes |= WebsiteDataType::DiskCache;
768     auto& websiteDataStore = webkitWebsiteDataManagerGetDataStore(context->priv->websiteDataManager.get()).websiteDataStore();
769     websiteDataStore.removeData(websiteDataTypes, std::chrono::system_clock::time_point::min(), [] { });
770 }
771
772 /**
773  * webkit_web_context_set_network_proxy_settings:
774  * @context: a #WebKitWebContext
775  * @proxy_mode: a #WebKitNetworkProxyMode
776  * @proxy_settings: (allow-none): a #WebKitNetworkProxySettings, or %NULL
777  *
778  * Set the network proxy settings to be used by connections started in @context.
779  * By default %WEBKIT_NETWORK_PROXY_MODE_DEFAULT is used, which means that the
780  * system settings will be used (g_proxy_resolver_get_default()).
781  * If you want to override the system default settings, you can either use
782  * %WEBKIT_NETWORK_PROXY_MODE_NO_PROXY to make sure no proxies are used at all,
783  * or %WEBKIT_NETWORK_PROXY_MODE_CUSTOM to provide your own proxy settings.
784  * When @proxy_mode is %WEBKIT_NETWORK_PROXY_MODE_CUSTOM @proxy_settings must be
785  * a valid #WebKitNetworkProxySettings; otherwise, @proxy_settings must be %NULL.
786  *
787  * Since: 2.16
788  */
789 void webkit_web_context_set_network_proxy_settings(WebKitWebContext* context, WebKitNetworkProxyMode proxyMode, WebKitNetworkProxySettings* proxySettings)
790 {
791     g_return_if_fail(WEBKIT_IS_WEB_CONTEXT(context));
792     g_return_if_fail((proxyMode != WEBKIT_NETWORK_PROXY_MODE_CUSTOM && !proxySettings) || (proxyMode == WEBKIT_NETWORK_PROXY_MODE_CUSTOM && proxySettings));
793
794     WebKitWebContextPrivate* priv = context->priv;
795     switch (proxyMode) {
796     case WEBKIT_NETWORK_PROXY_MODE_DEFAULT:
797         priv->processPool->setNetworkProxySettings({ });
798         break;
799     case WEBKIT_NETWORK_PROXY_MODE_NO_PROXY:
800         priv->processPool->setNetworkProxySettings(WebCore::SoupNetworkProxySettings(WebCore::SoupNetworkProxySettings::Mode::NoProxy));
801         break;
802     case WEBKIT_NETWORK_PROXY_MODE_CUSTOM:
803         const auto& settings = webkitNetworkProxySettingsGetNetworkProxySettings(proxySettings);
804         if (settings.isEmpty()) {
805             g_warning("Invalid attempt to set custom network proxy settings with an empty WebKitNetworkProxySettings. Use "
806                 "WEBKIT_NETWORK_PROXY_MODE_NO_PROXY to not use any proxy or WEBKIT_NETWORK_PROXY_MODE_DEFAULT to use the default system settings");
807         } else
808             priv->processPool->setNetworkProxySettings(settings);
809         break;
810     }
811 }
812
813 typedef HashMap<DownloadProxy*, GRefPtr<WebKitDownload> > DownloadsMap;
814
815 static DownloadsMap& downloadsMap()
816 {
817     static NeverDestroyed<DownloadsMap> downloads;
818     return downloads;
819 }
820
821 /**
822  * webkit_web_context_download_uri:
823  * @context: a #WebKitWebContext
824  * @uri: the URI to download
825  *
826  * Requests downloading of the specified URI string. The download operation
827  * will not be associated to any #WebKitWebView, if you are interested in
828  * starting a download from a particular #WebKitWebView use
829  * webkit_web_view_download_uri() instead.
830  *
831  * Returns: (transfer full): a new #WebKitDownload representing
832  *    the download operation.
833  */
834 WebKitDownload* webkit_web_context_download_uri(WebKitWebContext* context, const gchar* uri)
835 {
836     g_return_val_if_fail(WEBKIT_IS_WEB_CONTEXT(context), nullptr);
837     g_return_val_if_fail(uri, nullptr);
838
839     GRefPtr<WebKitDownload> download = webkitWebContextStartDownload(context, uri, nullptr);
840     return download.leakRef();
841 }
842
843 /**
844  * webkit_web_context_get_cookie_manager:
845  * @context: a #WebKitWebContext
846  *
847  * Get the #WebKitCookieManager of the @context's #WebKitWebsiteDataManager.
848  *
849  * Returns: (transfer none): the #WebKitCookieManager of @context.
850  */
851 WebKitCookieManager* webkit_web_context_get_cookie_manager(WebKitWebContext* context)
852 {
853     g_return_val_if_fail(WEBKIT_IS_WEB_CONTEXT(context), nullptr);
854
855     return webkit_website_data_manager_get_cookie_manager(context->priv->websiteDataManager.get());
856 }
857
858 static void ensureFaviconDatabase(WebKitWebContext* context)
859 {
860     WebKitWebContextPrivate* priv = context->priv;
861     if (priv->faviconDatabase)
862         return;
863
864     priv->faviconDatabase = adoptGRef(webkitFaviconDatabaseCreate());
865 }
866
867 static void webkitWebContextEnableIconDatabasePrivateBrowsingIfNeeded(WebKitWebContext* context, WebKitWebView* webView)
868 {
869     if (webkit_web_context_is_ephemeral(context))
870         return;
871     if (!webkit_web_view_is_ephemeral(webView))
872         return;
873
874     if (!context->priv->ephemeralPageCount && context->priv->faviconDatabase)
875         webkitFaviconDatabaseSetPrivateBrowsingEnabled(context->priv->faviconDatabase.get(), true);
876     context->priv->ephemeralPageCount++;
877 }
878
879 static void webkitWebContextDisableIconDatabasePrivateBrowsingIfNeeded(WebKitWebContext* context, WebKitWebView* webView)
880 {
881     if (webkit_web_context_is_ephemeral(context))
882         return;
883     if (!webkit_web_view_is_ephemeral(webView))
884         return;
885
886     ASSERT(context->priv->ephemeralPageCount);
887     context->priv->ephemeralPageCount--;
888     if (!context->priv->ephemeralPageCount && context->priv->faviconDatabase)
889         webkitFaviconDatabaseSetPrivateBrowsingEnabled(context->priv->faviconDatabase.get(), false);
890 }
891
892 /**
893  * webkit_web_context_set_favicon_database_directory:
894  * @context: a #WebKitWebContext
895  * @path: (allow-none): an absolute path to the icon database
896  * directory or %NULL to use the defaults
897  *
898  * Set the directory path to be used to store the favicons database
899  * for @context on disk. Passing %NULL as @path means using the
900  * default directory for the platform (see g_get_user_cache_dir()).
901  *
902  * Calling this method also means enabling the favicons database for
903  * its use from the applications, so that's why it's expected to be
904  * called only once. Further calls for the same instance of
905  * #WebKitWebContext won't cause any effect.
906  */
907 void webkit_web_context_set_favicon_database_directory(WebKitWebContext* context, const gchar* path)
908 {
909     g_return_if_fail(WEBKIT_IS_WEB_CONTEXT(context));
910
911     WebKitWebContextPrivate* priv = context->priv;
912     ensureFaviconDatabase(context);
913
914     String directoryPath = WebCore::FileSystem::stringFromFileSystemRepresentation(path);
915     // Use default if nullptr is passed as parameter.
916     if (directoryPath.isEmpty()) {
917 #if PLATFORM(GTK)
918         const char* portDirectory = "webkitgtk";
919 #elif PLATFORM(WPE)
920         const char* portDirectory = "wpe";
921 #endif
922         GUniquePtr<gchar> databaseDirectory(g_build_filename(g_get_user_cache_dir(), portDirectory, "icondatabase", nullptr));
923         directoryPath = WebCore::FileSystem::stringFromFileSystemRepresentation(databaseDirectory.get());
924     }
925     priv->faviconDatabaseDirectory = directoryPath.utf8();
926
927     // Build the full path to the icon database file on disk.
928     GUniquePtr<gchar> faviconDatabasePath(g_build_filename(priv->faviconDatabaseDirectory.data(),
929         "WebpageIcons.db", nullptr));
930
931     // Setting the path will cause the icon database to be opened.
932     webkitFaviconDatabaseOpen(priv->faviconDatabase.get(), WebCore::FileSystem::stringFromFileSystemRepresentation(faviconDatabasePath.get()));
933
934     if (webkit_web_context_is_ephemeral(context))
935         webkitFaviconDatabaseSetPrivateBrowsingEnabled(priv->faviconDatabase.get(), true);
936 }
937
938 /**
939  * webkit_web_context_get_favicon_database_directory:
940  * @context: a #WebKitWebContext
941  *
942  * Get the directory path being used to store the favicons database
943  * for @context, or %NULL if
944  * webkit_web_context_set_favicon_database_directory() hasn't been
945  * called yet.
946  *
947  * This function will always return the same path after having called
948  * webkit_web_context_set_favicon_database_directory() for the first
949  * time.
950  *
951  * Returns: (transfer none): the path of the directory of the favicons
952  * database associated with @context, or %NULL.
953  */
954 const gchar* webkit_web_context_get_favicon_database_directory(WebKitWebContext *context)
955 {
956     g_return_val_if_fail(WEBKIT_IS_WEB_CONTEXT(context), 0);
957
958     WebKitWebContextPrivate* priv = context->priv;
959     if (priv->faviconDatabaseDirectory.isNull())
960         return 0;
961
962     return priv->faviconDatabaseDirectory.data();
963 }
964
965 /**
966  * webkit_web_context_get_favicon_database:
967  * @context: a #WebKitWebContext
968  *
969  * Get the #WebKitFaviconDatabase associated with @context.
970  *
971  * To initialize the database you need to call
972  * webkit_web_context_set_favicon_database_directory().
973  *
974  * Returns: (transfer none): the #WebKitFaviconDatabase of @context.
975  */
976 WebKitFaviconDatabase* webkit_web_context_get_favicon_database(WebKitWebContext* context)
977 {
978     g_return_val_if_fail(WEBKIT_IS_WEB_CONTEXT(context), 0);
979
980     ensureFaviconDatabase(context);
981     return context->priv->faviconDatabase.get();
982 }
983
984 /**
985  * webkit_web_context_get_security_manager:
986  * @context: a #WebKitWebContext
987  *
988  * Get the #WebKitSecurityManager of @context.
989  *
990  * Returns: (transfer none): the #WebKitSecurityManager of @context.
991  */
992 WebKitSecurityManager* webkit_web_context_get_security_manager(WebKitWebContext* context)
993 {
994     g_return_val_if_fail(WEBKIT_IS_WEB_CONTEXT(context), 0);
995
996     WebKitWebContextPrivate* priv = context->priv;
997     if (!priv->securityManager)
998         priv->securityManager = adoptGRef(webkitSecurityManagerCreate(context));
999
1000     return priv->securityManager.get();
1001 }
1002
1003 /**
1004  * webkit_web_context_set_additional_plugins_directory:
1005  * @context: a #WebKitWebContext
1006  * @directory: the directory to add
1007  *
1008  * Set an additional directory where WebKit will look for plugins.
1009  */
1010 void webkit_web_context_set_additional_plugins_directory(WebKitWebContext* context, const char* directory)
1011 {
1012     g_return_if_fail(WEBKIT_IS_WEB_CONTEXT(context));
1013     g_return_if_fail(directory);
1014
1015 #if ENABLE(NETSCAPE_PLUGIN_API)
1016     context->priv->processPool->setAdditionalPluginsDirectory(WebCore::FileSystem::stringFromFileSystemRepresentation(directory));
1017 #endif
1018 }
1019
1020 static void destroyPluginList(GList* plugins)
1021 {
1022     g_list_free_full(plugins, g_object_unref);
1023 }
1024
1025 static void webkitWebContextGetPluginThread(GTask* task, gpointer object, gpointer /* taskData */, GCancellable*)
1026 {
1027     GList* returnValue = 0;
1028 #if ENABLE(NETSCAPE_PLUGIN_API)
1029     Vector<PluginModuleInfo> plugins = WEBKIT_WEB_CONTEXT(object)->priv->processPool->pluginInfoStore().plugins();
1030     for (size_t i = 0; i < plugins.size(); ++i)
1031         returnValue = g_list_prepend(returnValue, webkitPluginCreate(plugins[i]));
1032 #endif
1033     g_task_return_pointer(task, returnValue, reinterpret_cast<GDestroyNotify>(destroyPluginList));
1034 }
1035
1036 /**
1037  * webkit_web_context_get_plugins:
1038  * @context: a #WebKitWebContext
1039  * @cancellable: (allow-none): a #GCancellable or %NULL to ignore
1040  * @callback: (scope async): a #GAsyncReadyCallback to call when the request is satisfied
1041  * @user_data: (closure): the data to pass to callback function
1042  *
1043  * Asynchronously get the list of installed plugins.
1044  *
1045  * When the operation is finished, @callback will be called. You can then call
1046  * webkit_web_context_get_plugins_finish() to get the result of the operation.
1047  */
1048 void webkit_web_context_get_plugins(WebKitWebContext* context, GCancellable* cancellable, GAsyncReadyCallback callback, gpointer userData)
1049 {
1050     g_return_if_fail(WEBKIT_IS_WEB_CONTEXT(context));
1051
1052     GRefPtr<GTask> task = adoptGRef(g_task_new(context, cancellable, callback, userData));
1053     g_task_run_in_thread(task.get(), webkitWebContextGetPluginThread);
1054 }
1055
1056 /**
1057  * webkit_web_context_get_plugins_finish:
1058  * @context: a #WebKitWebContext
1059  * @result: a #GAsyncResult
1060  * @error: return location for error or %NULL to ignore
1061  *
1062  * Finish an asynchronous operation started with webkit_web_context_get_plugins.
1063  *
1064  * Returns: (element-type WebKitPlugin) (transfer full): a #GList of #WebKitPlugin. You must free the #GList with
1065  *    g_list_free() and unref the #WebKitPlugin<!-- -->s with g_object_unref() when you're done with them.
1066  */
1067 GList* webkit_web_context_get_plugins_finish(WebKitWebContext* context, GAsyncResult* result, GError** error)
1068 {
1069     g_return_val_if_fail(WEBKIT_IS_WEB_CONTEXT(context), 0);
1070     g_return_val_if_fail(g_task_is_valid(result, context), 0);
1071
1072     return static_cast<GList*>(g_task_propagate_pointer(G_TASK(result), error));
1073 }
1074
1075 /**
1076  * webkit_web_context_register_uri_scheme:
1077  * @context: a #WebKitWebContext
1078  * @scheme: the network scheme to register
1079  * @callback: (scope async): a #WebKitURISchemeRequestCallback
1080  * @user_data: data to pass to callback function
1081  * @user_data_destroy_func: destroy notify for @user_data
1082  *
1083  * Register @scheme in @context, so that when an URI request with @scheme is made in the
1084  * #WebKitWebContext, the #WebKitURISchemeRequestCallback registered will be called with a
1085  * #WebKitURISchemeRequest.
1086  * It is possible to handle URI scheme requests asynchronously, by calling g_object_ref() on the
1087  * #WebKitURISchemeRequest and calling webkit_uri_scheme_request_finish() later
1088  * when the data of the request is available or
1089  * webkit_uri_scheme_request_finish_error() in case of error.
1090  *
1091  * <informalexample><programlisting>
1092  * static void
1093  * about_uri_scheme_request_cb (WebKitURISchemeRequest *request,
1094  *                              gpointer                user_data)
1095  * {
1096  *     GInputStream *stream;
1097  *     gsize         stream_length;
1098  *     const gchar  *path;
1099  *
1100  *     path = webkit_uri_scheme_request_get_path (request);
1101  *     if (!g_strcmp0 (path, "plugins")) {
1102  *         /<!-- -->* Create a GInputStream with the contents of plugins about page, and set its length to stream_length *<!-- -->/
1103  *     } else if (!g_strcmp0 (path, "memory")) {
1104  *         /<!-- -->* Create a GInputStream with the contents of memory about page, and set its length to stream_length *<!-- -->/
1105  *     } else if (!g_strcmp0 (path, "applications")) {
1106  *         /<!-- -->* Create a GInputStream with the contents of applications about page, and set its length to stream_length *<!-- -->/
1107  *     } else if (!g_strcmp0 (path, "example")) {
1108  *         gchar *contents;
1109  *
1110  *         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;");
1111  *         stream_length = strlen (contents);
1112  *         stream = g_memory_input_stream_new_from_data (contents, stream_length, g_free);
1113  *     } else {
1114  *         GError *error;
1115  *
1116  *         error = g_error_new (ABOUT_HANDLER_ERROR, ABOUT_HANDLER_ERROR_INVALID, "Invalid about:%s page.", path);
1117  *         webkit_uri_scheme_request_finish_error (request, error);
1118  *         g_error_free (error);
1119  *         return;
1120  *     }
1121  *     webkit_uri_scheme_request_finish (request, stream, stream_length, "text/html");
1122  *     g_object_unref (stream);
1123  * }
1124  * </programlisting></informalexample>
1125  */
1126 void webkit_web_context_register_uri_scheme(WebKitWebContext* context, const char* scheme, WebKitURISchemeRequestCallback callback, gpointer userData, GDestroyNotify destroyNotify)
1127 {
1128     g_return_if_fail(WEBKIT_IS_WEB_CONTEXT(context));
1129     g_return_if_fail(scheme);
1130     g_return_if_fail(callback);
1131
1132     RefPtr<WebKitURISchemeHandler> handler = adoptRef(new WebKitURISchemeHandler(callback, userData, destroyNotify));
1133     auto addResult = context->priv->uriSchemeHandlers.set(String::fromUTF8(scheme), handler.get());
1134     if (addResult.isNewEntry)
1135         context->priv->processPool->registerSchemeForCustomProtocol(String::fromUTF8(scheme));
1136 }
1137
1138 /**
1139  * webkit_web_context_get_spell_checking_enabled:
1140  * @context: a #WebKitWebContext
1141  *
1142  * Get whether spell checking feature is currently enabled.
1143  *
1144  * Returns: %TRUE If spell checking is enabled, or %FALSE otherwise.
1145  */
1146 gboolean webkit_web_context_get_spell_checking_enabled(WebKitWebContext* context)
1147 {
1148     g_return_val_if_fail(WEBKIT_IS_WEB_CONTEXT(context), FALSE);
1149
1150 #if ENABLE(SPELLCHECK)
1151     return TextChecker::state().isContinuousSpellCheckingEnabled;
1152 #else
1153     return false;
1154 #endif
1155 }
1156
1157 /**
1158  * webkit_web_context_set_spell_checking_enabled:
1159  * @context: a #WebKitWebContext
1160  * @enabled: Value to be set
1161  *
1162  * Enable or disable the spell checking feature.
1163  */
1164 void webkit_web_context_set_spell_checking_enabled(WebKitWebContext* context, gboolean enabled)
1165 {
1166     g_return_if_fail(WEBKIT_IS_WEB_CONTEXT(context));
1167
1168 #if ENABLE(SPELLCHECK)
1169     TextChecker::setContinuousSpellCheckingEnabled(enabled);
1170 #endif
1171 }
1172
1173 /**
1174  * webkit_web_context_get_spell_checking_languages:
1175  * @context: a #WebKitWebContext
1176  *
1177  * Get the the list of spell checking languages associated with
1178  * @context, or %NULL if no languages have been previously set.
1179  *
1180  * See webkit_web_context_set_spell_checking_languages() for more
1181  * details on the format of the languages in the list.
1182  *
1183  * Returns: (array zero-terminated=1) (element-type utf8) (transfer none): A %NULL-terminated
1184  *    array of languages if available, or %NULL otherwise.
1185  */
1186 const gchar* const* webkit_web_context_get_spell_checking_languages(WebKitWebContext* context)
1187 {
1188     g_return_val_if_fail(WEBKIT_IS_WEB_CONTEXT(context), nullptr);
1189
1190 #if ENABLE(SPELLCHECK)
1191     Vector<String> spellCheckingLanguages = TextChecker::loadedSpellCheckingLanguages();
1192     if (spellCheckingLanguages.isEmpty())
1193         return nullptr;
1194
1195     static GRefPtr<GPtrArray> languagesToReturn;
1196     languagesToReturn = adoptGRef(g_ptr_array_new_with_free_func(g_free));
1197     for (const auto& language : spellCheckingLanguages)
1198         g_ptr_array_add(languagesToReturn.get(), g_strdup(language.utf8().data()));
1199     g_ptr_array_add(languagesToReturn.get(), nullptr);
1200
1201     return reinterpret_cast<char**>(languagesToReturn->pdata);
1202 #else
1203     return 0;
1204 #endif
1205 }
1206
1207 /**
1208  * webkit_web_context_set_spell_checking_languages:
1209  * @context: a #WebKitWebContext
1210  * @languages: (array zero-terminated=1) (transfer none): a %NULL-terminated list of spell checking languages
1211  *
1212  * Set the list of spell checking languages to be used for spell
1213  * checking.
1214  *
1215  * The locale string typically is in the form lang_COUNTRY, where lang
1216  * is an ISO-639 language code, and COUNTRY is an ISO-3166 country code.
1217  * For instance, sv_FI for Swedish as written in Finland or pt_BR
1218  * for Portuguese as written in Brazil.
1219  *
1220  * You need to call this function with a valid list of languages at
1221  * least once in order to properly enable the spell checking feature
1222  * in WebKit.
1223  */
1224 void webkit_web_context_set_spell_checking_languages(WebKitWebContext* context, const gchar* const* languages)
1225 {
1226     g_return_if_fail(WEBKIT_IS_WEB_CONTEXT(context));
1227     g_return_if_fail(languages);
1228
1229 #if ENABLE(SPELLCHECK)
1230     Vector<String> spellCheckingLanguages;
1231     for (size_t i = 0; languages[i]; ++i)
1232         spellCheckingLanguages.append(String::fromUTF8(languages[i]));
1233     TextChecker::setSpellCheckingLanguages(spellCheckingLanguages);
1234 #endif
1235 }
1236
1237 /**
1238  * webkit_web_context_set_preferred_languages:
1239  * @context: a #WebKitWebContext
1240  * @languages: (allow-none) (array zero-terminated=1) (element-type utf8) (transfer none): a %NULL-terminated list of language identifiers
1241  *
1242  * Set the list of preferred languages, sorted from most desirable
1243  * to least desirable. The list will be used to build the "Accept-Language"
1244  * header that will be included in the network requests started by
1245  * the #WebKitWebContext.
1246  */
1247 void webkit_web_context_set_preferred_languages(WebKitWebContext* context, const gchar* const* languageList)
1248 {
1249     g_return_if_fail(WEBKIT_IS_WEB_CONTEXT(context));
1250
1251     if (!languageList || !g_strv_length(const_cast<char**>(languageList)))
1252         return;
1253
1254     Vector<String> languages;
1255     for (size_t i = 0; languageList[i]; ++i) {
1256         // Do not propagate the C locale to WebCore.
1257         if (!g_ascii_strcasecmp(languageList[i], "C") || !g_ascii_strcasecmp(languageList[i], "POSIX"))
1258             languages.append(ASCIILiteral("en-us"));
1259         else
1260             languages.append(String::fromUTF8(languageList[i]).convertToASCIILowercase().replace("_", "-"));
1261     }
1262     overrideUserPreferredLanguages(languages);
1263 }
1264
1265 /**
1266  * webkit_web_context_set_tls_errors_policy:
1267  * @context: a #WebKitWebContext
1268  * @policy: a #WebKitTLSErrorsPolicy
1269  *
1270  * Set the TLS errors policy of @context as @policy
1271  */
1272 void webkit_web_context_set_tls_errors_policy(WebKitWebContext* context, WebKitTLSErrorsPolicy policy)
1273 {
1274     g_return_if_fail(WEBKIT_IS_WEB_CONTEXT(context));
1275
1276     if (context->priv->tlsErrorsPolicy == policy)
1277         return;
1278
1279     context->priv->tlsErrorsPolicy = policy;
1280     bool ignoreTLSErrors = policy == WEBKIT_TLS_ERRORS_POLICY_IGNORE;
1281     if (context->priv->processPool->ignoreTLSErrors() != ignoreTLSErrors)
1282         context->priv->processPool->setIgnoreTLSErrors(ignoreTLSErrors);
1283 }
1284
1285 /**
1286  * webkit_web_context_get_tls_errors_policy:
1287  * @context: a #WebKitWebContext
1288  *
1289  * Get the TLS errors policy of @context
1290  *
1291  * Returns: a #WebKitTLSErrorsPolicy
1292  */
1293 WebKitTLSErrorsPolicy webkit_web_context_get_tls_errors_policy(WebKitWebContext* context)
1294 {
1295     g_return_val_if_fail(WEBKIT_IS_WEB_CONTEXT(context), WEBKIT_TLS_ERRORS_POLICY_IGNORE);
1296
1297     return context->priv->tlsErrorsPolicy;
1298 }
1299
1300 /**
1301  * webkit_web_context_set_web_extensions_directory:
1302  * @context: a #WebKitWebContext
1303  * @directory: the directory to add
1304  *
1305  * Set the directory where WebKit will look for Web Extensions.
1306  * This method must be called before loading anything in this context,
1307  * otherwise it will not have any effect. You can connect to
1308  * #WebKitWebContext::initialize-web-extensions to call this method
1309  * before anything is loaded.
1310  */
1311 void webkit_web_context_set_web_extensions_directory(WebKitWebContext* context, const char* directory)
1312 {
1313     g_return_if_fail(WEBKIT_IS_WEB_CONTEXT(context));
1314     g_return_if_fail(directory);
1315
1316     context->priv->webExtensionsDirectory = directory;
1317 }
1318
1319 /**
1320  * webkit_web_context_set_web_extensions_initialization_user_data:
1321  * @context: a #WebKitWebContext
1322  * @user_data: a #GVariant
1323  *
1324  * Set user data to be passed to Web Extensions on initialization.
1325  * The data will be passed to the
1326  * #WebKitWebExtensionInitializeWithUserDataFunction.
1327  * This method must be called before loading anything in this context,
1328  * otherwise it will not have any effect. You can connect to
1329  * #WebKitWebContext::initialize-web-extensions to call this method
1330  * before anything is loaded.
1331  *
1332  * Since: 2.4
1333  */
1334 void webkit_web_context_set_web_extensions_initialization_user_data(WebKitWebContext* context, GVariant* userData)
1335 {
1336     g_return_if_fail(WEBKIT_IS_WEB_CONTEXT(context));
1337     g_return_if_fail(userData);
1338
1339     context->priv->webExtensionsInitializationUserData = userData;
1340 }
1341
1342 /**
1343  * webkit_web_context_set_disk_cache_directory:
1344  * @context: a #WebKitWebContext
1345  * @directory: the directory to set
1346  *
1347  * Set the directory where disk cache files will be stored
1348  * This method must be called before loading anything in this context, otherwise
1349  * it will not have any effect.
1350  *
1351  * Note that this method overrides the directory set in the #WebKitWebsiteDataManager,
1352  * but it doesn't change the value returned by webkit_website_data_manager_get_disk_cache_directory()
1353  * since the #WebKitWebsiteDataManager is immutable.
1354  *
1355  * Deprecated: 2.10. Use webkit_web_context_new_with_website_data_manager() instead.
1356  */
1357 void webkit_web_context_set_disk_cache_directory(WebKitWebContext* context, const char* directory)
1358 {
1359     g_return_if_fail(WEBKIT_IS_WEB_CONTEXT(context));
1360     g_return_if_fail(directory);
1361
1362     context->priv->processPool->configuration().setDiskCacheDirectory(WebCore::FileSystem::pathByAppendingComponent(WebCore::FileSystem::stringFromFileSystemRepresentation(directory), networkCacheSubdirectory));
1363 }
1364
1365 /**
1366  * webkit_web_context_prefetch_dns:
1367  * @context: a #WebKitWebContext
1368  * @hostname: a hostname to be resolved
1369  *
1370  * Resolve the domain name of the given @hostname in advance, so that if a URI
1371  * of @hostname is requested the load will be performed more quickly.
1372  */
1373 void webkit_web_context_prefetch_dns(WebKitWebContext* context, const char* hostname)
1374 {
1375     g_return_if_fail(WEBKIT_IS_WEB_CONTEXT(context));
1376     g_return_if_fail(hostname);
1377
1378     API::Dictionary::MapType message;
1379     message.set(String::fromUTF8("Hostname"), API::String::create(String::fromUTF8(hostname)));
1380     context->priv->processPool->postMessageToInjectedBundle(String::fromUTF8("PrefetchDNS"), API::Dictionary::create(WTFMove(message)).ptr());
1381 }
1382
1383 /**
1384  * webkit_web_context_allow_tls_certificate_for_host:
1385  * @context: a #WebKitWebContext
1386  * @certificate: a #GTlsCertificate
1387  * @host: the host for which a certificate is to be allowed
1388  *
1389  * Ignore further TLS errors on the @host for the certificate present in @info.
1390  *
1391  * Since: 2.6
1392  */
1393 void webkit_web_context_allow_tls_certificate_for_host(WebKitWebContext* context, GTlsCertificate* certificate, const gchar* host)
1394 {
1395     g_return_if_fail(WEBKIT_IS_WEB_CONTEXT(context));
1396     g_return_if_fail(G_IS_TLS_CERTIFICATE(certificate));
1397     g_return_if_fail(host);
1398
1399     RefPtr<WebCertificateInfo> webCertificateInfo = WebCertificateInfo::create(WebCore::CertificateInfo(certificate, static_cast<GTlsCertificateFlags>(0)));
1400     context->priv->processPool->allowSpecificHTTPSCertificateForHost(webCertificateInfo.get(), String::fromUTF8(host));
1401 }
1402
1403 /**
1404  * webkit_web_context_set_process_model:
1405  * @context: the #WebKitWebContext
1406  * @process_model: a #WebKitProcessModel
1407  *
1408  * Specifies a process model for WebViews, which WebKit will use to
1409  * determine how auxiliary processes are handled. The default setting
1410  * (%WEBKIT_PROCESS_MODEL_SHARED_SECONDARY_PROCESS) is suitable for most
1411  * applications which embed a small amount of WebViews, or are used to
1412  * display documents which are considered safe — like local files.
1413  *
1414  * Applications which may potentially use a large amount of WebViews
1415  * —for example a multi-tabbed web browser— may want to use
1416  * %WEBKIT_PROCESS_MODEL_MULTIPLE_SECONDARY_PROCESSES, which will use
1417  * one process per view most of the time, while still allowing for web
1418  * views to share a process when needed (for example when different
1419  * views interact with each other). Using this model, when a process
1420  * hangs or crashes, only the WebViews using it stop working, while
1421  * the rest of the WebViews in the application will still function
1422  * normally.
1423  *
1424  * This method **must be called before any web process has been created**,
1425  * as early as possible in your application. Calling it later will make
1426  * your application crash.
1427  *
1428  * Since: 2.4
1429  */
1430 void webkit_web_context_set_process_model(WebKitWebContext* context, WebKitProcessModel processModel)
1431 {
1432     g_return_if_fail(WEBKIT_IS_WEB_CONTEXT(context));
1433
1434     if (processModel == context->priv->processModel)
1435         return;
1436
1437     context->priv->processModel = processModel;
1438     switch (context->priv->processModel) {
1439     case WEBKIT_PROCESS_MODEL_SHARED_SECONDARY_PROCESS:
1440         context->priv->processPool->setMaximumNumberOfProcesses(1);
1441         break;
1442     case WEBKIT_PROCESS_MODEL_MULTIPLE_SECONDARY_PROCESSES:
1443         context->priv->processPool->setMaximumNumberOfProcesses(context->priv->processCountLimit);
1444         break;
1445     }
1446 }
1447
1448 /**
1449  * webkit_web_context_get_process_model:
1450  * @context: the #WebKitWebContext
1451  *
1452  * Returns the current process model. For more information about this value
1453  * see webkit_web_context_set_process_model().
1454  *
1455  * Returns: the current #WebKitProcessModel
1456  *
1457  * Since: 2.4
1458  */
1459 WebKitProcessModel webkit_web_context_get_process_model(WebKitWebContext* context)
1460 {
1461     g_return_val_if_fail(WEBKIT_IS_WEB_CONTEXT(context), WEBKIT_PROCESS_MODEL_SHARED_SECONDARY_PROCESS);
1462
1463     return context->priv->processModel;
1464 }
1465
1466 /**
1467  * webkit_web_context_set_web_process_count_limit:
1468  * @context: the #WebKitWebContext
1469  * @limit: the maximum number of web processes
1470  *
1471  * Sets the maximum number of web processes that can be created at the same time for the @context.
1472  * The default value is 0 and means no limit.
1473  *
1474  * This method **must be called before any web process has been created**,
1475  * as early as possible in your application. Calling it later will make
1476  * your application crash.
1477  *
1478  * Since: 2.10
1479  */
1480 void webkit_web_context_set_web_process_count_limit(WebKitWebContext* context, guint limit)
1481 {
1482     g_return_if_fail(WEBKIT_IS_WEB_CONTEXT(context));
1483
1484     if (context->priv->processCountLimit == limit)
1485         return;
1486
1487     context->priv->processCountLimit = limit;
1488     if (context->priv->processModel != WEBKIT_PROCESS_MODEL_SHARED_SECONDARY_PROCESS)
1489         context->priv->processPool->setMaximumNumberOfProcesses(limit);
1490 }
1491
1492 /**
1493  * webkit_web_context_get_web_process_count_limit:
1494  * @context: the #WebKitWebContext
1495  *
1496  * Gets the maximum number of web processes that can be created at the same time for the @context.
1497  *
1498  * Returns: the maximum limit of web processes, or 0 if there isn't a limit.
1499  *
1500  * Since: 2.10
1501  */
1502 guint webkit_web_context_get_web_process_count_limit(WebKitWebContext* context)
1503 {
1504     g_return_val_if_fail(WEBKIT_IS_WEB_CONTEXT(context), 0);
1505
1506     return context->priv->processCountLimit;
1507 }
1508
1509 static void addOriginToMap(WebKitSecurityOrigin* origin, HashMap<String, bool>* map, bool allowed)
1510 {
1511     String string = webkitSecurityOriginGetSecurityOrigin(origin).toString();
1512     if (string != "null")
1513         map->set(string, allowed);
1514 }
1515
1516 /**
1517  * webkit_web_context_initialize_notification_permissions:
1518  * @context: the #WebKitWebContext
1519  * @allowed_origins: (element-type WebKitSecurityOrigin): a #GList of security origins
1520  * @disallowed_origins: (element-type WebKitSecurityOrigin): a #GList of security origins
1521  *
1522  * Sets initial desktop notification permissions for the @context.
1523  * @allowed_origins and @disallowed_origins must each be #GList of
1524  * #WebKitSecurityOrigin objects representing origins that will,
1525  * respectively, either always or never have permission to show desktop
1526  * notifications. No #WebKitNotificationPermissionRequest will ever be
1527  * generated for any of the security origins represented in
1528  * @allowed_origins or @disallowed_origins. This function is necessary
1529  * because some webpages proactively check whether they have permission
1530  * to display notifications without ever creating a permission request.
1531  *
1532  * This function only affects web processes that have not already been
1533  * created. The best time to call it is when handling
1534  * #WebKitWebContext::initialize-notification-permissions so as to
1535  * ensure that new web processes receive the most recent set of
1536  * permissions.
1537  *
1538  * Since: 2.16
1539  */
1540 void webkit_web_context_initialize_notification_permissions(WebKitWebContext* context, GList* allowedOrigins, GList* disallowedOrigins)
1541 {
1542     HashMap<String, bool> map;
1543     g_list_foreach(allowedOrigins, [](gpointer data, gpointer userData) {
1544         addOriginToMap(static_cast<WebKitSecurityOrigin*>(data), static_cast<HashMap<String, bool>*>(userData), true);
1545     }, &map);
1546     g_list_foreach(disallowedOrigins, [](gpointer data, gpointer userData) {
1547         addOriginToMap(static_cast<WebKitSecurityOrigin*>(data), static_cast<HashMap<String, bool>*>(userData), false);
1548     }, &map);
1549     context->priv->notificationProvider->setNotificationPermissions(WTFMove(map));
1550 }
1551
1552 void webkitWebContextInitializeNotificationPermissions(WebKitWebContext* context)
1553 {
1554     g_signal_emit(context, signals[INITIALIZE_NOTIFICATION_PERMISSIONS], 0);
1555 }
1556
1557 WebKitDownload* webkitWebContextGetOrCreateDownload(DownloadProxy* downloadProxy)
1558 {
1559     GRefPtr<WebKitDownload> download = downloadsMap().get(downloadProxy);
1560     if (download)
1561         return download.get();
1562
1563     download = adoptGRef(webkitDownloadCreate(downloadProxy));
1564     downloadsMap().set(downloadProxy, download.get());
1565     return download.get();
1566 }
1567
1568 WebKitDownload* webkitWebContextStartDownload(WebKitWebContext* context, const char* uri, WebPageProxy* initiatingPage)
1569 {
1570     WebCore::ResourceRequest request(String::fromUTF8(uri));
1571     return webkitWebContextGetOrCreateDownload(context->priv->processPool->download(initiatingPage, request));
1572 }
1573
1574 void webkitWebContextRemoveDownload(DownloadProxy* downloadProxy)
1575 {
1576     downloadsMap().remove(downloadProxy);
1577 }
1578
1579 void webkitWebContextDownloadStarted(WebKitWebContext* context, WebKitDownload* download)
1580 {
1581     g_signal_emit(context, signals[DOWNLOAD_STARTED], 0, download);
1582 }
1583
1584 GVariant* webkitWebContextInitializeWebExtensions(WebKitWebContext* context)
1585 {
1586     g_signal_emit(context, signals[INITIALIZE_WEB_EXTENSIONS], 0);
1587     return g_variant_new("(msmv)",
1588         context->priv->webExtensionsDirectory.data(),
1589         context->priv->webExtensionsInitializationUserData.get());
1590 }
1591
1592 WebProcessPool& webkitWebContextGetProcessPool(WebKitWebContext* context)
1593 {
1594     g_assert(WEBKIT_IS_WEB_CONTEXT(context));
1595
1596     return *context->priv->processPool;
1597 }
1598
1599 void webkitWebContextStartLoadingCustomProtocol(WebKitWebContext* context, uint64_t customProtocolID, const WebCore::ResourceRequest& resourceRequest, LegacyCustomProtocolManagerProxy& manager)
1600 {
1601     GRefPtr<WebKitURISchemeRequest> request = adoptGRef(webkitURISchemeRequestCreate(customProtocolID, context, resourceRequest, manager));
1602     String scheme(String::fromUTF8(webkit_uri_scheme_request_get_scheme(request.get())));
1603     RefPtr<WebKitURISchemeHandler> handler = context->priv->uriSchemeHandlers.get(scheme);
1604     ASSERT(handler.get());
1605     if (!handler->hasCallback())
1606         return;
1607
1608     context->priv->uriSchemeRequests.set(customProtocolID, request.get());
1609     handler->performCallback(request.get());
1610 }
1611
1612 void webkitWebContextStopLoadingCustomProtocol(WebKitWebContext* context, uint64_t customProtocolID)
1613 {
1614     GRefPtr<WebKitURISchemeRequest> request = context->priv->uriSchemeRequests.get(customProtocolID);
1615     if (!request.get())
1616         return;
1617     webkitURISchemeRequestCancel(request.get());
1618 }
1619
1620 void webkitWebContextInvalidateCustomProtocolRequests(WebKitWebContext* context, LegacyCustomProtocolManagerProxy& manager)
1621 {
1622     for (auto& request : copyToVector(context->priv->uriSchemeRequests.values())) {
1623         if (webkitURISchemeRequestGetManager(request.get()) == &manager)
1624             webkitURISchemeRequestInvalidate(request.get());
1625     }
1626 }
1627
1628 void webkitWebContextDidFinishLoadingCustomProtocol(WebKitWebContext* context, uint64_t customProtocolID)
1629 {
1630     context->priv->uriSchemeRequests.remove(customProtocolID);
1631 }
1632
1633 bool webkitWebContextIsLoadingCustomProtocol(WebKitWebContext* context, uint64_t customProtocolID)
1634 {
1635     return context->priv->uriSchemeRequests.get(customProtocolID);
1636 }
1637
1638 void webkitWebContextCreatePageForWebView(WebKitWebContext* context, WebKitWebView* webView, WebKitUserContentManager* userContentManager, WebKitWebView* relatedView)
1639 {
1640     // FIXME: icon database private mode is global, not per page, so while there are
1641     // pages in private mode we need to enable the private mode in the icon database.
1642     webkitWebContextEnableIconDatabasePrivateBrowsingIfNeeded(context, webView);
1643
1644     auto pageConfiguration = API::PageConfiguration::create();
1645     pageConfiguration->setProcessPool(context->priv->processPool.get());
1646     pageConfiguration->setPreferences(webkitSettingsGetPreferences(webkit_web_view_get_settings(webView)));
1647     pageConfiguration->setRelatedPage(relatedView ? &webkitWebViewGetPage(relatedView) : nullptr);
1648     pageConfiguration->setUserContentController(userContentManager ? webkitUserContentManagerGetUserContentControllerProxy(userContentManager) : nullptr);
1649     pageConfiguration->setControlledByAutomation(webkit_web_view_is_controlled_by_automation(webView));
1650
1651     WebKitWebsiteDataManager* manager = webkitWebViewGetWebsiteDataManager(webView);
1652     if (!manager)
1653         manager = context->priv->websiteDataManager.get();
1654     pageConfiguration->setWebsiteDataStore(&webkitWebsiteDataManagerGetDataStore(manager));
1655     pageConfiguration->setSessionID(pageConfiguration->websiteDataStore()->websiteDataStore().sessionID());
1656     webkitWebViewCreatePage(webView, WTFMove(pageConfiguration));
1657
1658     context->priv->webViews.set(webkit_web_view_get_page_id(webView), webView);
1659 }
1660
1661 void webkitWebContextWebViewDestroyed(WebKitWebContext* context, WebKitWebView* webView)
1662 {
1663     webkitWebContextDisableIconDatabasePrivateBrowsingIfNeeded(context, webView);
1664     context->priv->webViews.remove(webkit_web_view_get_page_id(webView));
1665 }
1666
1667 WebKitWebView* webkitWebContextGetWebViewForPage(WebKitWebContext* context, WebPageProxy* page)
1668 {
1669     return page ? context->priv->webViews.get(page->pageID()) : 0;
1670 }