diff options
Diffstat (limited to 'Source/WebKit2/UIProcess/API/gtk/WebKitWebContext.cpp')
-rw-r--r-- | Source/WebKit2/UIProcess/API/gtk/WebKitWebContext.cpp | 789 |
1 files changed, 618 insertions, 171 deletions
diff --git a/Source/WebKit2/UIProcess/API/gtk/WebKitWebContext.cpp b/Source/WebKit2/UIProcess/API/gtk/WebKitWebContext.cpp index 1528324ba..e80255f4a 100644 --- a/Source/WebKit2/UIProcess/API/gtk/WebKitWebContext.cpp +++ b/Source/WebKit2/UIProcess/API/gtk/WebKitWebContext.cpp @@ -20,39 +20,48 @@ #include "config.h" #include "WebKitWebContext.h" +#include "APICustomProtocolManagerClient.h" +#include "APIDownloadClient.h" +#include "APIPageConfiguration.h" +#include "APIProcessPoolConfiguration.h" #include "APIString.h" -#include "WebBatteryManagerProxy.h" +#include "TextChecker.h" +#include "TextCheckerState.h" #include "WebCertificateInfo.h" -#include "WebCookieManagerProxy.h" #include "WebGeolocationManagerProxy.h" -#include "WebKitBatteryProvider.h" -#include "WebKitCertificateInfoPrivate.h" -#include "WebKitCookieManagerPrivate.h" +#include "WebKitCustomProtocolManagerClient.h" #include "WebKitDownloadClient.h" #include "WebKitDownloadPrivate.h" #include "WebKitFaviconDatabasePrivate.h" #include "WebKitGeolocationProvider.h" #include "WebKitInjectedBundleClient.h" +#include "WebKitNetworkProxySettingsPrivate.h" +#include "WebKitNotificationProvider.h" #include "WebKitPluginPrivate.h" #include "WebKitPrivate.h" -#include "WebKitRequestManagerClient.h" #include "WebKitSecurityManagerPrivate.h" -#include "WebKitTextChecker.h" +#include "WebKitSecurityOriginPrivate.h" +#include "WebKitSettingsPrivate.h" #include "WebKitURISchemeRequestPrivate.h" +#include "WebKitUserContentManagerPrivate.h" #include "WebKitWebContextPrivate.h" #include "WebKitWebViewBasePrivate.h" -#include "WebKitWebViewGroupPrivate.h" -#include "WebResourceCacheManagerProxy.h" +#include "WebKitWebViewPrivate.h" +#include "WebKitWebsiteDataManagerPrivate.h" +#include "WebNotificationManagerProxy.h" +#include "WebsiteDataType.h" #include <WebCore/FileSystem.h> #include <WebCore/IconDatabase.h> #include <WebCore/Language.h> +#include <glib/gi18n-lib.h> #include <libintl.h> +#include <memory> #include <wtf/HashMap.h> -#include <wtf/OwnPtr.h> +#include <wtf/NeverDestroyed.h> #include <wtf/PassRefPtr.h> #include <wtf/RefCounted.h> -#include <wtf/gobject/GRefPtr.h> -#include <wtf/gobject/GUniquePtr.h> +#include <wtf/glib/GRefPtr.h> +#include <wtf/glib/GUniquePtr.h> #include <wtf/text/CString.h> using namespace WebKit; @@ -68,11 +77,9 @@ using namespace WebKit; * You can define the #WebKitCacheModel and #WebKitProcessModel with * webkit_web_context_set_cache_model() and * webkit_web_context_set_process_model(), depending on the needs of - * your application. You can access the #WebKitCookieManager or the - * #WebKitSecurityManager to specify the behaviour of your application - * regarding cookies and security, using - * webkit_web_context_get_cookie_manager() and - * webkit_web_context_get_security_manager() for that. + * your application. You can access the #WebKitSecurityManager to specify + * the behaviour of your application regarding security using + * webkit_web_context_get_security_manager(). * * It is also possible to change your preferred language or enable * spell checking, using webkit_web_context_set_preferred_languages(), @@ -82,23 +89,32 @@ using namespace WebKit; * You can use webkit_web_context_register_uri_scheme() to register * custom URI schemes, and manage several other settings. * + * TLS certificate validation failure is now treated as a transport + * error by default. To handle TLS failures differently, you can + * connect to #WebKitWebView::load-failed-with-tls-errors. + * Alternatively, you can use webkit_web_context_set_tls_errors_policy() + * to set the policy %WEBKIT_TLS_ERRORS_POLICY_IGNORE; however, this is + * not appropriate for Internet applications. + * */ enum { + PROP_0, + + PROP_LOCAL_STORAGE_DIRECTORY, + PROP_WEBSITE_DATA_MANAGER +}; + +enum { DOWNLOAD_STARTED, INITIALIZE_WEB_EXTENSIONS, + INITIALIZE_NOTIFICATION_PERMISSIONS, LAST_SIGNAL }; class WebKitURISchemeHandler: public RefCounted<WebKitURISchemeHandler> { public: - WebKitURISchemeHandler() - : m_callback(0) - , m_userData(0) - , m_destroyNotify(0) - { - } WebKitURISchemeHandler(WebKitURISchemeRequestCallback callback, void* userData, GDestroyNotify destroyNotify) : m_callback(callback) , m_userData(userData) @@ -125,50 +141,221 @@ public: } private: - WebKitURISchemeRequestCallback m_callback; - void* m_userData; - GDestroyNotify m_destroyNotify; + WebKitURISchemeRequestCallback m_callback { nullptr }; + void* m_userData { nullptr }; + GDestroyNotify m_destroyNotify { nullptr }; }; typedef HashMap<String, RefPtr<WebKitURISchemeHandler> > URISchemeHandlerMap; typedef HashMap<uint64_t, GRefPtr<WebKitURISchemeRequest> > URISchemeRequestMap; struct _WebKitWebContextPrivate { - RefPtr<WebContext> context; + RefPtr<WebProcessPool> processPool; + bool clientsDetached; - GRefPtr<WebKitCookieManager> cookieManager; GRefPtr<WebKitFaviconDatabase> faviconDatabase; GRefPtr<WebKitSecurityManager> securityManager; - RefPtr<WebSoupCustomProtocolRequestManager> requestManager; URISchemeHandlerMap uriSchemeHandlers; URISchemeRequestMap uriSchemeRequests; #if ENABLE(GEOLOCATION) RefPtr<WebKitGeolocationProvider> geolocationProvider; #endif -#if ENABLE(BATTERY_STATUS) - RefPtr<WebKitBatteryProvider> batteryProvider; -#endif -#if ENABLE(SPELLCHECK) - OwnPtr<WebKitTextChecker> textChecker; +#if ENABLE(NOTIFICATIONS) + RefPtr<WebKitNotificationProvider> notificationProvider; #endif + GRefPtr<WebKitWebsiteDataManager> websiteDataManager; + CString faviconDatabaseDirectory; WebKitTLSErrorsPolicy tlsErrorsPolicy; + WebKitProcessModel processModel; + unsigned processCountLimit; HashMap<uint64_t, WebKitWebView*> webViews; - GRefPtr<WebKitWebViewGroup> defaultWebViewGroup; + unsigned ephemeralPageCount; CString webExtensionsDirectory; GRefPtr<GVariant> webExtensionsInitializationUserData; + + CString localStorageDirectory; }; static guint signals[LAST_SIGNAL] = { 0, }; WEBKIT_DEFINE_TYPE(WebKitWebContext, webkit_web_context, G_TYPE_OBJECT) +static const char* injectedBundleDirectory() +{ +#if ENABLE(DEVELOPER_MODE) + const char* bundleDirectory = g_getenv("WEBKIT_INJECTED_BUNDLE_PATH"); + if (bundleDirectory && g_file_test(bundleDirectory, G_FILE_TEST_IS_DIR)) + return bundleDirectory; +#endif + + static const char* injectedBundlePath = LIBDIR G_DIR_SEPARATOR_S "webkit2gtk-" WEBKITGTK_API_VERSION_STRING + G_DIR_SEPARATOR_S "injected-bundle" G_DIR_SEPARATOR_S; + return injectedBundlePath; +} + +static void webkitWebContextGetProperty(GObject* object, guint propID, GValue* value, GParamSpec* paramSpec) +{ + WebKitWebContext* context = WEBKIT_WEB_CONTEXT(object); + + switch (propID) { + case PROP_LOCAL_STORAGE_DIRECTORY: + g_value_set_string(value, context->priv->localStorageDirectory.data()); + break; + case PROP_WEBSITE_DATA_MANAGER: + g_value_set_object(value, webkit_web_context_get_website_data_manager(context)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propID, paramSpec); + } +} + +static void webkitWebContextSetProperty(GObject* object, guint propID, const GValue* value, GParamSpec* paramSpec) +{ + WebKitWebContext* context = WEBKIT_WEB_CONTEXT(object); + + switch (propID) { + case PROP_LOCAL_STORAGE_DIRECTORY: + context->priv->localStorageDirectory = g_value_get_string(value); + break; + case PROP_WEBSITE_DATA_MANAGER: { + gpointer manager = g_value_get_object(value); + context->priv->websiteDataManager = manager ? WEBKIT_WEBSITE_DATA_MANAGER(manager) : nullptr; + break; + } + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propID, paramSpec); + } +} + +static inline WebsiteDataStore::Configuration websiteDataStoreConfigurationForWebProcessPoolConfiguration(const API::ProcessPoolConfiguration& processPoolconfigurarion) +{ + WebsiteDataStore::Configuration configuration; + configuration.applicationCacheDirectory = processPoolconfigurarion.applicationCacheDirectory(); + configuration.networkCacheDirectory = processPoolconfigurarion.diskCacheDirectory(); + configuration.webSQLDatabaseDirectory = processPoolconfigurarion.webSQLDatabaseDirectory(); + configuration.localStorageDirectory = processPoolconfigurarion.localStorageDirectory(); + configuration.mediaKeysStorageDirectory = processPoolconfigurarion.mediaKeysStorageDirectory(); + return configuration; +} + +static void webkitWebContextConstructed(GObject* object) +{ + G_OBJECT_CLASS(webkit_web_context_parent_class)->constructed(object); + + GUniquePtr<char> bundleFilename(g_build_filename(injectedBundleDirectory(), "libwebkit2gtkinjectedbundle.so", nullptr)); + + API::ProcessPoolConfiguration configuration; + configuration.setInjectedBundlePath(WebCore::stringFromFileSystemRepresentation(bundleFilename.get())); + configuration.setMaximumProcessCount(1); + configuration.setDiskCacheSpeculativeValidationEnabled(true); + + WebKitWebContext* webContext = WEBKIT_WEB_CONTEXT(object); + WebKitWebContextPrivate* priv = webContext->priv; + if (priv->websiteDataManager && !webkit_website_data_manager_is_ephemeral(priv->websiteDataManager.get())) { + configuration.setLocalStorageDirectory(WebCore::stringFromFileSystemRepresentation(webkit_website_data_manager_get_local_storage_directory(priv->websiteDataManager.get()))); + configuration.setDiskCacheDirectory(WebCore::pathByAppendingComponent(WebCore::stringFromFileSystemRepresentation(webkit_website_data_manager_get_disk_cache_directory(priv->websiteDataManager.get())), networkCacheSubdirectory)); + configuration.setApplicationCacheDirectory(WebCore::stringFromFileSystemRepresentation(webkit_website_data_manager_get_offline_application_cache_directory(priv->websiteDataManager.get()))); + configuration.setIndexedDBDatabaseDirectory(WebCore::stringFromFileSystemRepresentation(webkit_website_data_manager_get_indexeddb_directory(priv->websiteDataManager.get()))); + configuration.setWebSQLDatabaseDirectory(WebCore::stringFromFileSystemRepresentation(webkit_website_data_manager_get_websql_directory(priv->websiteDataManager.get()))); + } else if (!priv->localStorageDirectory.isNull()) + configuration.setLocalStorageDirectory(WebCore::stringFromFileSystemRepresentation(priv->localStorageDirectory.data())); + + priv->processPool = WebProcessPool::create(configuration); + + if (!priv->websiteDataManager) + priv->websiteDataManager = adoptGRef(webkitWebsiteDataManagerCreate(websiteDataStoreConfigurationForWebProcessPoolConfiguration(configuration))); + + webkitWebsiteDataManagerAddProcessPool(priv->websiteDataManager.get(), *priv->processPool); + + priv->tlsErrorsPolicy = WEBKIT_TLS_ERRORS_POLICY_FAIL; + priv->processPool->setIgnoreTLSErrors(false); + +#if ENABLE(MEMORY_SAMPLER) + if (getenv("WEBKIT_SAMPLE_MEMORY")) + priv->processPool->startMemorySampler(0); +#endif + + attachInjectedBundleClientToContext(webContext); + attachDownloadClientToContext(webContext); + attachCustomProtocolManagerClientToContext(webContext); + +#if ENABLE(GEOLOCATION) + priv->geolocationProvider = WebKitGeolocationProvider::create(priv->processPool->supplement<WebGeolocationManagerProxy>()); +#endif +#if ENABLE(NOTIFICATIONS) + priv->notificationProvider = WebKitNotificationProvider::create(priv->processPool->supplement<WebNotificationManagerProxy>(), webContext); +#endif +} + +static void webkitWebContextDispose(GObject* object) +{ + WebKitWebContextPrivate* priv = WEBKIT_WEB_CONTEXT(object)->priv; + if (!priv->clientsDetached) { + priv->clientsDetached = true; + priv->processPool->initializeInjectedBundleClient(nullptr); + priv->processPool->setDownloadClient(nullptr); + priv->processPool->setCustomProtocolManagerClient(nullptr); + } + + if (priv->websiteDataManager) { + webkitWebsiteDataManagerRemoveProcessPool(priv->websiteDataManager.get(), *priv->processPool); + priv->websiteDataManager = nullptr; + } + + G_OBJECT_CLASS(webkit_web_context_parent_class)->dispose(object); +} + static void webkit_web_context_class_init(WebKitWebContextClass* webContextClass) { GObjectClass* gObjectClass = G_OBJECT_CLASS(webContextClass); + bindtextdomain(GETTEXT_PACKAGE, LOCALEDIR); + bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8"); + + gObjectClass->get_property = webkitWebContextGetProperty; + gObjectClass->set_property = webkitWebContextSetProperty; + gObjectClass->constructed = webkitWebContextConstructed; + gObjectClass->dispose = webkitWebContextDispose; + + /** + * WebKitWebContext:local-storage-directory: + * + * The directory where local storage data will be saved. + * + * Since: 2.8 + * + * Deprecated: 2.10. Use #WebKitWebsiteDataManager:local-storage-directory instead. + */ + g_object_class_install_property( + gObjectClass, + PROP_LOCAL_STORAGE_DIRECTORY, + g_param_spec_string( + "local-storage-directory", + _("Local Storage Directory"), + _("The directory where local storage data will be saved"), + nullptr, + static_cast<GParamFlags>(WEBKIT_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY))); + + /** + * WebKitWebContext:website-data-manager: + * + * The #WebKitWebsiteDataManager associated with this context. + * + * Since: 2.10 + */ + g_object_class_install_property( + gObjectClass, + PROP_WEBSITE_DATA_MANAGER, + g_param_spec_object( + "website-data-manager", + _("Website Data Manager"), + _("The WebKitWebsiteDataManager associated with this context"), + WEBKIT_TYPE_WEBSITE_DATA_MANAGER, + static_cast<GParamFlags>(WEBKIT_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY))); + /** * WebKitWebContext::download-started: * @context: the #WebKitWebContext @@ -178,12 +365,13 @@ static void webkit_web_context_class_init(WebKitWebContextClass* webContextClass */ signals[DOWNLOAD_STARTED] = g_signal_new("download-started", - G_TYPE_FROM_CLASS(gObjectClass), - G_SIGNAL_RUN_LAST, - 0, 0, 0, - g_cclosure_marshal_VOID__OBJECT, - G_TYPE_NONE, 1, - WEBKIT_TYPE_DOWNLOAD); + G_TYPE_FROM_CLASS(gObjectClass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET(WebKitWebContextClass, download_started), + nullptr, nullptr, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + WEBKIT_TYPE_DOWNLOAD); /** * WebKitWebContext::initialize-web-extensions: @@ -200,68 +388,138 @@ static void webkit_web_context_class_init(WebKitWebContextClass* webContextClass g_signal_new("initialize-web-extensions", G_TYPE_FROM_CLASS(gObjectClass), G_SIGNAL_RUN_LAST, - 0, nullptr, nullptr, + G_STRUCT_OFFSET(WebKitWebContextClass, initialize_web_extensions), + nullptr, nullptr, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + /** + * WebKitWebContext::initialize-notification-permissions: + * @context: the #WebKitWebContext + * + * This signal is emitted when a #WebKitWebContext needs to set + * initial notification permissions for a web process. It is emitted + * when a new web process is about to be launched, and signals the + * most appropriate moment to use + * webkit_web_context_initialize_notification_permissions(). If no + * notification permissions have changed since the last time this + * signal was emitted, then there is no need to call + * webkit_web_context_initialize_notification_permissions() again. + * + * Since: 2.16 + */ + signals[INITIALIZE_NOTIFICATION_PERMISSIONS] = + g_signal_new("initialize-notification-permissions", + G_TYPE_FROM_CLASS(gObjectClass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET(WebKitWebContextClass, initialize_notification_permissions), + nullptr, nullptr, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); } -static CString injectedBundleDirectory() +static gpointer createDefaultWebContext(gpointer) { - const char* bundleDirectory = g_getenv("WEBKIT_INJECTED_BUNDLE_PATH"); - if (bundleDirectory && g_file_test(bundleDirectory, G_FILE_TEST_IS_DIR)) - return bundleDirectory; + static GRefPtr<WebKitWebContext> webContext = adoptGRef(WEBKIT_WEB_CONTEXT(g_object_new(WEBKIT_TYPE_WEB_CONTEXT, nullptr))); + return webContext.get(); +} - static const char* injectedBundlePath = LIBDIR G_DIR_SEPARATOR_S "webkit2gtk-" WEBKITGTK_API_VERSION_STRING - G_DIR_SEPARATOR_S "injected-bundle" G_DIR_SEPARATOR_S; - return injectedBundlePath; +/** + * webkit_web_context_get_default: + * + * Gets the default web context + * + * Returns: (transfer none): a #WebKitWebContext + */ +WebKitWebContext* webkit_web_context_get_default(void) +{ + static GOnce onceInit = G_ONCE_INIT; + return WEBKIT_WEB_CONTEXT(g_once(&onceInit, createDefaultWebContext, 0)); } -static CString injectedBundleFilename() +/** + * webkit_web_context_new: + * + * Create a new #WebKitWebContext + * + * Returns: (transfer full): a newly created #WebKitWebContext + * + * Since: 2.8 + */ +WebKitWebContext* webkit_web_context_new(void) { - GUniquePtr<char> bundleFilename(g_build_filename(injectedBundleDirectory().data(), "libwebkit2gtkinjectedbundle.so", NULL)); - return bundleFilename.get(); + return WEBKIT_WEB_CONTEXT(g_object_new(WEBKIT_TYPE_WEB_CONTEXT, nullptr)); } -static gpointer createDefaultWebContext(gpointer) +/** + * webkit_web_context_new_ephemeral: + * + * Create a new ephemeral #WebKitWebContext. An ephemeral #WebKitWebContext is a context + * created with an ephemeral #WebKitWebsiteDataManager. This is just a convenient method + * to create ephemeral contexts without having to create your own #WebKitWebsiteDataManager. + * All #WebKitWebView<!-- -->s associated with this context will also be ephemeral. Websites will + * not store any data in the client storage. + * This is normally used to implement private instances. + * + * Returns: (transfer full): a new ephemeral #WebKitWebContext. + * + * Since: 2.16 + */ +WebKitWebContext* webkit_web_context_new_ephemeral() { - bindtextdomain(GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR); - bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8"); + GRefPtr<WebKitWebsiteDataManager> manager = adoptGRef(webkit_website_data_manager_new_ephemeral()); + return WEBKIT_WEB_CONTEXT(g_object_new(WEBKIT_TYPE_WEB_CONTEXT, "website-data-manager", manager.get(), nullptr)); +} - static GRefPtr<WebKitWebContext> webContext = adoptGRef(WEBKIT_WEB_CONTEXT(g_object_new(WEBKIT_TYPE_WEB_CONTEXT, NULL))); - WebKitWebContextPrivate* priv = webContext->priv; +/** + * webkit_web_context_new_with_website_data_manager: + * @manager: a #WebKitWebsiteDataManager + * + * Create a new #WebKitWebContext with a #WebKitWebsiteDataManager. + * + * Returns: (transfer full): a newly created #WebKitWebContext + * + * Since: 2.10 + */ +WebKitWebContext* webkit_web_context_new_with_website_data_manager(WebKitWebsiteDataManager* manager) +{ + g_return_val_if_fail(WEBKIT_IS_WEBSITE_DATA_MANAGER(manager), nullptr); - priv->context = WebContext::create(WebCore::filenameToString(injectedBundleFilename().data())); - priv->requestManager = webContext->priv->context->supplement<WebSoupCustomProtocolRequestManager>(); - priv->context->setCacheModel(CacheModelPrimaryWebBrowser); - priv->tlsErrorsPolicy = WEBKIT_TLS_ERRORS_POLICY_IGNORE; + return WEBKIT_WEB_CONTEXT(g_object_new(WEBKIT_TYPE_WEB_CONTEXT, "website-data-manager", manager, nullptr)); +} - attachInjectedBundleClientToContext(webContext.get()); - attachDownloadClientToContext(webContext.get()); - attachRequestManagerClientToContext(webContext.get()); +/** + * webkit_web_context_get_website_data_manager: + * @context: the #WebKitWebContext + * + * Get the #WebKitWebsiteDataManager of @context. + * + * Returns: (transfer none): a #WebKitWebsiteDataManager + * + * Since: 2.10 + */ +WebKitWebsiteDataManager* webkit_web_context_get_website_data_manager(WebKitWebContext* context) +{ + g_return_val_if_fail(WEBKIT_IS_WEB_CONTEXT(context), nullptr); -#if ENABLE(GEOLOCATION) - priv->geolocationProvider = WebKitGeolocationProvider::create(priv->context->supplement<WebGeolocationManagerProxy>()); -#endif -#if ENABLE(BATTERY_STATUS) - priv->batteryProvider = WebKitBatteryProvider::create(priv->context->supplement<WebBatteryManagerProxy>()); -#endif -#if ENABLE(SPELLCHECK) - priv->textChecker = WebKitTextChecker::create(); -#endif - return webContext.get(); + return context->priv->websiteDataManager.get(); } /** - * webkit_web_context_get_default: + * webkit_web_context_is_ephemeral: + * @context: the #WebKitWebContext * - * Gets the default web context + * Get whether a #WebKitWebContext is ephemeral. * - * Returns: (transfer none): a #WebKitWebContext + * Returns: %TRUE if @context is ephemeral or %FALSE otherwise. + * + * Since: 2.16 */ -WebKitWebContext* webkit_web_context_get_default(void) +gboolean webkit_web_context_is_ephemeral(WebKitWebContext* context) { - static GOnce onceInit = G_ONCE_INIT; - return WEBKIT_WEB_CONTEXT(g_once(&onceInit, createDefaultWebContext, 0)); + g_return_val_if_fail(WEBKIT_IS_WEB_CONTEXT(context), FALSE); + + return webkit_website_data_manager_is_ephemeral(context->priv->websiteDataManager.get()); } /** @@ -308,8 +566,8 @@ void webkit_web_context_set_cache_model(WebKitWebContext* context, WebKitCacheMo g_assert_not_reached(); } - if (cacheModel != context->priv->context->cacheModel()) - context->priv->context->setCacheModel(cacheModel); + if (cacheModel != context->priv->processPool->cacheModel()) + context->priv->processPool->setCacheModel(cacheModel); } /** @@ -326,7 +584,7 @@ WebKitCacheModel webkit_web_context_get_cache_model(WebKitWebContext* context) { g_return_val_if_fail(WEBKIT_IS_WEB_CONTEXT(context), WEBKIT_CACHE_MODEL_WEB_BROWSER); - switch (context->priv->context->cacheModel()) { + switch (context->priv->processPool->cacheModel()) { case CacheModelDocumentViewer: return WEBKIT_CACHE_MODEL_DOCUMENT_VIEWER; case CacheModelPrimaryWebBrowser: @@ -351,14 +609,59 @@ void webkit_web_context_clear_cache(WebKitWebContext* context) { g_return_if_fail(WEBKIT_IS_WEB_CONTEXT(context)); - context->priv->context->supplement<WebResourceCacheManagerProxy>()->clearCacheForAllOrigins(AllResourceCaches); + OptionSet<WebsiteDataType> websiteDataTypes; + websiteDataTypes |= WebsiteDataType::MemoryCache; + websiteDataTypes |= WebsiteDataType::DiskCache; + auto& websiteDataStore = webkitWebsiteDataManagerGetDataStore(context->priv->websiteDataManager.get()).websiteDataStore(); + websiteDataStore.removeData(websiteDataTypes, std::chrono::system_clock::time_point::min(), [] { }); +} + +/** + * webkit_web_context_set_network_proxy_settings: + * @context: a #WebKitWebContext + * @proxy_mode: a #WebKitNetworkProxyMode + * @proxy_settings: (allow-none): a #WebKitNetworkProxySettings, or %NULL + * + * Set the network proxy settings to be used by connections started in @context. + * By default %WEBKIT_NETWORK_PROXY_MODE_DEFAULT is used, which means that the + * system settings will be used (g_proxy_resolver_get_default()). + * If you want to override the system default settings, you can either use + * %WEBKIT_NETWORK_PROXY_MODE_NO_PROXY to make sure no proxies are used at all, + * or %WEBKIT_NETWORK_PROXY_MODE_CUSTOM to provide your own proxy settings. + * When @proxy_mode is %WEBKIT_NETWORK_PROXY_MODE_CUSTOM @proxy_settings must be + * a valid #WebKitNetworkProxySettings; otherwise, @proxy_settings must be %NULL. + * + * Since: 2.16 + */ +void webkit_web_context_set_network_proxy_settings(WebKitWebContext* context, WebKitNetworkProxyMode proxyMode, WebKitNetworkProxySettings* proxySettings) +{ + g_return_if_fail(WEBKIT_IS_WEB_CONTEXT(context)); + g_return_if_fail((proxyMode != WEBKIT_NETWORK_PROXY_MODE_CUSTOM && !proxySettings) || (proxyMode == WEBKIT_NETWORK_PROXY_MODE_CUSTOM && proxySettings)); + + WebKitWebContextPrivate* priv = context->priv; + switch (proxyMode) { + case WEBKIT_NETWORK_PROXY_MODE_DEFAULT: + priv->processPool->setNetworkProxySettings({ }); + break; + case WEBKIT_NETWORK_PROXY_MODE_NO_PROXY: + priv->processPool->setNetworkProxySettings(WebCore::SoupNetworkProxySettings(WebCore::SoupNetworkProxySettings::Mode::NoProxy)); + break; + case WEBKIT_NETWORK_PROXY_MODE_CUSTOM: + const auto& settings = webkitNetworkProxySettingsGetNetworkProxySettings(proxySettings); + if (settings.isEmpty()) { + g_warning("Invalid attempt to set custom network proxy settings with an empty WebKitNetworkProxySettings. Use " + "WEBKIT_NETWORK_PROXY_MODE_NO_PROXY to not use any proxy or WEBKIT_NETWORK_PROXY_MODE_DEFAULT to use the default system settings"); + } else + priv->processPool->setNetworkProxySettings(settings); + break; + } } typedef HashMap<DownloadProxy*, GRefPtr<WebKitDownload> > DownloadsMap; static DownloadsMap& downloadsMap() { - DEFINE_STATIC_LOCAL(DownloadsMap, downloads, ()); + static NeverDestroyed<DownloadsMap> downloads; return downloads; } @@ -377,29 +680,26 @@ static DownloadsMap& downloadsMap() */ WebKitDownload* webkit_web_context_download_uri(WebKitWebContext* context, const gchar* uri) { - g_return_val_if_fail(WEBKIT_IS_WEB_CONTEXT(context), 0); - g_return_val_if_fail(uri, 0); + g_return_val_if_fail(WEBKIT_IS_WEB_CONTEXT(context), nullptr); + g_return_val_if_fail(uri, nullptr); - return webkitWebContextStartDownload(context, uri, 0); + GRefPtr<WebKitDownload> download = webkitWebContextStartDownload(context, uri, nullptr); + return download.leakRef(); } /** * webkit_web_context_get_cookie_manager: * @context: a #WebKitWebContext * - * Get the #WebKitCookieManager of @context. + * Get the #WebKitCookieManager of the @context's #WebKitWebsiteDataManager. * * Returns: (transfer none): the #WebKitCookieManager of @context. */ WebKitCookieManager* webkit_web_context_get_cookie_manager(WebKitWebContext* context) { - g_return_val_if_fail(WEBKIT_IS_WEB_CONTEXT(context), 0); + g_return_val_if_fail(WEBKIT_IS_WEB_CONTEXT(context), nullptr); - WebKitWebContextPrivate* priv = context->priv; - if (!priv->cookieManager) - priv->cookieManager = adoptGRef(webkitCookieManagerCreate(priv->context->supplement<WebCookieManagerProxy>())); - - return priv->cookieManager.get(); + return webkit_website_data_manager_get_cookie_manager(context->priv->websiteDataManager.get()); } static void ensureFaviconDatabase(WebKitWebContext* context) @@ -408,7 +708,32 @@ static void ensureFaviconDatabase(WebKitWebContext* context) if (priv->faviconDatabase) return; - priv->faviconDatabase = adoptGRef(webkitFaviconDatabaseCreate(priv->context->iconDatabase())); + priv->faviconDatabase = adoptGRef(webkitFaviconDatabaseCreate(priv->processPool->iconDatabase())); +} + +static void webkitWebContextEnableIconDatabasePrivateBrowsingIfNeeded(WebKitWebContext* context, WebKitWebView* webView) +{ + if (webkit_web_context_is_ephemeral(context)) + return; + if (!webkit_web_view_is_ephemeral(webView)) + return; + + if (!context->priv->ephemeralPageCount) + context->priv->processPool->iconDatabase()->setPrivateBrowsingEnabled(true); + context->priv->ephemeralPageCount++; +} + +static void webkitWebContextDisableIconDatabasePrivateBrowsingIfNeeded(WebKitWebContext* context, WebKitWebView* webView) +{ + if (webkit_web_context_is_ephemeral(context)) + return; + if (!webkit_web_view_is_ephemeral(webView)) + return; + + ASSERT(context->priv->ephemeralPageCount); + context->priv->ephemeralPageCount--; + if (!context->priv->ephemeralPageCount) + context->priv->processPool->iconDatabase()->setPrivateBrowsingEnabled(false); } /** @@ -431,16 +756,16 @@ void webkit_web_context_set_favicon_database_directory(WebKitWebContext* context g_return_if_fail(WEBKIT_IS_WEB_CONTEXT(context)); WebKitWebContextPrivate* priv = context->priv; - WebIconDatabase* iconDatabase = priv->context->iconDatabase(); + WebIconDatabase* iconDatabase = priv->processPool->iconDatabase(); if (iconDatabase->isOpen()) return; ensureFaviconDatabase(context); // Use default if 0 is passed as parameter. - String directoryPath = WebCore::filenameToString(path); + String directoryPath = WebCore::stringFromFileSystemRepresentation(path); priv->faviconDatabaseDirectory = directoryPath.isEmpty() - ? priv->context->iconDatabasePath().utf8() + ? priv->processPool->iconDatabasePath().utf8() : directoryPath.utf8(); // Build the full path to the icon database file on disk. @@ -448,7 +773,10 @@ void webkit_web_context_set_favicon_database_directory(WebKitWebContext* context WebCore::IconDatabase::defaultDatabaseFilename().utf8().data(), nullptr)); // Setting the path will cause the icon database to be opened. - priv->context->setIconDatabasePath(WebCore::filenameToString(faviconDatabasePath.get())); + priv->processPool->setIconDatabasePath(WebCore::stringFromFileSystemRepresentation(faviconDatabasePath.get())); + + if (webkit_web_context_is_ephemeral(context)) + priv->processPool->iconDatabase()->setPrivateBrowsingEnabled(true); } /** @@ -528,7 +856,9 @@ void webkit_web_context_set_additional_plugins_directory(WebKitWebContext* conte g_return_if_fail(WEBKIT_IS_WEB_CONTEXT(context)); g_return_if_fail(directory); - context->priv->context->setAdditionalPluginsDirectory(WebCore::filenameToString(directory)); +#if ENABLE(NETSCAPE_PLUGIN_API) + context->priv->processPool->setAdditionalPluginsDirectory(WebCore::stringFromFileSystemRepresentation(directory)); +#endif } static void destroyPluginList(GList* plugins) @@ -536,12 +866,14 @@ static void destroyPluginList(GList* plugins) g_list_free_full(plugins, g_object_unref); } -static void webkitWebContextGetPluginThread(GTask* task, gpointer object, gpointer taskData, GCancellable*) +static void webkitWebContextGetPluginThread(GTask* task, gpointer object, gpointer /* taskData */, GCancellable*) { - Vector<PluginModuleInfo> plugins = WEBKIT_WEB_CONTEXT(object)->priv->context->pluginInfoStore().plugins(); GList* returnValue = 0; +#if ENABLE(NETSCAPE_PLUGIN_API) + Vector<PluginModuleInfo> plugins = WEBKIT_WEB_CONTEXT(object)->priv->processPool->pluginInfoStore().plugins(); for (size_t i = 0; i < plugins.size(); ++i) returnValue = g_list_prepend(returnValue, webkitPluginCreate(plugins[i])); +#endif g_task_return_pointer(task, returnValue, reinterpret_cast<GDestroyNotify>(destroyPluginList)); } @@ -642,8 +974,9 @@ void webkit_web_context_register_uri_scheme(WebKitWebContext* context, const cha g_return_if_fail(callback); RefPtr<WebKitURISchemeHandler> handler = adoptRef(new WebKitURISchemeHandler(callback, userData, destroyNotify)); - context->priv->uriSchemeHandlers.set(String::fromUTF8(scheme), handler.get()); - context->priv->requestManager->registerSchemeForCustomProtocol(String::fromUTF8(scheme)); + auto addResult = context->priv->uriSchemeHandlers.set(String::fromUTF8(scheme), handler.get()); + if (addResult.isNewEntry) + context->priv->processPool->registerSchemeForCustomProtocol(String::fromUTF8(scheme)); } /** @@ -659,7 +992,7 @@ gboolean webkit_web_context_get_spell_checking_enabled(WebKitWebContext* context g_return_val_if_fail(WEBKIT_IS_WEB_CONTEXT(context), FALSE); #if ENABLE(SPELLCHECK) - return context->priv->textChecker->isSpellCheckingEnabled(); + return TextChecker::state().isContinuousSpellCheckingEnabled; #else return false; #endif @@ -677,7 +1010,7 @@ void webkit_web_context_set_spell_checking_enabled(WebKitWebContext* context, gb g_return_if_fail(WEBKIT_IS_WEB_CONTEXT(context)); #if ENABLE(SPELLCHECK) - context->priv->textChecker->setSpellCheckingEnabled(enabled); + TextChecker::setContinuousSpellCheckingEnabled(enabled); #endif } @@ -696,10 +1029,20 @@ void webkit_web_context_set_spell_checking_enabled(WebKitWebContext* context, gb */ const gchar* const* webkit_web_context_get_spell_checking_languages(WebKitWebContext* context) { - g_return_val_if_fail(WEBKIT_IS_WEB_CONTEXT(context), 0); + g_return_val_if_fail(WEBKIT_IS_WEB_CONTEXT(context), nullptr); #if ENABLE(SPELLCHECK) - return context->priv->textChecker->getSpellCheckingLanguages(); + Vector<String> spellCheckingLanguages = TextChecker::loadedSpellCheckingLanguages(); + if (spellCheckingLanguages.isEmpty()) + return nullptr; + + static GRefPtr<GPtrArray> languagesToReturn; + languagesToReturn = adoptGRef(g_ptr_array_new_with_free_func(g_free)); + for (const auto& language : spellCheckingLanguages) + g_ptr_array_add(languagesToReturn.get(), g_strdup(language.utf8().data())); + g_ptr_array_add(languagesToReturn.get(), nullptr); + + return reinterpret_cast<char**>(languagesToReturn->pdata); #else return 0; #endif @@ -728,7 +1071,10 @@ void webkit_web_context_set_spell_checking_languages(WebKitWebContext* context, g_return_if_fail(languages); #if ENABLE(SPELLCHECK) - context->priv->textChecker->setSpellCheckingLanguages(languages); + Vector<String> spellCheckingLanguages; + for (size_t i = 0; languages[i]; ++i) + spellCheckingLanguages.append(String::fromUTF8(languages[i])); + TextChecker::setSpellCheckingLanguages(spellCheckingLanguages); #endif } @@ -750,11 +1096,14 @@ void webkit_web_context_set_preferred_languages(WebKitWebContext* context, const return; Vector<String> languages; - for (size_t i = 0; languageList[i]; ++i) - languages.append(String::fromUTF8(languageList[i]).lower().replace("_", "-")); - + for (size_t i = 0; languageList[i]; ++i) { + // Do not propagate the C locale to WebCore. + if (!g_ascii_strcasecmp(languageList[i], "C") || !g_ascii_strcasecmp(languageList[i], "POSIX")) + languages.append(ASCIILiteral("en-us")); + else + languages.append(String::fromUTF8(languageList[i]).convertToASCIILowercase().replace("_", "-")); + } WebCore::overrideUserPreferredLanguages(languages); - WebCore::languageDidChange(); } /** @@ -773,8 +1122,8 @@ void webkit_web_context_set_tls_errors_policy(WebKitWebContext* context, WebKitT context->priv->tlsErrorsPolicy = policy; bool ignoreTLSErrors = policy == WEBKIT_TLS_ERRORS_POLICY_IGNORE; - if (context->priv->context->ignoreTLSErrors() != ignoreTLSErrors) - context->priv->context->setIgnoreTLSErrors(ignoreTLSErrors); + if (context->priv->processPool->ignoreTLSErrors() != ignoreTLSErrors) + context->priv->processPool->setIgnoreTLSErrors(ignoreTLSErrors); } /** @@ -842,13 +1191,19 @@ void webkit_web_context_set_web_extensions_initialization_user_data(WebKitWebCon * Set the directory where disk cache files will be stored * This method must be called before loading anything in this context, otherwise * it will not have any effect. + * + * Note that this method overrides the directory set in the #WebKitWebsiteDataManager, + * but it doesn't change the value returned by webkit_website_data_manager_get_disk_cache_directory() + * since the #WebKitWebsiteDataManager is immutable. + * + * Deprecated: 2.10. Use webkit_web_context_new_with_website_data_manager() instead. */ void webkit_web_context_set_disk_cache_directory(WebKitWebContext* context, const char* directory) { g_return_if_fail(WEBKIT_IS_WEB_CONTEXT(context)); g_return_if_fail(directory); - context->priv->context->setDiskCacheDirectory(WebCore::filenameToString(directory)); + context->priv->processPool->configuration().setDiskCacheDirectory(WebCore::pathByAppendingComponent(WebCore::stringFromFileSystemRepresentation(directory), networkCacheSubdirectory)); } /** @@ -864,29 +1219,29 @@ void webkit_web_context_prefetch_dns(WebKitWebContext* context, const char* host g_return_if_fail(WEBKIT_IS_WEB_CONTEXT(context)); g_return_if_fail(hostname); - ImmutableDictionary::MapType message; + API::Dictionary::MapType message; message.set(String::fromUTF8("Hostname"), API::String::create(String::fromUTF8(hostname))); - context->priv->context->postMessageToInjectedBundle(String::fromUTF8("PrefetchDNS"), ImmutableDictionary::create(std::move(message)).get()); + context->priv->processPool->postMessageToInjectedBundle(String::fromUTF8("PrefetchDNS"), API::Dictionary::create(WTFMove(message)).ptr()); } /** * webkit_web_context_allow_tls_certificate_for_host: * @context: a #WebKitWebContext - * @info: a #WebKitCertificateInfo + * @certificate: a #GTlsCertificate * @host: the host for which a certificate is to be allowed * * Ignore further TLS errors on the @host for the certificate present in @info. * - * Since: 2.4 + * Since: 2.6 */ -void webkit_web_context_allow_tls_certificate_for_host(WebKitWebContext* context, WebKitCertificateInfo* info, const gchar* host) +void webkit_web_context_allow_tls_certificate_for_host(WebKitWebContext* context, GTlsCertificate* certificate, const gchar* host) { g_return_if_fail(WEBKIT_IS_WEB_CONTEXT(context)); - g_return_if_fail(info); + g_return_if_fail(G_IS_TLS_CERTIFICATE(certificate)); g_return_if_fail(host); - RefPtr<WebCertificateInfo> webCertificateInfo = WebCertificateInfo::create(webkitCertificateInfoGetCertificateInfo(info)); - context->priv->context->allowSpecificHTTPSCertificateForHost(webCertificateInfo.get(), String::fromUTF8(host)); + RefPtr<WebCertificateInfo> webCertificateInfo = WebCertificateInfo::create(WebCore::CertificateInfo(certificate, static_cast<GTlsCertificateFlags>(0))); + context->priv->processPool->allowSpecificHTTPSCertificateForHost(webCertificateInfo.get(), String::fromUTF8(host)); } /** @@ -910,7 +1265,7 @@ void webkit_web_context_allow_tls_certificate_for_host(WebKitWebContext* context * the rest of the WebViews in the application will still function * normally. * - * This method **must be called before any other functions**, + * This method **must be called before any web process has been created**, * as early as possible in your application. Calling it later will make * your application crash. * @@ -920,24 +1275,18 @@ void webkit_web_context_set_process_model(WebKitWebContext* context, WebKitProce { g_return_if_fail(WEBKIT_IS_WEB_CONTEXT(context)); - ProcessModel newProcessModel; + if (processModel == context->priv->processModel) + return; - switch (processModel) { + context->priv->processModel = processModel; + switch (context->priv->processModel) { case WEBKIT_PROCESS_MODEL_SHARED_SECONDARY_PROCESS: - newProcessModel = ProcessModelSharedSecondaryProcess; + context->priv->processPool->setMaximumNumberOfProcesses(1); break; case WEBKIT_PROCESS_MODEL_MULTIPLE_SECONDARY_PROCESSES: - newProcessModel = ProcessModelMultipleSecondaryProcesses; + context->priv->processPool->setMaximumNumberOfProcesses(context->priv->processCountLimit); break; - default: - g_assert_not_reached(); } - - if (newProcessModel == context->priv->context->processModel()) - return; - - context->priv->context->setUsesNetworkProcess(newProcessModel == ProcessModelMultipleSecondaryProcesses); - context->priv->context->setProcessModel(newProcessModel); } /** @@ -955,14 +1304,98 @@ WebKitProcessModel webkit_web_context_get_process_model(WebKitWebContext* contex { g_return_val_if_fail(WEBKIT_IS_WEB_CONTEXT(context), WEBKIT_PROCESS_MODEL_SHARED_SECONDARY_PROCESS); - switch (context->priv->context->processModel()) { - case ProcessModelSharedSecondaryProcess: - return WEBKIT_PROCESS_MODEL_SHARED_SECONDARY_PROCESS; - case ProcessModelMultipleSecondaryProcesses: - return WEBKIT_PROCESS_MODEL_MULTIPLE_SECONDARY_PROCESSES; - default: - g_assert_not_reached(); - } + return context->priv->processModel; +} + +/** + * webkit_web_context_set_web_process_count_limit: + * @context: the #WebKitWebContext + * @limit: the maximum number of web processes + * + * Sets the maximum number of web processes that can be created at the same time for the @context. + * The default value is 0 and means no limit. + * + * This method **must be called before any web process has been created**, + * as early as possible in your application. Calling it later will make + * your application crash. + * + * Since: 2.10 + */ +void webkit_web_context_set_web_process_count_limit(WebKitWebContext* context, guint limit) +{ + g_return_if_fail(WEBKIT_IS_WEB_CONTEXT(context)); + + if (context->priv->processCountLimit == limit) + return; + + context->priv->processCountLimit = limit; + if (context->priv->processModel != WEBKIT_PROCESS_MODEL_SHARED_SECONDARY_PROCESS) + context->priv->processPool->setMaximumNumberOfProcesses(limit); +} + +/** + * webkit_web_context_get_web_process_count_limit: + * @context: the #WebKitWebContext + * + * Gets the maximum number of web processes that can be created at the same time for the @context. + * + * Returns: the maximum limit of web processes, or 0 if there isn't a limit. + * + * Since: 2.10 + */ +guint webkit_web_context_get_web_process_count_limit(WebKitWebContext* context) +{ + g_return_val_if_fail(WEBKIT_IS_WEB_CONTEXT(context), 0); + + return context->priv->processCountLimit; +} + +static void addOriginToMap(WebKitSecurityOrigin* origin, HashMap<String, RefPtr<API::Object>>* map, bool allowed) +{ + String string = webkitSecurityOriginGetSecurityOrigin(origin).toString(); + if (string != "null") + map->set(string, API::Boolean::create(allowed)); +} + +/** + * webkit_web_context_initialize_notification_permissions: + * @context: the #WebKitWebContext + * @allowed_origins: (element-type WebKitSecurityOrigin): a #GList of security origins + * @disallowed_origins: (element-type WebKitSecurityOrigin): a #GList of security origins + * + * Sets initial desktop notification permissions for the @context. + * @allowed_origins and @disallowed_origins must each be #GList of + * #WebKitSecurityOrigin objects representing origins that will, + * respectively, either always or never have permission to show desktop + * notifications. No #WebKitNotificationPermissionRequest will ever be + * generated for any of the security origins represented in + * @allowed_origins or @disallowed_origins. This function is necessary + * because some webpages proactively check whether they have permission + * to display notifications without ever creating a permission request. + * + * This function only affects web processes that have not already been + * created. The best time to call it is when handling + * #WebKitWebContext::initialize-notification-permissions so as to + * ensure that new web processes receive the most recent set of + * permissions. + * + * Since: 2.16 + */ +void webkit_web_context_initialize_notification_permissions(WebKitWebContext* context, GList* allowedOrigins, GList* disallowedOrigins) +{ + HashMap<String, RefPtr<API::Object>> map; + g_list_foreach(allowedOrigins, [](gpointer data, gpointer userData) { + addOriginToMap(static_cast<WebKitSecurityOrigin*>(data), static_cast<HashMap<String, RefPtr<API::Object>>*>(userData), true); + }, &map); + g_list_foreach(disallowedOrigins, [](gpointer data, gpointer userData) { + addOriginToMap(static_cast<WebKitSecurityOrigin*>(data), static_cast<HashMap<String, RefPtr<API::Object>>*>(userData), false); + }, &map); + context->priv->notificationProvider->setNotificationPermissions(WTFMove(map)); +} + +void webkitWebContextInitializeNotificationPermissions(WebKitWebContext* context) +{ + g_signal_emit(context, signals[INITIALIZE_NOTIFICATION_PERMISSIONS], 0); } WebKitDownload* webkitWebContextGetOrCreateDownload(DownloadProxy* downloadProxy) @@ -979,10 +1412,7 @@ WebKitDownload* webkitWebContextGetOrCreateDownload(DownloadProxy* downloadProxy WebKitDownload* webkitWebContextStartDownload(WebKitWebContext* context, const char* uri, WebPageProxy* initiatingPage) { WebCore::ResourceRequest request(String::fromUTF8(uri)); - DownloadProxy* downloadProxy = context->priv->context->download(initiatingPage, request); - WebKitDownload* download = webkitDownloadCreateForRequest(downloadProxy, request); - downloadsMap().set(downloadProxy, download); - return download; + return webkitWebContextGetOrCreateDownload(context->priv->processPool->download(initiatingPage, request)); } void webkitWebContextRemoveDownload(DownloadProxy* downloadProxy) @@ -1003,21 +1433,16 @@ GVariant* webkitWebContextInitializeWebExtensions(WebKitWebContext* context) context->priv->webExtensionsInitializationUserData.get()); } -WebContext* webkitWebContextGetContext(WebKitWebContext* context) +WebProcessPool& webkitWebContextGetProcessPool(WebKitWebContext* context) { g_assert(WEBKIT_IS_WEB_CONTEXT(context)); - return context->priv->context.get(); -} - -WebSoupCustomProtocolRequestManager* webkitWebContextGetRequestManager(WebKitWebContext* context) -{ - return context->priv->requestManager.get(); + return *context->priv->processPool; } -void webkitWebContextStartLoadingCustomProtocol(WebKitWebContext* context, uint64_t customProtocolID, API::URLRequest* urlRequest) +void webkitWebContextStartLoadingCustomProtocol(WebKitWebContext* context, uint64_t customProtocolID, const WebCore::ResourceRequest& resourceRequest, CustomProtocolManagerProxy& manager) { - GRefPtr<WebKitURISchemeRequest> request = adoptGRef(webkitURISchemeRequestCreate(customProtocolID, context, urlRequest)); + GRefPtr<WebKitURISchemeRequest> request = adoptGRef(webkitURISchemeRequestCreate(customProtocolID, context, resourceRequest, manager)); String scheme(String::fromUTF8(webkit_uri_scheme_request_get_scheme(request.get()))); RefPtr<WebKitURISchemeHandler> handler = context->priv->uriSchemeHandlers.get(scheme); ASSERT(handler.get()); @@ -1036,27 +1461,54 @@ void webkitWebContextStopLoadingCustomProtocol(WebKitWebContext* context, uint64 webkitURISchemeRequestCancel(request.get()); } +void webkitWebContextInvalidateCustomProtocolRequests(WebKitWebContext* context, CustomProtocolManagerProxy& manager) +{ + Vector<GRefPtr<WebKitURISchemeRequest>> requests; + copyValuesToVector(context->priv->uriSchemeRequests, requests); + for (auto& request : requests) { + if (webkitURISchemeRequestGetManager(request.get()) == &manager) + webkitURISchemeRequestInvalidate(request.get()); + } +} + void webkitWebContextDidFinishLoadingCustomProtocol(WebKitWebContext* context, uint64_t customProtocolID) { context->priv->uriSchemeRequests.remove(customProtocolID); } -void webkitWebContextCreatePageForWebView(WebKitWebContext* context, WebKitWebView* webView, WebKitWebViewGroup* webViewGroup, WebKitWebView* relatedView) +bool webkitWebContextIsLoadingCustomProtocol(WebKitWebContext* context, uint64_t customProtocolID) +{ + return context->priv->uriSchemeRequests.get(customProtocolID); +} + +void webkitWebContextCreatePageForWebView(WebKitWebContext* context, WebKitWebView* webView, WebKitUserContentManager* userContentManager, WebKitWebView* relatedView) { WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(webView); - WebPageGroup* pageGroup = webViewGroup ? webkitWebViewGroupGetPageGroup(webViewGroup) : 0; - WebPageProxy* relatedPage = relatedView ? webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(relatedView)) : nullptr; - webkitWebViewBaseCreateWebPage(webViewBase, context->priv->context.get(), pageGroup, relatedPage); + + // FIXME: icon database private mode is global, not per page, so while there are + // pages in private mode we need to enable the private mode in the icon database. + webkitWebContextEnableIconDatabasePrivateBrowsingIfNeeded(context, webView); + + auto pageConfiguration = API::PageConfiguration::create(); + pageConfiguration->setProcessPool(context->priv->processPool.get()); + pageConfiguration->setPreferences(webkitSettingsGetPreferences(webkit_web_view_get_settings(webView))); + pageConfiguration->setRelatedPage(relatedView ? webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(relatedView)) : nullptr); + pageConfiguration->setUserContentController(userContentManager ? webkitUserContentManagerGetUserContentControllerProxy(userContentManager) : nullptr); + + WebKitWebsiteDataManager* manager = webkitWebViewGetWebsiteDataManager(webView); + if (!manager) + manager = context->priv->websiteDataManager.get(); + pageConfiguration->setWebsiteDataStore(&webkitWebsiteDataManagerGetDataStore(manager)); + pageConfiguration->setSessionID(pageConfiguration->websiteDataStore()->websiteDataStore().sessionID()); + webkitWebViewBaseCreateWebPage(webViewBase, WTFMove(pageConfiguration)); WebPageProxy* page = webkitWebViewBaseGetPage(webViewBase); context->priv->webViews.set(page->pageID(), webView); - - if (!pageGroup && !context->priv->defaultWebViewGroup) - context->priv->defaultWebViewGroup = adoptGRef(webkitWebViewGroupCreate(&page->pageGroup())); } void webkitWebContextWebViewDestroyed(WebKitWebContext* context, WebKitWebView* webView) { + webkitWebContextDisableIconDatabasePrivateBrowsingIfNeeded(context, webView); WebPageProxy* page = webkitWebViewBaseGetPage(WEBKIT_WEB_VIEW_BASE(webView)); context->priv->webViews.remove(page->pageID()); } @@ -1065,8 +1517,3 @@ WebKitWebView* webkitWebContextGetWebViewForPage(WebKitWebContext* context, WebP { return page ? context->priv->webViews.get(page->pageID()) : 0; } - -WebKitWebViewGroup* webkitWebContextGetDefaultWebViewGroup(WebKitWebContext* context) -{ - return context->priv->defaultWebViewGroup.get(); -} |