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