diff options
author | Allan Sandfeld Jensen <allan.jensen@digia.com> | 2014-11-24 18:03:17 +0100 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@theqtcompany.com> | 2014-12-12 12:29:12 +0100 |
commit | 6ec3268a30a63d5c15258ea6f4f792e21930b093 (patch) | |
tree | b2a122f94eed67546a7ee1d0f118a7e72ec18c8f /src/core | |
parent | b93a478d60e90073870aad22febd519adc4a4a3b (diff) |
Introduce QWebEngineProfile API
Introduces initial widgets API for the Chromium BrowserContext.
Adds API for controlling cookie jar policy, user-agent string and
cache and persistent data paths.
Similar QML API will follow in another patch.
[ChangeLog][QtWebEngineWidgets][QWebEngineProfile] New API for profiles
applying to groups of QWebEnginePages.
Change-Id: I3c4ef4053fde7564af29178c91a0aca8a2b61a5f
Reviewed-by: Jocelyn Turcotte <jocelyn.turcotte@digia.com>
Diffstat (limited to 'src/core')
-rw-r--r-- | src/core/browser_context_adapter.cpp | 161 | ||||
-rw-r--r-- | src/core/browser_context_adapter.h | 51 | ||||
-rw-r--r-- | src/core/browser_context_qt.cpp | 7 | ||||
-rw-r--r-- | src/core/browser_context_qt.h | 4 | ||||
-rw-r--r-- | src/core/url_request_context_getter_qt.cpp | 304 | ||||
-rw-r--r-- | src/core/url_request_context_getter_qt.h | 24 | ||||
-rw-r--r-- | src/core/web_contents_adapter.cpp | 7 | ||||
-rw-r--r-- | src/core/web_contents_adapter_p.h | 4 | ||||
-rw-r--r-- | src/core/web_engine_context.cpp | 8 | ||||
-rw-r--r-- | src/core/web_engine_context.h | 6 |
10 files changed, 440 insertions, 136 deletions
diff --git a/src/core/browser_context_adapter.cpp b/src/core/browser_context_adapter.cpp index ccb6a385d..133dd688a 100644 --- a/src/core/browser_context_adapter.cpp +++ b/src/core/browser_context_adapter.cpp @@ -37,8 +37,12 @@ #include "browser_context_adapter.h" #include "browser_context_qt.h" +#include "content_client_qt.h" #include "web_engine_context.h" #include "web_engine_visited_links_manager.h" +#include "url_request_context_getter_qt.h" + +#include "net/proxy/proxy_service.h" #include <QCoreApplication> #include <QDir> @@ -57,11 +61,22 @@ inline QString buildLocationFromStandardPath(const QString &standardPath, const } } -BrowserContextAdapter::BrowserContextAdapter(const QString &name, bool offTheRecord) - : m_name(name) - , m_offTheRecord(offTheRecord) +BrowserContextAdapter::BrowserContextAdapter(bool offTheRecord) + : m_offTheRecord(offTheRecord) + , m_browserContext(new BrowserContextQt(this)) + , m_httpCacheType(DiskHttpCache) + , m_persistentCookiesPolicy(AllowPersistentCookies) + , m_httpCacheMaxSize(0) +{ +} + +BrowserContextAdapter::BrowserContextAdapter(const QString &storageName) + : m_name(storageName) + , m_offTheRecord(false) , m_browserContext(new BrowserContextQt(this)) - , m_visitedLinksManager(new WebEngineVisitedLinksManager(this)) + , m_httpCacheType(DiskHttpCache) + , m_persistentCookiesPolicy(AllowPersistentCookies) + , m_httpCacheMaxSize(0) { } @@ -69,6 +84,24 @@ BrowserContextAdapter::~BrowserContextAdapter() { } +void BrowserContextAdapter::setStorageName(const QString &storageName) +{ + if (storageName == m_name) + return; + m_name = storageName; + if (m_browserContext->url_request_getter_) + m_browserContext->url_request_getter_->updateStorageSettings(); +} + +void BrowserContextAdapter::setOffTheRecord(bool offTheRecord) +{ + if (offTheRecord == m_offTheRecord) + return; + m_offTheRecord = offTheRecord; + if (m_browserContext->url_request_getter_) + m_browserContext->url_request_getter_->updateStorageSettings(); +} + BrowserContextQt *BrowserContextAdapter::browserContext() { return m_browserContext.data(); @@ -76,6 +109,8 @@ BrowserContextQt *BrowserContextAdapter::browserContext() WebEngineVisitedLinksManager *BrowserContextAdapter::visitedLinksManager() { + if (!m_visitedLinksManager) + m_visitedLinksManager.reset(new WebEngineVisitedLinksManager(this)); return m_visitedLinksManager.data(); } @@ -91,10 +126,124 @@ BrowserContextAdapter* BrowserContextAdapter::offTheRecordContext() QString BrowserContextAdapter::dataPath() const { - return buildLocationFromStandardPath(QStandardPaths::writableLocation(QStandardPaths::DataLocation), m_name); + if (m_offTheRecord) + return QString(); + if (!m_dataPath.isEmpty()) + return m_dataPath; + if (!m_name.isNull()) + return buildLocationFromStandardPath(QStandardPaths::writableLocation(QStandardPaths::DataLocation), m_name); + return QString(); +} + +void BrowserContextAdapter::setDataPath(const QString &path) +{ + if (m_dataPath == path) + return; + m_dataPath = path; + if (m_browserContext->url_request_getter_) + m_browserContext->url_request_getter_->updateStorageSettings(); } QString BrowserContextAdapter::cachePath() const { - return buildLocationFromStandardPath(QStandardPaths::writableLocation(QStandardPaths::CacheLocation), m_name); + if (m_offTheRecord) + return QString(); + if (!m_cachePath.isEmpty()) + return m_cachePath; + if (!m_name.isNull()) + return buildLocationFromStandardPath(QStandardPaths::writableLocation(QStandardPaths::CacheLocation), m_name); + return QString(); +} + +void BrowserContextAdapter::setCachePath(const QString &path) +{ + if (m_cachePath == path) + return; + m_cachePath = path; + if (m_browserContext->url_request_getter_) + m_browserContext->url_request_getter_->updateHttpCache(); +} + +QString BrowserContextAdapter::cookiesPath() const +{ + if (m_offTheRecord) + return QString(); + QString basePath = dataPath(); + if (!basePath.isEmpty()) + return basePath % QDir::separator() % QLatin1String("Coookies"); + return QString(); +} + +QString BrowserContextAdapter::httpCachePath() const +{ + if (m_offTheRecord) + return QString(); + QString basePath = cachePath(); + if (!basePath.isEmpty()) + return basePath % QDir::separator() % QLatin1String("Cache"); + return QString(); +} + +QString BrowserContextAdapter::httpUserAgent() const +{ + if (m_httpUserAgent.isNull()) + return QString::fromStdString(ContentClientQt::getUserAgent()); + return m_httpUserAgent; +} + +void BrowserContextAdapter::setHttpUserAgent(const QString &userAgent) +{ + if (m_httpUserAgent == userAgent) + return; + m_httpUserAgent = userAgent; + if (m_browserContext->url_request_getter_) + m_browserContext->url_request_getter_->updateUserAgent(); +} + +BrowserContextAdapter::HttpCacheType BrowserContextAdapter::httpCacheType() const +{ + if (isOffTheRecord() || httpCachePath().isEmpty()) + return MemoryHttpCache; + return m_httpCacheType; +} + +void BrowserContextAdapter::setHttpCacheType(BrowserContextAdapter::HttpCacheType newhttpCacheType) +{ + BrowserContextAdapter::HttpCacheType oldCacheType = httpCacheType(); + m_httpCacheType = newhttpCacheType; + if (oldCacheType == httpCacheType()) + return; + if (m_browserContext->url_request_getter_) + m_browserContext->url_request_getter_->updateHttpCache(); +} + +BrowserContextAdapter::PersistentCookiesPolicy BrowserContextAdapter::persistentCookiesPolicy() const +{ + if (isOffTheRecord() || cookiesPath().isEmpty()) + return NoPersistentCookies; + return m_persistentCookiesPolicy; +} + +void BrowserContextAdapter::setPersistentCookiesPolicy(BrowserContextAdapter::PersistentCookiesPolicy newPersistentCookiesPolicy) +{ + BrowserContextAdapter::PersistentCookiesPolicy oldPolicy = persistentCookiesPolicy(); + m_persistentCookiesPolicy = newPersistentCookiesPolicy; + if (oldPolicy == persistentCookiesPolicy()) + return; + if (m_browserContext->url_request_getter_) + m_browserContext->url_request_getter_->updateCookieStore(); +} + +int BrowserContextAdapter::httpCacheMaxSize() const +{ + return m_httpCacheMaxSize; +} + +void BrowserContextAdapter::setHttpCacheMaxSize(int maxSize) +{ + if (m_httpCacheMaxSize == maxSize) + return; + m_httpCacheMaxSize = maxSize; + if (m_browserContext->url_request_getter_) + m_browserContext->url_request_getter_->updateHttpCache(); } diff --git a/src/core/browser_context_adapter.h b/src/core/browser_context_adapter.h index e4e046c8e..dabd8a11e 100644 --- a/src/core/browser_context_adapter.h +++ b/src/core/browser_context_adapter.h @@ -46,10 +46,11 @@ class BrowserContextQt; class WebEngineVisitedLinksManager; -// Make a QSharedData if we need to open arbitrary BrowserContextAdapter beyond the defaults. -class QWEBENGINE_EXPORT BrowserContextAdapter // : public QSharedData +class QWEBENGINE_EXPORT BrowserContextAdapter : public QSharedData { public: + explicit BrowserContextAdapter(bool offTheRecord = false); + explicit BrowserContextAdapter(const QString &storagePrefix); virtual ~BrowserContextAdapter(); static BrowserContextAdapter* defaultContext(); @@ -58,19 +59,57 @@ public: WebEngineVisitedLinksManager *visitedLinksManager(); BrowserContextQt *browserContext(); + + QString storageName() const { return m_name; } + void setStorageName(const QString &storageName); + bool isOffTheRecord() const { return m_offTheRecord; } + void setOffTheRecord(bool offTheRecord); + QString dataPath() const; + void setDataPath(const QString &path); + QString cachePath() const; + void setCachePath(const QString &path); + + QString httpCachePath() const; + QString cookiesPath() const; + + QString httpUserAgent() const; + void setHttpUserAgent(const QString &userAgent); + + // KEEP IN SYNC with API or add mapping layer + enum HttpCacheType { + MemoryHttpCache = 0, + DiskHttpCache + }; + + enum PersistentCookiesPolicy { + NoPersistentCookies = 0, + AllowPersistentCookies, + ForcePersistentCookies + }; + + HttpCacheType httpCacheType() const; + void setHttpCacheType(BrowserContextAdapter::HttpCacheType); + + PersistentCookiesPolicy persistentCookiesPolicy() const; + void setPersistentCookiesPolicy(BrowserContextAdapter::PersistentCookiesPolicy); -protected: - BrowserContextAdapter(const QString &name, bool offTheRecord = false); + int httpCacheMaxSize() const; + void setHttpCacheMaxSize(int maxSize); private: - const QString m_name; + QString m_name; bool m_offTheRecord; QScopedPointer<BrowserContextQt> m_browserContext; QScopedPointer<WebEngineVisitedLinksManager> m_visitedLinksManager; - friend class WebEngineContext; + QString m_dataPath; + QString m_cachePath; + QString m_httpUserAgent; + HttpCacheType m_httpCacheType; + PersistentCookiesPolicy m_persistentCookiesPolicy; + int m_httpCacheMaxSize; Q_DISABLE_COPY(BrowserContextAdapter) }; diff --git a/src/core/browser_context_qt.cpp b/src/core/browser_context_qt.cpp index 2484ba879..e2cc8851b 100644 --- a/src/core/browser_context_qt.cpp +++ b/src/core/browser_context_qt.cpp @@ -51,7 +51,6 @@ BrowserContextQt::BrowserContextQt(BrowserContextAdapter *adapter) : m_adapter(adapter) { - resourceContext.reset(new ResourceContextQt(this)); } BrowserContextQt::~BrowserContextQt() @@ -102,6 +101,8 @@ net::URLRequestContextGetter *BrowserContextQt::GetMediaRequestContextForStorage content::ResourceContext *BrowserContextQt::GetResourceContext() { + if (!resourceContext) + resourceContext.reset(new ResourceContextQt(this)); return resourceContext.get(); } @@ -128,7 +129,7 @@ content::PushMessagingService *BrowserContextQt::GetPushMessagingService() net::URLRequestContextGetter *BrowserContextQt::CreateRequestContext(content::ProtocolHandlerMap *protocol_handlers) { - url_request_getter_ = new URLRequestContextGetterQt(this, protocol_handlers); - static_cast<ResourceContextQt*>(resourceContext.get())->set_url_request_context_getter(url_request_getter_.get()); + url_request_getter_ = new URLRequestContextGetterQt(m_adapter, protocol_handlers); + static_cast<ResourceContextQt*>(GetResourceContext())->set_url_request_context_getter(url_request_getter_.get()); return url_request_getter_.get(); } diff --git a/src/core/browser_context_qt.h b/src/core/browser_context_qt.h index 634db6f3f..c11a234ab 100644 --- a/src/core/browser_context_qt.h +++ b/src/core/browser_context_qt.h @@ -44,6 +44,7 @@ #include "download_manager_delegate_qt.h" class BrowserContextAdapter; +class URLRequestContextGetterQt; class BrowserContextQt : public content::BrowserContext { @@ -70,9 +71,10 @@ public: private: scoped_ptr<content::ResourceContext> resourceContext; - scoped_refptr<net::URLRequestContextGetter> url_request_getter_; + scoped_refptr<URLRequestContextGetterQt> url_request_getter_; scoped_ptr<DownloadManagerDelegateQt> downloadManagerDelegate; BrowserContextAdapter *m_adapter; + friend class BrowserContextAdapter; DISALLOW_COPY_AND_ASSIGN(BrowserContextQt); }; diff --git a/src/core/url_request_context_getter_qt.cpp b/src/core/url_request_context_getter_qt.cpp index 282e5e94f..0d72845b5 100644 --- a/src/core/url_request_context_getter_qt.cpp +++ b/src/core/url_request_context_getter_qt.cpp @@ -61,141 +61,229 @@ #include "net/url_request/ftp_protocol_handler.h" #include "net/ftp/ftp_network_layer.h" -#include "browser_context_qt.h" +#include "browser_context_adapter.h" #include "content_client_qt.h" #include "network_delegate_qt.h" #include "qrc_protocol_handler_qt.h" +#include "type_conversion.h" static const char kQrcSchemeQt[] = "qrc"; using content::BrowserThread; -URLRequestContextGetterQt::URLRequestContextGetterQt(BrowserContextQt *browserContext, content::ProtocolHandlerMap *protocolHandlers) +URLRequestContextGetterQt::URLRequestContextGetterQt(BrowserContextAdapter *browserContext, content::ProtocolHandlerMap *protocolHandlers) : m_ignoreCertificateErrors(false) + , m_updateStorageSettings(false) + , m_updateCookieStore(false) + , m_updateHttpCache(false) , m_browserContext(browserContext) { std::swap(m_protocolHandlers, *protocolHandlers); - // We must create the proxy config service on the UI loop on Linux because it - // must synchronously run on the glib message loop. This will be passed to - // the URLRequestContextStorage on the IO thread in GetURLRequestContext(). -//#ifdef Q_OS_LINUX - m_proxyConfigService.reset(net::ProxyService::CreateSystemProxyConfigService(BrowserThread::UnsafeGetMessageLoopForThread(BrowserThread::IO)->message_loop_proxy() - , BrowserThread::UnsafeGetMessageLoopForThread(BrowserThread::FILE))); -//#endif + updateStorageSettings(); } net::URLRequestContext *URLRequestContextGetterQt::GetURLRequestContext() { if (!m_urlRequestContext) { - m_urlRequestContext.reset(new net::URLRequestContext()); - m_networkDelegate.reset(new NetworkDelegateQt); + m_networkDelegate.reset(new NetworkDelegateQt); m_urlRequestContext->set_network_delegate(m_networkDelegate.get()); - scoped_refptr<net::CookieStore> cookieStore; - if (m_browserContext->IsOffTheRecord()) { - cookieStore = content::CreateCookieStore(content::CookieStoreConfig(base::FilePath(), content::CookieStoreConfig::EPHEMERAL_SESSION_COOKIES, NULL, NULL)); - } else { - base::FilePath cookiesPath = m_browserContext->GetPath().Append(FILE_PATH_LITERAL("Cookies")); - cookieStore = content::CreateCookieStore(content::CookieStoreConfig(cookiesPath, content::CookieStoreConfig::PERSISTANT_SESSION_COOKIES, NULL, NULL)); - } - - m_storage.reset(new net::URLRequestContextStorage(m_urlRequestContext.get())); - m_storage->set_cookie_store(cookieStore.get()); - m_storage->set_server_bound_cert_service(new net::ServerBoundCertService( - new net::DefaultServerBoundCertStore(NULL), - base::WorkerPool::GetTaskRunner(true))); - m_storage->set_http_user_agent_settings( - new net::StaticHttpUserAgentSettings("en-us,en", ContentClientQt::getUserAgent())); - - scoped_ptr<net::HostResolver> host_resolver( - net::HostResolver::CreateDefaultResolver(NULL)); - - m_storage->set_cert_verifier(net::CertVerifier::CreateDefault()); - - m_storage->set_proxy_service(net::ProxyService::CreateUsingSystemProxyResolver(m_proxyConfigService.release(), 0, NULL)); - - m_storage->set_ssl_config_service(new net::SSLConfigServiceDefaults); - m_storage->set_transport_security_state(new net::TransportSecurityState()); - - m_storage->set_http_auth_handler_factory( - net::HttpAuthHandlerFactory::CreateDefault(host_resolver.get())); - m_storage->set_http_server_properties(scoped_ptr<net::HttpServerProperties>(new net::HttpServerPropertiesImpl)); - - net::HttpCache::DefaultBackend* main_backend; - if (m_browserContext->IsOffTheRecord()) { - main_backend = - new net::HttpCache::DefaultBackend( - net::MEMORY_CACHE, - net::CACHE_BACKEND_DEFAULT, - base::FilePath(), - 0, - BrowserThread::GetMessageLoopProxyForThread( - BrowserThread::CACHE)); - } else { - base::FilePath cache_path = m_browserContext->GetCachePath().Append(FILE_PATH_LITERAL("Cache")); - main_backend = - new net::HttpCache::DefaultBackend( - net::DISK_CACHE, - net::CACHE_BACKEND_DEFAULT, - cache_path, - 0, - BrowserThread::GetMessageLoopProxyForThread( - BrowserThread::CACHE)); - } - - net::HttpNetworkSession::Params network_session_params; - network_session_params.transport_security_state = - m_urlRequestContext->transport_security_state(); - network_session_params.cert_verifier = - m_urlRequestContext->cert_verifier(); - network_session_params.server_bound_cert_service = - m_urlRequestContext->server_bound_cert_service(); - network_session_params.proxy_service = - m_urlRequestContext->proxy_service(); - network_session_params.ssl_config_service = - m_urlRequestContext->ssl_config_service(); - network_session_params.http_auth_handler_factory = - m_urlRequestContext->http_auth_handler_factory(); - network_session_params.network_delegate = - m_networkDelegate.get(); - network_session_params.http_server_properties = - m_urlRequestContext->http_server_properties(); - network_session_params.ignore_certificate_errors = - m_ignoreCertificateErrors; - - // Give |m_storage| ownership at the end in case it's |mapped_host_resolver|. - m_storage->set_host_resolver(host_resolver.Pass()); - network_session_params.host_resolver = - m_urlRequestContext->host_resolver(); - - net::HttpCache* main_cache = new net::HttpCache( - network_session_params, main_backend); - m_storage->set_http_transaction_factory(main_cache); - - - m_jobFactory.reset(new net::URLRequestJobFactoryImpl()); - - // Chromium has a few protocol handlers ready for us, only pick blob: and throw away the rest. - content::ProtocolHandlerMap::iterator it = m_protocolHandlers.find(url::kBlobScheme); - Q_ASSERT(it != m_protocolHandlers.end()); - m_jobFactory->SetProtocolHandler(it->first, it->second.release()); - m_protocolHandlers.clear(); - - m_jobFactory->SetProtocolHandler(url::kDataScheme, new net::DataProtocolHandler()); - m_jobFactory->SetProtocolHandler(url::kFileScheme, new net::FileProtocolHandler( - content::BrowserThread::GetBlockingPool()->GetTaskRunnerWithShutdownBehavior(base::SequencedWorkerPool::SKIP_ON_SHUTDOWN))); - m_jobFactory->SetProtocolHandler(kQrcSchemeQt, new QrcProtocolHandlerQt()); - m_jobFactory->SetProtocolHandler(url::kFtpScheme, new net::FtpProtocolHandler( - new net::FtpNetworkLayer(m_urlRequestContext->host_resolver()))); - m_urlRequestContext->set_job_factory(m_jobFactory.get()); + generateStorage(); + generateJobFactory(); } return m_urlRequestContext.get(); } +void URLRequestContextGetterQt::updateStorageSettings() +{ + Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + if (!m_proxyConfigService) { + // We must create the proxy config service on the UI loop on Linux because it + // must synchronously run on the glib message loop. This will be passed to + // the URLRequestContextStorage on the IO thread in GetURLRequestContext(). + m_proxyConfigService.reset(net::ProxyService::CreateSystemProxyConfigService( + BrowserThread::UnsafeGetMessageLoopForThread(BrowserThread::IO)->message_loop_proxy(), + BrowserThread::UnsafeGetMessageLoopForThread(BrowserThread::FILE)) + ); + } + if (m_storage && !m_updateStorageSettings) { + m_updateStorageSettings = true; + content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE, base::Bind(&URLRequestContextGetterQt::generateStorage, this)); + } +} + +void URLRequestContextGetterQt::generateStorage() +{ + Q_ASSERT(m_urlRequestContext); + Q_ASSERT(m_proxyConfigService); + m_updateStorageSettings = false; + + m_storage.reset(new net::URLRequestContextStorage(m_urlRequestContext.get())); + + generateCookieStore(); + generateUserAgent(); + + m_storage->set_server_bound_cert_service(new net::ServerBoundCertService( + new net::DefaultServerBoundCertStore(NULL), + base::WorkerPool::GetTaskRunner(true))); + + m_storage->set_cert_verifier(net::CertVerifier::CreateDefault()); + m_storage->set_proxy_service(net::ProxyService::CreateUsingSystemProxyResolver( + m_proxyConfigService.release(), 0, NULL)); + m_storage->set_ssl_config_service(new net::SSLConfigServiceDefaults); + m_storage->set_transport_security_state(new net::TransportSecurityState()); + + scoped_ptr<net::HostResolver> host_resolver(net::HostResolver::CreateDefaultResolver(NULL)); + m_storage->set_http_auth_handler_factory(net::HttpAuthHandlerFactory::CreateDefault(host_resolver.get())); + m_storage->set_http_server_properties(scoped_ptr<net::HttpServerProperties>(new net::HttpServerPropertiesImpl)); + + // Give |m_storage| ownership at the end in case it's |mapped_host_resolver|. + m_storage->set_host_resolver(host_resolver.Pass()); + + generateHttpCache(); +} + +void URLRequestContextGetterQt::updateCookieStore() +{ + if (m_urlRequestContext && !m_updateCookieStore && !m_updateStorageSettings) { + m_updateCookieStore = true; + content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE, base::Bind(&URLRequestContextGetterQt::generateCookieStore, this)); + } +} + +void URLRequestContextGetterQt::generateCookieStore() +{ + Q_ASSERT(m_urlRequestContext); + Q_ASSERT(m_storage); + m_updateCookieStore = false; + + // Unset it first to get a chance to destroy and flush the old cookie store before before opening a new on possibly the same file. + m_storage->set_cookie_store(0); + + net::CookieStore* cookieStore = 0; + switch (m_browserContext->persistentCookiesPolicy()) { + case BrowserContextAdapter::NoPersistentCookies: + cookieStore = + content::CreateCookieStore(content::CookieStoreConfig( + base::FilePath(), + content::CookieStoreConfig::EPHEMERAL_SESSION_COOKIES, + NULL, NULL) + ); + break; + case BrowserContextAdapter::AllowPersistentCookies: + cookieStore = + content::CreateCookieStore(content::CookieStoreConfig( + base::FilePath(toFilePathString(m_browserContext->cookiesPath())), + content::CookieStoreConfig::PERSISTANT_SESSION_COOKIES, + NULL, NULL) + ); + break; + case BrowserContextAdapter::ForcePersistentCookies: + cookieStore = + content::CreateCookieStore(content::CookieStoreConfig( + base::FilePath(toFilePathString(m_browserContext->cookiesPath())), + content::CookieStoreConfig::RESTORED_SESSION_COOKIES, + NULL, NULL) + ); + break; + } + m_storage->set_cookie_store(cookieStore); +} + +void URLRequestContextGetterQt::updateUserAgent() +{ + if (m_urlRequestContext && !m_updateStorageSettings) + content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE, base::Bind(&URLRequestContextGetterQt::generateUserAgent, this)); +} + +void URLRequestContextGetterQt::generateUserAgent() +{ + Q_ASSERT(m_urlRequestContext); + Q_ASSERT(m_storage); + + m_storage->set_http_user_agent_settings( + new net::StaticHttpUserAgentSettings("en-us,en", m_browserContext->httpUserAgent().toStdString())); +} + +void URLRequestContextGetterQt::updateHttpCache() +{ + if (m_urlRequestContext && !m_updateHttpCache && !m_updateStorageSettings) { + m_updateHttpCache = true; + content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE, base::Bind(&URLRequestContextGetterQt::generateHttpCache, this)); + } +} + +void URLRequestContextGetterQt::generateHttpCache() +{ + Q_ASSERT(m_urlRequestContext); + Q_ASSERT(m_storage); + m_updateHttpCache = false; + + net::HttpCache::DefaultBackend* main_backend = 0; + switch (m_browserContext->httpCacheType()) { + case BrowserContextAdapter::MemoryHttpCache: + main_backend = + new net::HttpCache::DefaultBackend( + net::MEMORY_CACHE, + net::CACHE_BACKEND_DEFAULT, + base::FilePath(), + m_browserContext->httpCacheMaxSize(), + BrowserThread::GetMessageLoopProxyForThread(BrowserThread::CACHE) + ); + break; + case BrowserContextAdapter::DiskHttpCache: + main_backend = + new net::HttpCache::DefaultBackend( + net::DISK_CACHE, + net::CACHE_BACKEND_DEFAULT, + base::FilePath(toFilePathString(m_browserContext->httpCachePath())), + m_browserContext->httpCacheMaxSize(), + BrowserThread::GetMessageLoopProxyForThread(BrowserThread::CACHE) + ); + break; + } + + net::HttpNetworkSession::Params network_session_params; + network_session_params.transport_security_state = m_urlRequestContext->transport_security_state(); + network_session_params.cert_verifier = m_urlRequestContext->cert_verifier(); + network_session_params.server_bound_cert_service = m_urlRequestContext->server_bound_cert_service(); + network_session_params.proxy_service = m_urlRequestContext->proxy_service(); + network_session_params.ssl_config_service = m_urlRequestContext->ssl_config_service(); + network_session_params.http_auth_handler_factory = m_urlRequestContext->http_auth_handler_factory(); + network_session_params.network_delegate = m_networkDelegate.get(); + network_session_params.http_server_properties = m_urlRequestContext->http_server_properties(); + network_session_params.ignore_certificate_errors = m_ignoreCertificateErrors; + network_session_params.host_resolver = m_urlRequestContext->host_resolver(); + + m_storage->set_http_transaction_factory(new net::HttpCache(network_session_params, main_backend)); +} + +void URLRequestContextGetterQt::generateJobFactory() +{ + Q_ASSERT(m_urlRequestContext); + Q_ASSERT(!m_jobFactory); + m_jobFactory.reset(new net::URLRequestJobFactoryImpl()); + + // Chromium has a few protocol handlers ready for us, only pick blob: and throw away the rest. + content::ProtocolHandlerMap::iterator it = m_protocolHandlers.find(url::kBlobScheme); + Q_ASSERT(it != m_protocolHandlers.end()); + m_jobFactory->SetProtocolHandler(it->first, it->second.release()); + m_protocolHandlers.clear(); + + m_jobFactory->SetProtocolHandler(url::kDataScheme, new net::DataProtocolHandler()); + m_jobFactory->SetProtocolHandler(url::kFileScheme, new net::FileProtocolHandler( + content::BrowserThread::GetBlockingPool()->GetTaskRunnerWithShutdownBehavior( + base::SequencedWorkerPool::SKIP_ON_SHUTDOWN))); + m_jobFactory->SetProtocolHandler(kQrcSchemeQt, new QrcProtocolHandlerQt()); + m_jobFactory->SetProtocolHandler(url::kFtpScheme, + new net::FtpProtocolHandler(new net::FtpNetworkLayer(m_urlRequestContext->host_resolver()))); + + m_urlRequestContext->set_job_factory(m_jobFactory.get()); +} scoped_refptr<base::SingleThreadTaskRunner> URLRequestContextGetterQt::GetNetworkTaskRunner() const { diff --git a/src/core/url_request_context_getter_qt.h b/src/core/url_request_context_getter_qt.h index 2c42322bd..5f6048403 100644 --- a/src/core/url_request_context_getter_qt.h +++ b/src/core/url_request_context_getter_qt.h @@ -40,6 +40,7 @@ #include "net/url_request/url_request_context_getter.h" #include "base/files/file_path.h" +#include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" #include "base/single_thread_task_runner.h" #include "content/public/browser/content_browser_client.h" @@ -50,26 +51,41 @@ #include "qglobal.h" namespace net { -class HostResolver; class MappedHostResolver; class NetworkDelegate; class ProxyConfigService; } -class BrowserContextQt; +class BrowserContextAdapter; class URLRequestContextGetterQt : public net::URLRequestContextGetter { public: - explicit URLRequestContextGetterQt(BrowserContextQt *browserContext, content::ProtocolHandlerMap *protocolHandlers); + explicit URLRequestContextGetterQt(BrowserContextAdapter *browserContext, content::ProtocolHandlerMap *protocolHandlers); virtual net::URLRequestContext *GetURLRequestContext() Q_DECL_OVERRIDE; virtual scoped_refptr<base::SingleThreadTaskRunner> GetNetworkTaskRunner() const Q_DECL_OVERRIDE; + // Called on the UI thread: + void updateStorageSettings(); + void updateUserAgent(); + void updateCookieStore(); + void updateHttpCache(); + private: virtual ~URLRequestContextGetterQt() {} + // Called on the IO thread: + void generateStorage(); + void generateCookieStore(); + void generateHttpCache(); + void generateUserAgent(); + void generateJobFactory(); + bool m_ignoreCertificateErrors; - BrowserContextQt *m_browserContext; + volatile bool m_updateStorageSettings; + volatile bool m_updateCookieStore; + volatile bool m_updateHttpCache; + BrowserContextAdapter *m_browserContext; content::ProtocolHandlerMap m_protocolHandlers; scoped_ptr<net::ProxyConfigService> m_proxyConfigService; diff --git a/src/core/web_contents_adapter.cpp b/src/core/web_contents_adapter.cpp index 678b558c1..0b1aba1cf 100644 --- a/src/core/web_contents_adapter.cpp +++ b/src/core/web_contents_adapter.cpp @@ -347,10 +347,13 @@ void WebContentsAdapter::initialize(WebContentsAdapterClient *adapterClient) { Q_D(WebContentsAdapter); d->adapterClient = adapterClient; + // We keep a reference to browserContextAdapter to keep it alive as long as we use it. + // This is needed in case the QML WebEngineProfile is garbage collected before the WebEnginePage. + d->browserContextAdapter = adapterClient->browserContextAdapter(); // Create our own if a WebContents wasn't provided at construction. if (!d->webContents) - d->webContents.reset(createBlankWebContents(adapterClient, adapterClient->browserContextAdapter()->browserContext())); + d->webContents.reset(createBlankWebContents(adapterClient, d->browserContextAdapter->browserContext())); // This might replace any adapter that has been initialized with this WebEngineSettings. adapterClient->webEngineSettings()->setWebContentsAdapter(this); @@ -631,7 +634,7 @@ void WebContentsAdapter::enableInspector(bool enable) BrowserContextQt* WebContentsAdapter::browserContext() { Q_D(WebContentsAdapter); - return static_cast<BrowserContextQt*>(d->webContents->GetBrowserContext()); + return d->browserContextAdapter->browserContext(); } QAccessibleInterface *WebContentsAdapter::browserAccessible() diff --git a/src/core/web_contents_adapter_p.h b/src/core/web_contents_adapter_p.h index 28df0113a..f47c05de0 100644 --- a/src/core/web_contents_adapter_p.h +++ b/src/core/web_contents_adapter_p.h @@ -42,6 +42,9 @@ #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" +#include <QExplicitlySharedDataPointer> + +class BrowserContextAdapter; class QtRenderViewObserverHost; class WebContentsAdapterClient; class WebContentsDelegateQt; @@ -52,6 +55,7 @@ public: WebContentsAdapterPrivate(); ~WebContentsAdapterPrivate(); scoped_refptr<WebEngineContext> engineContext; + QExplicitlySharedDataPointer<BrowserContextAdapter> browserContextAdapter; scoped_ptr<content::WebContents> webContents; scoped_ptr<WebContentsDelegateQt> webContentsDelegate; scoped_ptr<QtRenderViewObserverHost> renderViewObserverHost; diff --git a/src/core/web_engine_context.cpp b/src/core/web_engine_context.cpp index b17ee124c..6f335d2fc 100644 --- a/src/core/web_engine_context.cpp +++ b/src/core/web_engine_context.cpp @@ -142,15 +142,15 @@ scoped_refptr<WebEngineContext> WebEngineContext::current() BrowserContextAdapter* WebEngineContext::defaultBrowserContext() { if (!m_defaultBrowserContext) - m_defaultBrowserContext.reset(new BrowserContextAdapter(QStringLiteral("Default"), false)); - return m_defaultBrowserContext.get(); + m_defaultBrowserContext = new BrowserContextAdapter(QStringLiteral("Default")); + return m_defaultBrowserContext.data(); } BrowserContextAdapter* WebEngineContext::offTheRecordBrowserContext() { if (!m_offTheRecordBrowserContext) - m_offTheRecordBrowserContext.reset(new BrowserContextAdapter(QStringLiteral("OTR"), true)); - return m_offTheRecordBrowserContext.get(); + m_offTheRecordBrowserContext = new BrowserContextAdapter(true); + return m_offTheRecordBrowserContext.data(); } #ifndef CHROMIUM_VERSION diff --git a/src/core/web_engine_context.h b/src/core/web_engine_context.h index 0b3ad8678..a44a48d3a 100644 --- a/src/core/web_engine_context.h +++ b/src/core/web_engine_context.h @@ -40,6 +40,8 @@ #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" +#include <QExplicitlySharedDataPointer> + namespace base { class RunLoop; } @@ -72,8 +74,8 @@ private: #if defined(OS_ANDROID) scoped_ptr<SurfaceFactoryQt> m_surfaceFactory; #endif - scoped_ptr<BrowserContextAdapter> m_defaultBrowserContext; - scoped_ptr<BrowserContextAdapter> m_offTheRecordBrowserContext; + QExplicitlySharedDataPointer<BrowserContextAdapter> m_defaultBrowserContext; + QExplicitlySharedDataPointer<BrowserContextAdapter> m_offTheRecordBrowserContext; }; #endif // WEB_ENGINE_CONTEXT_H |