summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichal Klocek <michal.klocek@qt.io>2018-04-20 13:44:15 +0200
committerMichal Klocek <michal.klocek@qt.io>2018-05-25 08:30:20 +0000
commitaf313cb881610fedb04c9d486597462e6b3c8e12 (patch)
treed0573f374b926c8e7df8f87bcda8eb5754ee68cf
parent6c319ced199772c89a6c2cee46e551bb36c50360 (diff)
Refactor out ProfileIODataQt
Currently we can crash due to use-after-free of browser context, it happens due to fact that resource context has pointer to browser context which is destroyed on ui thread, while resource context is destroyed on io thread. We used url request getter to maintain objects destruction on io thread. Refactor the code and create profile io data, which will live on io thread, move all the objects currently maintained by url request getter qt to newly created class. Fix destruction order and remove references to browser context from resource context. Compared to url request getter, profile io data is not ref counted class and uses weak pointer factory to handle all "generate" requests. Task-number: QTBUG-67865 Change-Id: Iee4fec854eda1c1600d26e991657d4877cbc966f Reviewed-by: Jüri Valdmann <juri.valdmann@qt.io>
-rw-r--r--src/core/browser_context_adapter.cpp66
-rw-r--r--src/core/core_chromium.pri2
-rw-r--r--src/core/net/network_delegate_qt.cpp18
-rw-r--r--src/core/net/network_delegate_qt.h6
-rw-r--r--src/core/net/url_request_context_getter_qt.cpp582
-rw-r--r--src/core/net/url_request_context_getter_qt.h98
-rw-r--r--src/core/profile_io_data_qt.cpp658
-rw-r--r--src/core/profile_io_data_qt.h145
-rw-r--r--src/core/profile_qt.cpp56
-rw-r--r--src/core/profile_qt.h13
-rw-r--r--src/core/resource_context_qt.cpp18
-rw-r--r--src/core/resource_context_qt.h18
12 files changed, 914 insertions, 766 deletions
diff --git a/src/core/browser_context_adapter.cpp b/src/core/browser_context_adapter.cpp
index 4db9ec8b9..ecf9bdbc2 100644
--- a/src/core/browser_context_adapter.cpp
+++ b/src/core/browser_context_adapter.cpp
@@ -78,48 +78,42 @@ namespace QtWebEngineCore {
BrowserContextAdapter::BrowserContextAdapter(bool offTheRecord):
m_offTheRecord(offTheRecord)
- , m_browserContext(new ProfileQt(this))
, m_httpCacheType(DiskHttpCache)
, m_persistentCookiesPolicy(AllowPersistentCookies)
, m_visitedLinksPolicy(TrackVisitedLinksOnDisk)
, m_httpCacheMaxSize(0)
{
WebEngineContext::current()->addBrowserContext(this);
- // Mark the context as live. This prevents the use-after-free DCHECK in
- // AssertBrowserContextWasntDestroyed from being triggered when a new
- // BrowserContextQt object is allocated at the same address as a previously
- // destroyed one. Needs to be called after WebEngineContext initialization.
- BrowserContextDependencyManager::GetInstance()->MarkBrowserContextLive(m_browserContext.data());
+ // creation of profile requires webengine context
+ m_browserContext.reset(new ProfileQt(this));
content::BrowserContext::Initialize(m_browserContext.data(), toFilePath(dataPath()));
+ // fixme: this should not be here
+ m_browserContext->m_profileIOData->initializeOnUIThread();
}
BrowserContextAdapter::BrowserContextAdapter(const QString &storageName):
m_name(storageName)
, m_offTheRecord(false)
- , m_browserContext(new ProfileQt(this))
, m_httpCacheType(DiskHttpCache)
, m_persistentCookiesPolicy(AllowPersistentCookies)
, m_visitedLinksPolicy(TrackVisitedLinksOnDisk)
, m_httpCacheMaxSize(0)
{
WebEngineContext::current()->addBrowserContext(this);
- // Mark the context as live. This prevents the use-after-free DCHECK in
- // AssertBrowserContextWasntDestroyed from being triggered when a new
- // BrowserContextQt object is allocated at the same address as a previously
- // destroyed one. Needs to be called after WebEngineContext initialization.
- BrowserContextDependencyManager::GetInstance()->MarkBrowserContextLive(m_browserContext.data());
+ // creation of profile requires webengine context
+ m_browserContext.reset(new ProfileQt(this));
content::BrowserContext::Initialize(m_browserContext.data(), toFilePath(dataPath()));
+ // fixme: this should not be here
+ m_browserContext->m_profileIOData->initializeOnUIThread();
}
BrowserContextAdapter::~BrowserContextAdapter()
{
WebEngineContext::current()->removeBrowserContext(this);
- m_browserContext->ShutdownStoragePartitions();
if (m_downloadManagerDelegate) {
m_browserContext->GetDownloadManager(m_browserContext.data())->Shutdown();
m_downloadManagerDelegate.reset();
}
- BrowserContextDependencyManager::GetInstance()->DestroyBrowserContextServices(m_browserContext.data());
}
void BrowserContextAdapter::setStorageName(const QString &storageName)
@@ -128,8 +122,8 @@ void BrowserContextAdapter::setStorageName(const QString &storageName)
return;
m_name = storageName;
if (!m_offTheRecord) {
- if (m_browserContext->url_request_getter_.get())
- m_browserContext->url_request_getter_->updateStorageSettings();
+ if (m_browserContext->m_urlRequestContextGetter.get())
+ m_browserContext->m_profileIOData->updateStorageSettings();
if (m_visitedLinksManager)
resetVisitedLinksManager();
}
@@ -140,8 +134,8 @@ void BrowserContextAdapter::setOffTheRecord(bool offTheRecord)
if (offTheRecord == m_offTheRecord)
return;
m_offTheRecord = offTheRecord;
- if (m_browserContext->url_request_getter_.get())
- m_browserContext->url_request_getter_->updateStorageSettings();
+ if (m_browserContext->m_urlRequestContextGetter.get())
+ m_browserContext->m_profileIOData->updateStorageSettings();
if (m_visitedLinksManager)
resetVisitedLinksManager();
}
@@ -182,8 +176,8 @@ void BrowserContextAdapter::setRequestInterceptor(QWebEngineUrlRequestIntercepto
if (m_requestInterceptor == interceptor)
return;
m_requestInterceptor = interceptor;
- if (m_browserContext->url_request_getter_.get())
- m_browserContext->url_request_getter_->updateRequestInterceptor();
+ if (m_browserContext->m_urlRequestContextGetter.get())
+ m_browserContext->m_profileIOData->updateRequestInterceptor();
}
void BrowserContextAdapter::addClient(BrowserContextAdapterClient *adapterClient)
@@ -238,8 +232,8 @@ void BrowserContextAdapter::setDataPath(const QString &path)
return;
m_dataPath = path;
if (!m_offTheRecord) {
- if (m_browserContext->url_request_getter_.get())
- m_browserContext->url_request_getter_->updateStorageSettings();
+ if (m_browserContext->m_urlRequestContextGetter.get())
+ m_browserContext->m_profileIOData->updateStorageSettings();
if (m_visitedLinksManager)
resetVisitedLinksManager();
}
@@ -261,8 +255,8 @@ void BrowserContextAdapter::setCachePath(const QString &path)
if (m_cachePath == path)
return;
m_cachePath = path;
- if (!m_offTheRecord && m_browserContext->url_request_getter_.get())
- m_browserContext->url_request_getter_->updateHttpCache();
+ if (!m_offTheRecord && m_browserContext->m_urlRequestContextGetter.get())
+ m_browserContext->m_profileIOData->updateHttpCache();
}
QString BrowserContextAdapter::cookiesPath() const
@@ -318,8 +312,8 @@ void BrowserContextAdapter::setHttpUserAgent(const QString &userAgent)
if (web_contents->GetBrowserContext() == m_browserContext.data())
web_contents->SetUserAgentOverride(m_httpUserAgent.toStdString());
- if (m_browserContext->url_request_getter_.get())
- m_browserContext->url_request_getter_->updateUserAgent();
+ if (m_browserContext->m_urlRequestContextGetter.get())
+ m_browserContext->m_profileIOData->updateUserAgent();
}
BrowserContextAdapter::HttpCacheType BrowserContextAdapter::httpCacheType() const
@@ -337,8 +331,8 @@ void BrowserContextAdapter::setHttpCacheType(BrowserContextAdapter::HttpCacheTyp
m_httpCacheType = newhttpCacheType;
if (oldCacheType == httpCacheType())
return;
- if (!m_offTheRecord && m_browserContext->url_request_getter_.get())
- m_browserContext->url_request_getter_->updateHttpCache();
+ if (!m_offTheRecord && m_browserContext->m_urlRequestContextGetter.get())
+ m_browserContext->m_profileIOData->updateHttpCache();
}
BrowserContextAdapter::PersistentCookiesPolicy BrowserContextAdapter::persistentCookiesPolicy() const
@@ -354,8 +348,8 @@ void BrowserContextAdapter::setPersistentCookiesPolicy(BrowserContextAdapter::Pe
m_persistentCookiesPolicy = newPersistentCookiesPolicy;
if (oldPolicy == persistentCookiesPolicy())
return;
- if (!m_offTheRecord && m_browserContext->url_request_getter_.get())
- m_browserContext->url_request_getter_->updateCookieStore();
+ if (!m_offTheRecord && m_browserContext->m_urlRequestContextGetter.get())
+ m_browserContext->m_profileIOData->updateCookieStore();
}
BrowserContextAdapter::VisitedLinksPolicy BrowserContextAdapter::visitedLinksPolicy() const
@@ -409,8 +403,8 @@ void BrowserContextAdapter::setHttpCacheMaxSize(int maxSize)
if (m_httpCacheMaxSize == maxSize)
return;
m_httpCacheMaxSize = maxSize;
- if (!m_offTheRecord && m_browserContext->url_request_getter_.get())
- m_browserContext->url_request_getter_->updateHttpCache();
+ if (!m_offTheRecord && m_browserContext->m_urlRequestContextGetter.get())
+ m_browserContext->m_profileIOData->updateHttpCache();
}
const QHash<QByteArray, QWebEngineUrlSchemeHandler *> &BrowserContextAdapter::customUrlSchemeHandlers() const
@@ -425,8 +419,8 @@ const QList<QByteArray> BrowserContextAdapter::customUrlSchemes() const
void BrowserContextAdapter::updateCustomUrlSchemeHandlers()
{
- if (m_browserContext->url_request_getter_.get())
- m_browserContext->url_request_getter_->updateJobFactory();
+ if (m_browserContext->m_urlRequestContextGetter.get())
+ m_browserContext->m_profileIOData->updateJobFactory();
}
bool BrowserContextAdapter::removeCustomUrlSchemeHandler(QWebEngineUrlSchemeHandler *handler)
@@ -515,8 +509,8 @@ void BrowserContextAdapter::setHttpAcceptLanguage(const QString &httpAcceptLangu
}
}
- if (m_browserContext->url_request_getter_.get())
- m_browserContext->url_request_getter_->updateUserAgent();
+ if (m_browserContext->m_urlRequestContextGetter.get())
+ m_browserContext->m_profileIOData->updateUserAgent();
}
void BrowserContextAdapter::clearHttpCache()
diff --git a/src/core/core_chromium.pri b/src/core/core_chromium.pri
index 31dbd7586..94d3e9624 100644
--- a/src/core/core_chromium.pri
+++ b/src/core/core_chromium.pri
@@ -89,6 +89,7 @@ SOURCES = \
permission_manager_qt.cpp \
process_main.cpp \
profile_qt.cpp \
+ profile_io_data_qt.cpp \
quota_permission_context_qt.cpp \
quota_request_controller_impl.cpp \
register_protocol_handler_request_controller_impl.cpp \
@@ -175,6 +176,7 @@ HEADERS = \
permission_manager_qt.h \
process_main.h \
profile_qt.h \
+ profile_io_data_qt.h \
proxy_config_service_qt.h \
quota_permission_context_qt.h \
quota_request_controller.h \
diff --git a/src/core/net/network_delegate_qt.cpp b/src/core/net/network_delegate_qt.cpp
index 74db51d7d..2373fa180 100644
--- a/src/core/net/network_delegate_qt.cpp
+++ b/src/core/net/network_delegate_qt.cpp
@@ -45,7 +45,7 @@
#include "content/public/browser/resource_request_info.h"
#include "cookie_monster_delegate_qt.h"
#include "ui/base/page_transition_types.h"
-#include "url_request_context_getter_qt.h"
+#include "profile_io_data_qt.h"
#include "net/base/load_flags.h"
#include "net/url_request/url_request.h"
#include "qwebengineurlrequestinfo.h"
@@ -202,15 +202,15 @@ const char URLRequestNotification::UserData::key[] = "QtWebEngineCore::URLReques
} // namespace
-NetworkDelegateQt::NetworkDelegateQt(URLRequestContextGetterQt *requestContext)
- : m_requestContextGetter(requestContext)
+NetworkDelegateQt::NetworkDelegateQt(ProfileIODataQt *data)
+ : m_profileIOData(data)
{
}
int NetworkDelegateQt::OnBeforeURLRequest(net::URLRequest *request, const net::CompletionCallback &callback, GURL *newUrl)
{
Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
- Q_ASSERT(m_requestContextGetter);
+ Q_ASSERT(m_profileIOData);
const content::ResourceRequestInfo *resourceInfo = content::ResourceRequestInfo::ForRequest(request);
@@ -224,7 +224,7 @@ int NetworkDelegateQt::OnBeforeURLRequest(net::URLRequest *request, const net::C
const QUrl qUrl = toQt(request->url());
- QWebEngineUrlRequestInterceptor* interceptor = m_requestContextGetter->m_requestInterceptor;
+ QWebEngineUrlRequestInterceptor* interceptor = m_profileIOData->m_requestInterceptor;
if (interceptor) {
QWebEngineUrlRequestInfoPrivate *infoPrivate = new QWebEngineUrlRequestInfoPrivate(toQt(resourceType),
toQt(navigationType),
@@ -298,14 +298,14 @@ bool NetworkDelegateQt::OnCanEnablePrivacyMode(const GURL &url, const GURL &site
bool NetworkDelegateQt::canSetCookies(const GURL &first_party, const GURL &url, const std::string &cookie_line) const
{
- Q_ASSERT(m_requestContextGetter);
- return m_requestContextGetter->m_cookieDelegate->canSetCookie(toQt(first_party), QByteArray::fromStdString(cookie_line), toQt(url));
+ Q_ASSERT(m_profileIOData);
+ return m_profileIOData->m_cookieDelegate->canSetCookie(toQt(first_party), QByteArray::fromStdString(cookie_line), toQt(url));
}
bool NetworkDelegateQt::canGetCookies(const GURL &first_party, const GURL &url) const
{
- Q_ASSERT(m_requestContextGetter);
- return m_requestContextGetter->m_cookieDelegate->canGetCookies(toQt(first_party), toQt(url));
+ Q_ASSERT(m_profileIOData);
+ return m_profileIOData->m_cookieDelegate->canGetCookies(toQt(first_party), toQt(url));
}
int NetworkDelegateQt::OnBeforeStartTransaction(net::URLRequest *request, const net::CompletionCallback &callback, net::HttpRequestHeaders *headers)
diff --git a/src/core/net/network_delegate_qt.h b/src/core/net/network_delegate_qt.h
index b5165d229..4677fc158 100644
--- a/src/core/net/network_delegate_qt.h
+++ b/src/core/net/network_delegate_qt.h
@@ -52,12 +52,12 @@ class WebContents;
namespace QtWebEngineCore {
-class URLRequestContextGetterQt;
+class ProfileIODataQt;
class NetworkDelegateQt : public net::NetworkDelegate {
- URLRequestContextGetterQt *m_requestContextGetter;
+ ProfileIODataQt *m_profileIOData;
public:
- NetworkDelegateQt(URLRequestContextGetterQt *requestContext);
+ NetworkDelegateQt(ProfileIODataQt *data);
// net::NetworkDelegate implementation
int OnBeforeURLRequest(net::URLRequest* request, const net::CompletionCallback& callback, GURL* newUrl) override;
diff --git a/src/core/net/url_request_context_getter_qt.cpp b/src/core/net/url_request_context_getter_qt.cpp
index 56b31c7fa..636d27358 100644
--- a/src/core/net/url_request_context_getter_qt.cpp
+++ b/src/core/net/url_request_context_getter_qt.cpp
@@ -38,597 +38,23 @@
****************************************************************************/
#include "url_request_context_getter_qt.h"
-
-#include "base/memory/ptr_util.h"
-#include "base/task_scheduler/post_task.h"
-#include "base/threading/sequenced_worker_pool.h"
-#include "chrome/browser/custom_handlers/protocol_handler_registry_factory.h"
-#include "chrome/browser/net/chrome_mojo_proxy_resolver_factory.h"
-#include "content/network/proxy_service_mojo.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/browsing_data_remover.h"
-#include "content/public/browser/cookie_store_factory.h"
-#include "content/public/common/content_features.h"
-#include "content/public/common/content_switches.h"
-#include "net/base/cache_type.h"
-#include "net/cert/cert_verifier.h"
-#include "net/cert/ct_known_logs.h"
-#include "net/cert/ct_log_verifier.h"
-#include "net/cert/ct_policy_enforcer.h"
-#include "net/cert/multi_log_ct_verifier.h"
-#include "net/dns/host_resolver.h"
-#include "net/dns/mapped_host_resolver.h"
-#include "net/extras/sqlite/sqlite_channel_id_store.h"
-#include "net/http/http_auth_handler_factory.h"
-#include "net/http/http_auth_preferences.h"
-#include "net/http/http_auth_scheme.h"
-#include "net/http/http_cache.h"
-#include "net/http/http_server_properties_impl.h"
-#include "net/proxy/proxy_script_fetcher_impl.h"
-#include "net/proxy/proxy_service.h"
-#include "net/ssl/channel_id_service.h"
-#include "net/ssl/default_channel_id_store.h"
-#include "net/ssl/ssl_config_service_defaults.h"
-#include "net/url_request/static_http_user_agent_settings.h"
-#include "net/url_request/url_request_context.h"
-#include "net/url_request/data_protocol_handler.h"
-#include "net/url_request/file_protocol_handler.h"
-#include "net/url_request/ftp_protocol_handler.h"
-#include "net/url_request/url_request_intercepting_job_factory.h"
-#include "net/ftp/ftp_network_layer.h"
-
-#include "api/qwebengineurlschemehandler.h"
-#include "custom_protocol_handler.h"
-#include "profile_qt.h"
-#include "proxy_config_service_qt.h"
-#include "qrc_protocol_handler_qt.h"
-#include "qwebenginecookiestore.h"
-#include "qwebenginecookiestore_p.h"
-#include "type_conversion.h"
+#include "profile_io_data_qt.h"
namespace QtWebEngineCore {
-using content::BrowserThread;
-
-URLRequestContextGetterQt::URLRequestContextGetterQt(BrowserContextAdapter *browserContext,
- content::ProtocolHandlerMap *protocolHandlers,
- content::URLRequestInterceptorScopedVector request_interceptors)
- : m_ignoreCertificateErrors(false)
- , m_mutex(QMutex::Recursive)
- , m_contextInitialized(false)
- , m_updateAllStorage(false)
- , m_updateCookieStore(false)
- , m_updateHttpCache(false)
- , m_updateJobFactory(true)
- , m_updateUserAgent(false)
- , m_browserContextAdapter(browserContext)
- , m_baseJobFactory(0)
- , m_cookieDelegate(new CookieMonsterDelegateQt())
- , m_requestInterceptors(std::move(request_interceptors))
+URLRequestContextGetterQt::URLRequestContextGetterQt(ProfileIODataQt *data)
+ : m_profileIOData(data)
{
- std::swap(m_protocolHandlers, *protocolHandlers);
-
- // The ProtocolHandlerRegistry and it's JobInterceptorFactory need to be
- // created on the UI thread:
- ProtocolHandlerRegistry* protocolHandlerRegistry =
- ProtocolHandlerRegistryFactory::GetForBrowserContext(browserContext->browserContext());
- DCHECK(protocolHandlerRegistry);
- m_protocolHandlerInterceptor =
- protocolHandlerRegistry->CreateJobInterceptorFactory();
-
- QMutexLocker lock(&m_mutex);
- m_cookieDelegate->setClient(browserContext->cookieStore());
- updateStorageSettings();
}
URLRequestContextGetterQt::~URLRequestContextGetterQt()
{
- m_cookieDelegate->setCookieMonster(0); // this will let CookieMonsterDelegateQt be deleted
- delete m_proxyConfigService.fetchAndStoreAcquire(0);
-}
-
-
-void URLRequestContextGetterQt::setFullConfiguration()
-{
- Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
- m_requestInterceptor = m_browserContextAdapter->requestInterceptor();
- m_persistentCookiesPolicy = m_browserContextAdapter->persistentCookiesPolicy();
- m_cookiesPath = m_browserContextAdapter->cookiesPath();
- m_channelIdPath = m_browserContextAdapter->channelIdPath();
- m_httpAcceptLanguage = m_browserContextAdapter->httpAcceptLanguage();
- m_httpUserAgent = m_browserContextAdapter->httpUserAgent();
- m_httpCacheType = m_browserContextAdapter->httpCacheType();
- m_httpCachePath = m_browserContextAdapter->httpCachePath();
- m_httpCacheMaxSize = m_browserContextAdapter->httpCacheMaxSize();
- m_customUrlSchemes = m_browserContextAdapter->customUrlSchemes();
}
net::URLRequestContext *URLRequestContextGetterQt::GetURLRequestContext()
{
Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
- if (!m_urlRequestContext) {
- m_urlRequestContext.reset(new net::URLRequestContext());
-
- m_networkDelegate.reset(new NetworkDelegateQt(this));
- m_urlRequestContext->set_network_delegate(m_networkDelegate.get());
- m_urlRequestContext->set_enable_brotli(base::FeatureList::IsEnabled(features::kBrotliEncoding));
-
- QMutexLocker lock(&m_mutex);
- generateAllStorage();
- generateJobFactory();
- m_contextInitialized = true;
- }
-
- return m_urlRequestContext.get();
-}
-
-void URLRequestContextGetterQt::updateStorageSettings()
-{
- Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
-
- QMutexLocker lock(&m_mutex);
- setFullConfiguration();
-
- if (!m_updateAllStorage) {
- m_updateAllStorage = true;
- // 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().
- Q_ASSERT(m_proxyConfigService == 0);
- m_proxyConfigService =
- new ProxyConfigServiceQt(
- net::ProxyService::CreateSystemProxyConfigService(
- content::BrowserThread::GetTaskRunnerForThread(BrowserThread::IO)));
- m_proxyResolverFactory = ChromeMojoProxyResolverFactory::CreateWithStrongBinding();
-
- if (m_contextInitialized)
- content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE,
- base::Bind(&URLRequestContextGetterQt::generateAllStorage, this));
- }
-}
-
-void URLRequestContextGetterQt::cancelAllUrlRequests()
-{
- Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
- Q_ASSERT(m_urlRequestContext);
-
- const std::set<const net::URLRequest*> *url_requests = m_urlRequestContext->url_requests();
- std::set<const net::URLRequest*>::const_iterator it = url_requests->begin();
- std::set<const net::URLRequest*>::const_iterator end = url_requests->end();
- for ( ; it != end; ++it) {
- net::URLRequest* request = const_cast<net::URLRequest*>(*it);
- if (request)
- request->Cancel();
- }
-
-}
-
-void URLRequestContextGetterQt::generateAllStorage()
-{
- Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
- QMutexLocker lock(&m_mutex);
- generateStorage();
- generateCookieStore();
- generateUserAgent();
- generateHttpCache();
- m_updateAllStorage = false;
-}
-
-static const char* const kDefaultAuthSchemes[] = { net::kBasicAuthScheme,
- net::kDigestAuthScheme,
-#if defined(USE_KERBEROS) && !defined(OS_ANDROID)
- net::kNegotiateAuthScheme,
-#endif
- net::kNtlmAuthScheme };
-
-void URLRequestContextGetterQt::generateStorage()
-{
- Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
- Q_ASSERT(m_urlRequestContext);
-
- // We must stop all requests before deleting their backends.
- if (m_storage) {
- m_cookieDelegate->setCookieMonster(0);
- m_storage->set_cookie_store(0);
- cancelAllUrlRequests();
- // we need to get rid of dangling pointer due to coming storage deletion
- m_urlRequestContext->set_http_transaction_factory(0);
- m_httpNetworkSession.reset();
- }
-
-
- m_storage.reset(new net::URLRequestContextStorage(m_urlRequestContext.get()));
-
- net::ProxyConfigService *proxyConfigService = m_proxyConfigService.fetchAndStoreAcquire(0);
- Q_ASSERT(proxyConfigService);
-
- m_storage->set_cert_verifier(net::CertVerifier::CreateDefault());
- std::unique_ptr<net::MultiLogCTVerifier> ct_verifier(new net::MultiLogCTVerifier());
- ct_verifier->AddLogs(net::ct::CreateLogVerifiersForKnownLogs());
- m_storage->set_cert_transparency_verifier(std::move(ct_verifier));
- m_storage->set_ct_policy_enforcer(base::WrapUnique(new net::CTPolicyEnforcer));
-
- std::unique_ptr<net::HostResolver> host_resolver(net::HostResolver::CreateDefaultResolver(NULL));
-
- // The System Proxy Resolver has issues on Windows with unconfigured network cards,
- // which is why we want to use the v8 one
- if (!m_dhcpProxyScriptFetcherFactory)
- m_dhcpProxyScriptFetcherFactory.reset(new net::DhcpProxyScriptFetcherFactory);
-
- m_storage->set_proxy_service(content::CreateProxyServiceUsingMojoFactory(
- std::move(m_proxyResolverFactory),
- std::unique_ptr<net::ProxyConfigService>(proxyConfigService),
- std::make_unique<net::ProxyScriptFetcherImpl>(m_urlRequestContext.get()),
- m_dhcpProxyScriptFetcherFactory->Create(m_urlRequestContext.get()),
- host_resolver.get(),
- nullptr /* NetLog */,
- m_networkDelegate.get()));
-
- m_storage->set_ssl_config_service(new net::SSLConfigServiceDefaults);
- m_storage->set_transport_security_state(std::unique_ptr<net::TransportSecurityState>(new net::TransportSecurityState()));
-
- if (!m_httpAuthPreferences) {
- std::vector<std::string> auth_types(std::begin(kDefaultAuthSchemes), std::end(kDefaultAuthSchemes));
- m_httpAuthPreferences.reset(new net::HttpAuthPreferences(auth_types
-#if defined(OS_POSIX) && !defined(OS_ANDROID)
- , std::string() /* gssapi library name */
-#endif
- ));
- }
- m_storage->set_http_auth_handler_factory(net::HttpAuthHandlerRegistryFactory::Create(m_httpAuthPreferences.get(), host_resolver.get()));
- m_storage->set_http_server_properties(std::unique_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(std::move(host_resolver));
-}
-
-void URLRequestContextGetterQt::updateCookieStore()
-{
- Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
- QMutexLocker lock(&m_mutex);
- m_persistentCookiesPolicy = m_browserContextAdapter->persistentCookiesPolicy();
- m_cookiesPath = m_browserContextAdapter->cookiesPath();
- m_channelIdPath = m_browserContextAdapter->channelIdPath();
-
- if (m_contextInitialized && !m_updateAllStorage && !m_updateCookieStore) {
- m_updateCookieStore = true;
- m_updateHttpCache = true;
- content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE,
- base::Bind(&URLRequestContextGetterQt::generateCookieStore, this));
- }
-}
-
-void URLRequestContextGetterQt::generateCookieStore()
-{
- Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
- Q_ASSERT(m_urlRequestContext);
- Q_ASSERT(m_storage);
-
- QMutexLocker lock(&m_mutex);
- m_updateCookieStore = false;
-
- scoped_refptr<net::SQLiteChannelIDStore> channel_id_db;
- if (!m_channelIdPath.isEmpty() && m_persistentCookiesPolicy != BrowserContextAdapter::NoPersistentCookies) {
- channel_id_db = new net::SQLiteChannelIDStore(
- toFilePath(m_channelIdPath),
- base::CreateSequencedTaskRunnerWithTraits(
- {base::MayBlock(), base::TaskPriority::BACKGROUND}));
- }
-
- m_storage->set_channel_id_service(
- base::WrapUnique(new net::ChannelIDService(
- new net::DefaultChannelIDStore(channel_id_db.get()))));
-
- // Unset it first to get a chance to destroy and flush the old cookie store before opening a new on possibly the same file.
- m_cookieDelegate->setCookieMonster(0);
- m_storage->set_cookie_store(0);
-
- std::unique_ptr<net::CookieStore> cookieStore;
- switch (m_persistentCookiesPolicy) {
- case BrowserContextAdapter::NoPersistentCookies:
- cookieStore = content::CreateCookieStore(
- content::CookieStoreConfig(
- base::FilePath(),
- false,
- false,
- nullptr)
- );
- break;
- case BrowserContextAdapter::AllowPersistentCookies:
- cookieStore = content::CreateCookieStore(
- content::CookieStoreConfig(
- toFilePath(m_cookiesPath),
- false,
- true,
- nullptr)
- );
- break;
- case BrowserContextAdapter::ForcePersistentCookies:
- cookieStore = content::CreateCookieStore(
- content::CookieStoreConfig(
- toFilePath(m_cookiesPath),
- true,
- true,
- nullptr)
- );
- break;
- }
-
- net::CookieMonster * const cookieMonster = static_cast<net::CookieMonster*>(cookieStore.get());
- cookieStore->SetChannelIDServiceID(m_urlRequestContext->channel_id_service()->GetUniqueID());
- m_cookieDelegate->setCookieMonster(cookieMonster);
- m_storage->set_cookie_store(std::move(cookieStore));
-
- const std::vector<std::string> cookieableSchemes(kCookieableSchemes, kCookieableSchemes + arraysize(kCookieableSchemes));
- cookieMonster->SetCookieableSchemes(cookieableSchemes);
-
- if (!m_updateAllStorage && m_updateHttpCache) {
- // HttpCache needs to be regenerated when we generate a new channel id service
- generateHttpCache();
- }
-}
-
-void URLRequestContextGetterQt::updateUserAgent()
-{
- Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
- QMutexLocker lock(&m_mutex);
- m_httpAcceptLanguage = m_browserContextAdapter->httpAcceptLanguage();
- m_httpUserAgent = m_browserContextAdapter->httpUserAgent();
-
- if (m_contextInitialized && !m_updateAllStorage && !m_updateUserAgent) {
- m_updateUserAgent = true;
- content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE,
- base::Bind(&URLRequestContextGetterQt::generateUserAgent, this));
- }
-}
-
-void URLRequestContextGetterQt::generateUserAgent()
-{
- Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
- Q_ASSERT(m_urlRequestContext);
- Q_ASSERT(m_storage);
-
- QMutexLocker lock(&m_mutex);
- m_updateUserAgent = false;
-
- m_storage->set_http_user_agent_settings(std::unique_ptr<net::HttpUserAgentSettings>(
- new net::StaticHttpUserAgentSettings(m_httpAcceptLanguage.toStdString(), m_httpUserAgent.toStdString())));
-}
-
-void URLRequestContextGetterQt::updateHttpCache()
-{
- Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
- QMutexLocker lock(&m_mutex);
- m_httpCacheType = m_browserContextAdapter->httpCacheType();
- m_httpCachePath = m_browserContextAdapter->httpCachePath();
- m_httpCacheMaxSize = m_browserContextAdapter->httpCacheMaxSize();
-
- if (m_httpCacheType == BrowserContextAdapter::NoCache) {
- content::BrowsingDataRemover *remover = content::BrowserContext::GetBrowsingDataRemover(m_browserContextAdapter->browserContext());
- remover->Remove(base::Time(), base::Time::Max(),
- content::BrowsingDataRemover::DATA_TYPE_CACHE,
- content::BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB | content::BrowsingDataRemover::ORIGIN_TYPE_PROTECTED_WEB);
- }
-
- if (m_contextInitialized && !m_updateAllStorage && !m_updateHttpCache) {
- m_updateHttpCache = true;
- content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE,
- base::Bind(&URLRequestContextGetterQt::generateHttpCache, this));
- }
-}
-
-void URLRequestContextGetterQt::updateJobFactory()
-{
- Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
- QMutexLocker lock(&m_mutex);
-
- m_customUrlSchemes = m_browserContextAdapter->customUrlSchemes();
-
- if (m_contextInitialized && !m_updateJobFactory) {
- m_updateJobFactory = true;
- content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE,
- base::Bind(&URLRequestContextGetterQt::regenerateJobFactory, this));
- }
-}
-
-void URLRequestContextGetterQt::updateRequestInterceptor()
-{
- Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
- QMutexLocker lock(&m_mutex);
- m_requestInterceptor = m_browserContextAdapter->requestInterceptor();
-
- // We in this case do not need to regenerate any Chromium classes.
-}
-
-static bool doNetworkSessionContextMatch(const net::HttpNetworkSession::Context &first, const net::HttpNetworkSession::Context &second)
-{
- if (first.transport_security_state != second.transport_security_state)
- return false;
- if (first.cert_verifier != second.cert_verifier)
- return false;
- if (first.channel_id_service != second.channel_id_service)
- return false;
- if (first.proxy_service != second.proxy_service)
- return false;
- if (first.ssl_config_service != second.ssl_config_service)
- return false;
- if (first.http_auth_handler_factory != second.http_auth_handler_factory)
- return false;
- if (first.http_server_properties != second.http_server_properties)
- return false;
- if (first.host_resolver != second.host_resolver)
- return false;
- if (first.cert_transparency_verifier != second.cert_transparency_verifier)
- return false;
- if (first.ct_policy_enforcer != second.ct_policy_enforcer)
- return false;
-
- return true;
-}
-
-static bool doNetworkSessionParamsMatch(const net::HttpNetworkSession::Params &first, const net::HttpNetworkSession::Params &second)
-{
- if (first.ignore_certificate_errors != second.ignore_certificate_errors)
- return false;
-
- return true;
-}
-
-net::HttpNetworkSession::Context URLRequestContextGetterQt::generateNetworkSessionContext()
-{
- Q_ASSERT(m_urlRequestContext);
-
- net::HttpNetworkSession::Context network_session_context;
-
- network_session_context.transport_security_state = m_urlRequestContext->transport_security_state();
- network_session_context.cert_verifier = m_urlRequestContext->cert_verifier();
- network_session_context.channel_id_service = m_urlRequestContext->channel_id_service();
- network_session_context.proxy_service = m_urlRequestContext->proxy_service();
- network_session_context.ssl_config_service = m_urlRequestContext->ssl_config_service();
- network_session_context.http_auth_handler_factory = m_urlRequestContext->http_auth_handler_factory();
- network_session_context.http_server_properties = m_urlRequestContext->http_server_properties();
- network_session_context.host_resolver = m_urlRequestContext->host_resolver();
- network_session_context.cert_transparency_verifier = m_urlRequestContext->cert_transparency_verifier();
- network_session_context.ct_policy_enforcer = m_urlRequestContext->ct_policy_enforcer();
-
- return network_session_context;
-}
-
-net::HttpNetworkSession::Params URLRequestContextGetterQt::generateNetworkSessionParams()
-{
- Q_ASSERT(m_urlRequestContext);
-
- net::HttpNetworkSession::Params network_session_params;
-
- network_session_params.ignore_certificate_errors = m_ignoreCertificateErrors;
-
- return network_session_params;
-}
-
-void URLRequestContextGetterQt::generateHttpCache()
-{
- Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
- Q_ASSERT(m_urlRequestContext);
- Q_ASSERT(m_storage);
-
- QMutexLocker lock(&m_mutex);
- m_updateHttpCache = false;
-
- if (m_updateCookieStore)
- generateCookieStore();
-
- net::HttpCache::DefaultBackend* main_backend = 0;
- switch (m_httpCacheType) {
- case BrowserContextAdapter::MemoryHttpCache:
- main_backend =
- new net::HttpCache::DefaultBackend(
- net::MEMORY_CACHE,
- net::CACHE_BACKEND_DEFAULT,
- base::FilePath(),
- m_httpCacheMaxSize
- );
- break;
- case BrowserContextAdapter::DiskHttpCache:
- main_backend =
- new net::HttpCache::DefaultBackend(
- net::DISK_CACHE,
- net::CACHE_BACKEND_DEFAULT,
- toFilePath(m_httpCachePath),
- m_httpCacheMaxSize
- );
- break;
- case BrowserContextAdapter::NoCache:
- // It's safe to not create BackendFactory.
- break;
- }
-
- net::HttpCache *cache = 0;
- net::HttpNetworkSession::Context network_session_context = generateNetworkSessionContext();
- net::HttpNetworkSession::Params network_session_params = generateNetworkSessionParams();
-
- if (!m_httpNetworkSession
- || !doNetworkSessionParamsMatch(network_session_params, m_httpNetworkSession->params())
- || !doNetworkSessionContextMatch(network_session_context, m_httpNetworkSession->context())) {
- cancelAllUrlRequests();
- m_httpNetworkSession.reset(new net::HttpNetworkSession(network_session_params, network_session_context));
- }
-
- cache = new net::HttpCache(m_httpNetworkSession.get(), std::unique_ptr<net::HttpCache::DefaultBackend>(main_backend), false);
-
- m_storage->set_http_transaction_factory(std::unique_ptr<net::HttpCache>(cache));
-}
-
-void URLRequestContextGetterQt::generateJobFactory()
-{
- Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
- Q_ASSERT(m_urlRequestContext);
- Q_ASSERT(!m_jobFactory);
-
- QMutexLocker lock(&m_mutex);
- m_updateJobFactory = false;
-
- std::unique_ptr<net::URLRequestJobFactoryImpl> jobFactory(new net::URLRequestJobFactoryImpl());
- for (auto &it : m_protocolHandlers)
- jobFactory->SetProtocolHandler(it.first, base::WrapUnique(it.second.release()));
- m_protocolHandlers.clear();
-
- jobFactory->SetProtocolHandler(url::kDataScheme, std::unique_ptr<net::URLRequestJobFactory::ProtocolHandler>(new net::DataProtocolHandler()));
- jobFactory->SetProtocolHandler(url::kFileScheme,
- std::make_unique<net::FileProtocolHandler>(
- base::CreateTaskRunnerWithTraits({base::MayBlock(),
- base::TaskPriority::BACKGROUND,
- base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN})));
- jobFactory->SetProtocolHandler(kQrcSchemeQt, std::unique_ptr<net::URLRequestJobFactory::ProtocolHandler>(new QrcProtocolHandlerQt()));
- jobFactory->SetProtocolHandler(url::kFtpScheme,
- net::FtpProtocolHandler::Create(m_urlRequestContext->host_resolver()));
-
- m_installedCustomSchemes = m_customUrlSchemes;
- Q_FOREACH (const QByteArray &scheme, m_installedCustomSchemes) {
- jobFactory->SetProtocolHandler(scheme.toStdString(), std::unique_ptr<net::URLRequestJobFactory::ProtocolHandler>(new CustomProtocolHandler(m_browserContextAdapter)));
- }
-
- m_baseJobFactory = jobFactory.get();
-
- // Set up interceptors in the reverse order.
- std::unique_ptr<net::URLRequestJobFactory> topJobFactory = std::move(jobFactory);
-
- for (content::URLRequestInterceptorScopedVector::reverse_iterator i = m_requestInterceptors.rbegin(); i != m_requestInterceptors.rend(); ++i) {
- topJobFactory.reset(new net::URLRequestInterceptingJobFactory(std::move(topJobFactory), std::move(*i)));
- }
-
- m_requestInterceptors.clear();
-
- if (m_protocolHandlerInterceptor) {
- m_protocolHandlerInterceptor->Chain(std::move(topJobFactory));
- topJobFactory = std::move(m_protocolHandlerInterceptor);
- }
-
- m_jobFactory = std::move(topJobFactory);
-
- m_urlRequestContext->set_job_factory(m_jobFactory.get());
-}
-
-void URLRequestContextGetterQt::regenerateJobFactory()
-{
- Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
- Q_ASSERT(m_urlRequestContext);
- Q_ASSERT(m_jobFactory);
- Q_ASSERT(m_baseJobFactory);
-
- QMutexLocker lock(&m_mutex);
- m_updateJobFactory = false;
-
- if (m_customUrlSchemes == m_installedCustomSchemes)
- return;
-
- Q_FOREACH (const QByteArray &scheme, m_installedCustomSchemes) {
- m_baseJobFactory->SetProtocolHandler(scheme.toStdString(), nullptr);
- }
-
- m_installedCustomSchemes = m_customUrlSchemes;
- Q_FOREACH (const QByteArray &scheme, m_installedCustomSchemes) {
- m_baseJobFactory->SetProtocolHandler(scheme.toStdString(), std::unique_ptr<net::URLRequestJobFactory::ProtocolHandler>(new CustomProtocolHandler(m_browserContextAdapter)));
- }
+ return m_profileIOData->urlRequestContext();
}
scoped_refptr<base::SingleThreadTaskRunner> URLRequestContextGetterQt::GetNetworkTaskRunner() const
diff --git a/src/core/net/url_request_context_getter_qt.h b/src/core/net/url_request_context_getter_qt.h
index fbc445e4f..b6135cb16 100644
--- a/src/core/net/url_request_context_getter_qt.h
+++ b/src/core/net/url_request_context_getter_qt.h
@@ -42,108 +42,18 @@
#include "net/url_request/url_request_context_getter.h"
-#include "base/memory/ref_counted.h"
-#include "base/single_thread_task_runner.h"
-#include "chrome/browser/custom_handlers/protocol_handler_registry.h"
-#include "net/http/http_network_session.h"
-#include "net/url_request/url_request_context_storage.h"
-#include "net/url_request/url_request_job_factory_impl.h"
-#include "net/proxy/dhcp_proxy_script_fetcher_factory.h"
-#include "services/proxy_resolver/public/interfaces/proxy_resolver.mojom.h"
-
-#include "cookie_monster_delegate_qt.h"
-#include "network_delegate_qt.h"
-#include "browser_context_adapter.h"
-
-#include <QtCore/qatomic.h>
-#include <QtCore/qmutex.h>
-#include <QtCore/qsharedpointer.h>
-
-namespace net {
-class HttpAuthPreferences;
-class MappedHostResolver;
-class ProxyConfigService;
-}
-
namespace QtWebEngineCore {
-// FIXME: This class should be split into a URLRequestContextGetter and a ProfileIOData, similar to what chrome does.
+class ProfileIODataQt;
+
class URLRequestContextGetterQt : public net::URLRequestContextGetter {
public:
- URLRequestContextGetterQt(BrowserContextAdapter *browserContext,
- content::ProtocolHandlerMap *protocolHandlers,
- content::URLRequestInterceptorScopedVector request_interceptors);
-
+ URLRequestContextGetterQt(ProfileIODataQt *data);
net::URLRequestContext *GetURLRequestContext() override;
scoped_refptr<base::SingleThreadTaskRunner> GetNetworkTaskRunner() const override;
-
- // Called on the UI thread:
- void updateStorageSettings();
- void updateUserAgent();
- void updateCookieStore();
- void updateHttpCache();
- void updateJobFactory();
- void updateRequestInterceptor();
- void setFullConfiguration();
-
private:
virtual ~URLRequestContextGetterQt();
-
- // Called on the IO thread:
- void generateAllStorage();
- void generateStorage();
- void generateCookieStore();
- void generateHttpCache();
- void generateUserAgent();
- void generateJobFactory();
- void regenerateJobFactory();
- void cancelAllUrlRequests();
- net::HttpNetworkSession::Params generateNetworkSessionParams();
- net::HttpNetworkSession::Context generateNetworkSessionContext();
-
- bool m_ignoreCertificateErrors;
- QMutex m_mutex;
- bool m_contextInitialized;
- bool m_updateAllStorage;
- bool m_updateCookieStore;
- bool m_updateHttpCache;
- bool m_updateJobFactory;
- bool m_updateUserAgent;
-
- // m_browserContext is never dereferenced in IO thread and it is passed by
- // qpointer in generateJobFactory
- QPointer<BrowserContextAdapter> m_browserContextAdapter;
- content::ProtocolHandlerMap m_protocolHandlers;
- QAtomicPointer<net::ProxyConfigService> m_proxyConfigService;
- std::unique_ptr<net::URLRequestContext> m_urlRequestContext;
- std::unique_ptr<NetworkDelegateQt> m_networkDelegate;
- std::unique_ptr<net::URLRequestContextStorage> m_storage;
- std::unique_ptr<net::URLRequestJobFactory> m_jobFactory;
- std::unique_ptr<ProtocolHandlerRegistry::JobInterceptorFactory> m_protocolHandlerInterceptor;
- net::URLRequestJobFactoryImpl *m_baseJobFactory;
- std::unique_ptr<net::DhcpProxyScriptFetcherFactory> m_dhcpProxyScriptFetcherFactory;
- scoped_refptr<CookieMonsterDelegateQt> m_cookieDelegate;
- content::URLRequestInterceptorScopedVector m_requestInterceptors;
- std::unique_ptr<net::HttpNetworkSession> m_httpNetworkSession;
- std::unique_ptr<net::HttpAuthPreferences> m_httpAuthPreferences;
- proxy_resolver::mojom::ProxyResolverFactoryPtr m_proxyResolverFactory;
-
- QList<QByteArray> m_installedCustomSchemes;
- QWebEngineUrlRequestInterceptor* m_requestInterceptor;
-
- // Configuration values to setup URLRequestContext in IO thread, copied from browserContext
- // FIXME: Should later be moved to a separate ProfileIOData class.
- BrowserContextAdapter::PersistentCookiesPolicy m_persistentCookiesPolicy;
- QString m_cookiesPath;
- QString m_channelIdPath;
- QString m_httpAcceptLanguage;
- QString m_httpUserAgent;
- BrowserContextAdapter::HttpCacheType m_httpCacheType;
- QString m_httpCachePath;
- int m_httpCacheMaxSize;
- QList<QByteArray> m_customUrlSchemes;
-
- friend class NetworkDelegateQt;
+ ProfileIODataQt *m_profileIOData;
};
} // namespace QtWebEngineCore
diff --git a/src/core/profile_io_data_qt.cpp b/src/core/profile_io_data_qt.cpp
new file mode 100644
index 000000000..cf13559bc
--- /dev/null
+++ b/src/core/profile_io_data_qt.cpp
@@ -0,0 +1,658 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtWebEngine module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "profile_io_data_qt.h"
+#include "base/task_scheduler/post_task.h"
+#include "content/network/proxy_service_mojo.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/browsing_data_remover.h"
+#include "content/public/browser/cookie_store_factory.h"
+#include "content/public/common/content_features.h"
+#include "chrome/browser/custom_handlers/protocol_handler_registry_factory.h"
+#include "chrome/browser/net/chrome_mojo_proxy_resolver_factory.h"
+#include "net/cookie_monster_delegate_qt.h"
+#include "net/cert/cert_verifier.h"
+#include "net/cert/ct_known_logs.h"
+#include "net/cert/ct_log_verifier.h"
+#include "net/cert/multi_log_ct_verifier.h"
+#include "net/custom_protocol_handler.h"
+#include "net/extras/sqlite/sqlite_channel_id_store.h"
+#include "net/http/http_auth_handler_factory.h"
+#include "net/http/http_auth_scheme.h"
+#include "net/http/http_auth_preferences.h"
+#include "net/http/http_cache.h"
+#include "net/http/http_server_properties_impl.h"
+#include "net/http/http_network_session.h"
+#include "net/proxy/dhcp_proxy_script_fetcher_factory.h"
+#include "net/proxy/proxy_script_fetcher_impl.h"
+#include "net/proxy/proxy_service.h"
+#include "net/proxy_config_service_qt.h"
+#include "net/ssl/channel_id_service.h"
+#include "net/ssl/ssl_config_service_defaults.h"
+#include "net/network_delegate_qt.h"
+#include "net/url_request_context_getter_qt.h"
+#include "net/url_request/data_protocol_handler.h"
+#include "net/url_request/file_protocol_handler.h"
+#include "net/url_request/ftp_protocol_handler.h"
+#include "net/url_request/static_http_user_agent_settings.h"
+#include "net/url_request/url_request_context_storage.h"
+#include "net/url_request/url_request_job_factory_impl.h"
+#include "net/url_request/url_request_intercepting_job_factory.h"
+#include "net/qrc_protocol_handler_qt.h"
+#include "profile_qt.h"
+#include "resource_context_qt.h"
+#include "type_conversion.h"
+namespace QtWebEngineCore {
+
+static const char* const kDefaultAuthSchemes[] = { net::kBasicAuthScheme,
+ net::kDigestAuthScheme,
+#if defined(USE_KERBEROS) && !defined(OS_ANDROID)
+ net::kNegotiateAuthScheme,
+#endif
+ net::kNtlmAuthScheme };
+
+static bool doNetworkSessionParamsMatch(const net::HttpNetworkSession::Params &first,
+ const net::HttpNetworkSession::Params &second)
+{
+ if (first.ignore_certificate_errors != second.ignore_certificate_errors)
+ return false;
+ return true;
+}
+
+static bool doNetworkSessionContextMatch(const net::HttpNetworkSession::Context &first,
+ const net::HttpNetworkSession::Context &second)
+{
+ if (first.transport_security_state != second.transport_security_state)
+ return false;
+ if (first.cert_verifier != second.cert_verifier)
+ return false;
+ if (first.channel_id_service != second.channel_id_service)
+ return false;
+ if (first.proxy_service != second.proxy_service)
+ return false;
+ if (first.ssl_config_service != second.ssl_config_service)
+ return false;
+ if (first.http_auth_handler_factory != second.http_auth_handler_factory)
+ return false;
+ if (first.http_server_properties != second.http_server_properties)
+ return false;
+ if (first.host_resolver != second.host_resolver)
+ return false;
+ if (first.cert_transparency_verifier != second.cert_transparency_verifier)
+ return false;
+ if (first.ct_policy_enforcer != second.ct_policy_enforcer)
+ return false;
+ return true;
+}
+
+static net::HttpNetworkSession::Context generateNetworkSessionContext(net::URLRequestContext *urlRequestContext)
+{
+ net::HttpNetworkSession::Context network_session_context;
+ network_session_context.transport_security_state = urlRequestContext->transport_security_state();
+ network_session_context.cert_verifier = urlRequestContext->cert_verifier();
+ network_session_context.channel_id_service = urlRequestContext->channel_id_service();
+ network_session_context.proxy_service = urlRequestContext->proxy_service();
+ network_session_context.ssl_config_service = urlRequestContext->ssl_config_service();
+ network_session_context.http_auth_handler_factory = urlRequestContext->http_auth_handler_factory();
+ network_session_context.http_server_properties = urlRequestContext->http_server_properties();
+ network_session_context.host_resolver = urlRequestContext->host_resolver();
+ network_session_context.cert_transparency_verifier = urlRequestContext->cert_transparency_verifier();
+ network_session_context.ct_policy_enforcer = urlRequestContext->ct_policy_enforcer();
+ return network_session_context;
+}
+
+static net::HttpNetworkSession::Params generateNetworkSessionParams(bool ignoreCertificateErrors)
+{
+ net::HttpNetworkSession::Params network_session_params;
+ network_session_params.ignore_certificate_errors = ignoreCertificateErrors;
+ return network_session_params;
+}
+
+ProfileIODataQt::ProfileIODataQt(ProfileQt *profile)
+ : m_profile(profile),
+ m_mutex(QMutex::Recursive),
+ m_weakPtrFactory(this)
+{
+ if (content::BrowserThread::IsMessageLoopValid(content::BrowserThread::UI))
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+}
+
+ProfileIODataQt::~ProfileIODataQt()
+{
+ if (content::BrowserThread::IsMessageLoopValid(content::BrowserThread::IO))
+ DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+ m_resourceContext.reset();
+ if (m_cookieDelegate)
+ m_cookieDelegate->setCookieMonster(0); // this will let CookieMonsterDelegateQt be deleted
+ m_networkDelegate.reset();
+ delete m_proxyConfigService.fetchAndStoreAcquire(0);
+}
+
+void ProfileIODataQt::shutdownOnUIThread()
+{
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+ bool posted = content::BrowserThread::DeleteSoon(content::BrowserThread::IO, FROM_HERE, this);
+ if (!posted) {
+ qWarning() << "Could not delete ProfileIODataQt on io thread !";
+ delete this;
+ }
+}
+
+net::URLRequestContext *ProfileIODataQt::urlRequestContext()
+{
+ DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+ if (!m_initialized)
+ initializeOnIOThread();
+ return m_urlRequestContext.get();
+}
+
+content::ResourceContext *ProfileIODataQt::resourceContext()
+{
+ return m_resourceContext.get();
+}
+
+void ProfileIODataQt::initializeOnIOThread()
+{
+ m_networkDelegate.reset(new NetworkDelegateQt(this));
+ m_urlRequestContext.reset(new net::URLRequestContext());
+ m_urlRequestContext->set_network_delegate(m_networkDelegate.get());
+ m_urlRequestContext->set_enable_brotli(base::FeatureList::IsEnabled(features::kBrotliEncoding));
+ // this binds factory to io thread
+ m_weakPtr = m_weakPtrFactory.GetWeakPtr();
+ QMutexLocker lock(&m_mutex);
+ m_initialized = true;
+ generateAllStorage();
+ generateJobFactory();
+}
+
+void ProfileIODataQt::initializeOnUIThread()
+{
+ m_browserContextAdapter = m_profile->adapter();
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+ m_resourceContext.reset(new ResourceContextQt(this));
+ ProtocolHandlerRegistry* protocolHandlerRegistry =
+ ProtocolHandlerRegistryFactory::GetForBrowserContext(m_profile);
+ DCHECK(protocolHandlerRegistry);
+ m_protocolHandlerInterceptor =
+ protocolHandlerRegistry->CreateJobInterceptorFactory();
+ m_cookieDelegate = new CookieMonsterDelegateQt();
+ m_cookieDelegate->setClient(m_profile->adapter()->cookieStore());
+}
+
+void ProfileIODataQt::cancelAllUrlRequests()
+{
+ Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
+ Q_ASSERT(m_urlRequestContext);
+
+ const std::set<const net::URLRequest*> *url_requests = m_urlRequestContext->url_requests();
+ std::set<const net::URLRequest*>::const_iterator it = url_requests->begin();
+ std::set<const net::URLRequest*>::const_iterator end = url_requests->end();
+ for ( ; it != end; ++it) {
+ net::URLRequest* request = const_cast<net::URLRequest*>(*it);
+ if (request)
+ request->Cancel();
+ }
+}
+
+void ProfileIODataQt::generateAllStorage()
+{
+ Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
+ QMutexLocker lock(&m_mutex);
+ generateStorage();
+ generateCookieStore();
+ generateUserAgent();
+ generateHttpCache();
+ m_updateAllStorage = false;
+}
+
+void ProfileIODataQt::generateStorage()
+{
+ Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
+ Q_ASSERT(m_urlRequestContext);
+
+ // We must stop all requests before deleting their backends.
+ if (m_storage) {
+ m_cookieDelegate->setCookieMonster(0);
+ m_storage->set_cookie_store(0);
+ cancelAllUrlRequests();
+ // we need to get rid of dangling pointer due to coming storage deletion
+ m_urlRequestContext->set_http_transaction_factory(0);
+ m_httpNetworkSession.reset();
+ }
+
+ m_storage.reset(new net::URLRequestContextStorage(m_urlRequestContext.get()));
+
+ net::ProxyConfigService *proxyConfigService = m_proxyConfigService.fetchAndStoreAcquire(0);
+ Q_ASSERT(proxyConfigService);
+
+ m_storage->set_cert_verifier(net::CertVerifier::CreateDefault());
+ std::unique_ptr<net::MultiLogCTVerifier> ct_verifier(new net::MultiLogCTVerifier());
+ ct_verifier->AddLogs(net::ct::CreateLogVerifiersForKnownLogs());
+ m_storage->set_cert_transparency_verifier(std::move(ct_verifier));
+ m_storage->set_ct_policy_enforcer(base::WrapUnique(new net::CTPolicyEnforcer));
+
+ std::unique_ptr<net::HostResolver> host_resolver(net::HostResolver::CreateDefaultResolver(NULL));
+
+ // The System Proxy Resolver has issues on Windows with unconfigured network cards,
+ // which is why we want to use the v8 one
+ if (!m_dhcpProxyScriptFetcherFactory)
+ m_dhcpProxyScriptFetcherFactory.reset(new net::DhcpProxyScriptFetcherFactory);
+
+ m_storage->set_proxy_service(content::CreateProxyServiceUsingMojoFactory(
+ std::move(m_proxyResolverFactory),
+ std::unique_ptr<net::ProxyConfigService>(proxyConfigService),
+ std::make_unique<net::ProxyScriptFetcherImpl>(m_urlRequestContext.get()),
+ m_dhcpProxyScriptFetcherFactory->Create(m_urlRequestContext.get()),
+ host_resolver.get(),
+ nullptr /* NetLog */,
+ m_networkDelegate.get()));
+
+ m_storage->set_ssl_config_service(new net::SSLConfigServiceDefaults);
+ m_storage->set_transport_security_state(std::unique_ptr<net::TransportSecurityState>(
+ new net::TransportSecurityState()));
+
+ if (!m_httpAuthPreferences) {
+ std::vector<std::string> auth_types(std::begin(kDefaultAuthSchemes),
+ std::end(kDefaultAuthSchemes));
+ m_httpAuthPreferences.reset(new net::HttpAuthPreferences(auth_types
+#if defined(OS_POSIX) && !defined(OS_ANDROID)
+ , std::string() /* gssapi library name */
+#endif
+ ));
+ }
+ m_storage->set_http_auth_handler_factory(
+ net::HttpAuthHandlerRegistryFactory::Create(m_httpAuthPreferences.get(),
+ host_resolver.get()));
+ m_storage->set_http_server_properties(std::unique_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(std::move(host_resolver));
+}
+
+
+void ProfileIODataQt::generateCookieStore()
+{
+ Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
+ Q_ASSERT(m_urlRequestContext);
+ Q_ASSERT(m_storage);
+
+ QMutexLocker lock(&m_mutex);
+ m_updateCookieStore = false;
+
+ scoped_refptr<net::SQLiteChannelIDStore> channel_id_db;
+ if (!m_channelIdPath.isEmpty() && m_persistentCookiesPolicy != BrowserContextAdapter::NoPersistentCookies) {
+ channel_id_db = new net::SQLiteChannelIDStore(
+ toFilePath(m_channelIdPath),
+ base::CreateSequencedTaskRunnerWithTraits(
+ {base::MayBlock(), base::TaskPriority::BACKGROUND}));
+ }
+
+ m_storage->set_channel_id_service(
+ base::WrapUnique(new net::ChannelIDService(
+ new net::DefaultChannelIDStore(channel_id_db.get()))));
+
+ // Unset it first to get a chance to destroy and flush the old cookie store before
+ // opening a new on possibly the same file.
+ m_cookieDelegate->setCookieMonster(0);
+ m_storage->set_cookie_store(0);
+
+ std::unique_ptr<net::CookieStore> cookieStore;
+ switch (m_persistentCookiesPolicy) {
+ case BrowserContextAdapter::NoPersistentCookies:
+ cookieStore = content::CreateCookieStore(
+ content::CookieStoreConfig(
+ base::FilePath(),
+ false,
+ false,
+ nullptr)
+ );
+ break;
+ case BrowserContextAdapter::AllowPersistentCookies:
+ cookieStore = content::CreateCookieStore(
+ content::CookieStoreConfig(
+ toFilePath(m_cookiesPath),
+ false,
+ true,
+ nullptr)
+ );
+ break;
+ case BrowserContextAdapter::ForcePersistentCookies:
+ cookieStore = content::CreateCookieStore(
+ content::CookieStoreConfig(
+ toFilePath(m_cookiesPath),
+ true,
+ true,
+ nullptr)
+ );
+ break;
+ }
+
+ net::CookieMonster * const cookieMonster = static_cast<net::CookieMonster*>(cookieStore.get());
+ cookieStore->SetChannelIDServiceID(m_urlRequestContext->channel_id_service()->GetUniqueID());
+ m_cookieDelegate->setCookieMonster(cookieMonster);
+ m_storage->set_cookie_store(std::move(cookieStore));
+
+ const std::vector<std::string> cookieableSchemes(kCookieableSchemes,
+ kCookieableSchemes + arraysize(kCookieableSchemes));
+ cookieMonster->SetCookieableSchemes(cookieableSchemes);
+
+ if (!m_updateAllStorage && m_updateHttpCache) {
+ // HttpCache needs to be regenerated when we generate a new channel id service
+ generateHttpCache();
+ }
+}
+
+void ProfileIODataQt::generateUserAgent()
+{
+ Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
+ Q_ASSERT(m_urlRequestContext);
+ Q_ASSERT(m_storage);
+
+ QMutexLocker lock(&m_mutex);
+ m_updateUserAgent = false;
+
+ m_storage->set_http_user_agent_settings(std::unique_ptr<net::HttpUserAgentSettings>(
+ new net::StaticHttpUserAgentSettings(m_httpAcceptLanguage.toStdString(),
+ m_httpUserAgent.toStdString())));
+}
+
+void ProfileIODataQt::generateHttpCache()
+{
+ Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
+ Q_ASSERT(m_urlRequestContext);
+ Q_ASSERT(m_storage);
+
+ QMutexLocker lock(&m_mutex);
+ m_updateHttpCache = false;
+
+ if (m_updateCookieStore)
+ generateCookieStore();
+
+ net::HttpCache::DefaultBackend* main_backend = 0;
+ switch (m_httpCacheType) {
+ case BrowserContextAdapter::MemoryHttpCache:
+ main_backend =
+ new net::HttpCache::DefaultBackend(
+ net::MEMORY_CACHE,
+ net::CACHE_BACKEND_DEFAULT,
+ base::FilePath(),
+ m_httpCacheMaxSize
+ );
+ break;
+ case BrowserContextAdapter::DiskHttpCache:
+ main_backend =
+ new net::HttpCache::DefaultBackend(
+ net::DISK_CACHE,
+ net::CACHE_BACKEND_DEFAULT,
+ toFilePath(m_httpCachePath),
+ m_httpCacheMaxSize
+ );
+ break;
+ case BrowserContextAdapter::NoCache:
+ // It's safe to not create BackendFactory.
+ break;
+ }
+
+ net::HttpCache *cache = 0;
+ net::HttpNetworkSession::Context network_session_context =
+ generateNetworkSessionContext(m_urlRequestContext.get());
+ net::HttpNetworkSession::Params network_session_params =
+ generateNetworkSessionParams(m_ignoreCertificateErrors);
+
+ if (!m_httpNetworkSession
+ || !doNetworkSessionParamsMatch(network_session_params, m_httpNetworkSession->params())
+ || !doNetworkSessionContextMatch(network_session_context, m_httpNetworkSession->context())) {
+ cancelAllUrlRequests();
+ m_httpNetworkSession.reset(new net::HttpNetworkSession(network_session_params,
+ network_session_context));
+ }
+
+ cache = new net::HttpCache(m_httpNetworkSession.get(),
+ std::unique_ptr<net::HttpCache::DefaultBackend>(main_backend), false);
+
+ m_storage->set_http_transaction_factory(std::unique_ptr<net::HttpCache>(cache));
+}
+
+void ProfileIODataQt::generateJobFactory()
+{
+ Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
+ Q_ASSERT(m_urlRequestContext);
+ Q_ASSERT(!m_jobFactory);
+
+ QMutexLocker lock(&m_mutex);
+ m_updateJobFactory = false;
+
+ std::unique_ptr<net::URLRequestJobFactoryImpl> jobFactory(new net::URLRequestJobFactoryImpl());
+ for (auto &it : m_protocolHandlers)
+ jobFactory->SetProtocolHandler(it.first, base::WrapUnique(it.second.release()));
+ m_protocolHandlers.clear();
+
+ jobFactory->SetProtocolHandler(url::kDataScheme,
+ std::unique_ptr<net::URLRequestJobFactory::ProtocolHandler>(
+ new net::DataProtocolHandler()));
+ scoped_refptr<base::TaskRunner> taskRunner(base::CreateTaskRunnerWithTraits({base::MayBlock(),
+ base::TaskPriority::BACKGROUND,
+ base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN}));
+ jobFactory->SetProtocolHandler(url::kFileScheme,
+ std::make_unique<net::FileProtocolHandler>(taskRunner));
+ jobFactory->SetProtocolHandler(kQrcSchemeQt,
+ std::unique_ptr<net::URLRequestJobFactory::ProtocolHandler>(
+ new QrcProtocolHandlerQt()));
+ jobFactory->SetProtocolHandler(url::kFtpScheme,
+ net::FtpProtocolHandler::Create(m_urlRequestContext->host_resolver()));
+
+ m_installedCustomSchemes = m_customUrlSchemes;
+ Q_FOREACH (const QByteArray &scheme, m_installedCustomSchemes) {
+ jobFactory->SetProtocolHandler(scheme.toStdString(),
+ std::unique_ptr<net::URLRequestJobFactory::ProtocolHandler>(
+ new CustomProtocolHandler(m_browserContextAdapter)));
+ }
+
+ m_baseJobFactory = jobFactory.get();
+
+ // Set up interceptors in the reverse order.
+ std::unique_ptr<net::URLRequestJobFactory> topJobFactory = std::move(jobFactory);
+ content::URLRequestInterceptorScopedVector::reverse_iterator i;
+ for (i = m_requestInterceptors.rbegin(); i != m_requestInterceptors.rend(); ++i) {
+ topJobFactory.reset(new net::URLRequestInterceptingJobFactory(std::move(topJobFactory),
+ std::move(*i)));
+ }
+
+ m_requestInterceptors.clear();
+
+ if (m_protocolHandlerInterceptor) {
+ m_protocolHandlerInterceptor->Chain(std::move(topJobFactory));
+ topJobFactory = std::move(m_protocolHandlerInterceptor);
+ }
+
+ m_jobFactory = std::move(topJobFactory);
+
+ m_urlRequestContext->set_job_factory(m_jobFactory.get());
+}
+
+void ProfileIODataQt::regenerateJobFactory()
+{
+ Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
+ Q_ASSERT(m_urlRequestContext);
+ Q_ASSERT(m_jobFactory);
+ Q_ASSERT(m_baseJobFactory);
+
+ QMutexLocker lock(&m_mutex);
+ m_updateJobFactory = false;
+
+ if (m_customUrlSchemes == m_installedCustomSchemes)
+ return;
+
+ Q_FOREACH (const QByteArray &scheme, m_installedCustomSchemes) {
+ m_baseJobFactory->SetProtocolHandler(scheme.toStdString(), nullptr);
+ }
+
+ m_installedCustomSchemes = m_customUrlSchemes;
+ Q_FOREACH (const QByteArray &scheme, m_installedCustomSchemes) {
+ m_baseJobFactory->SetProtocolHandler(scheme.toStdString(),
+ std::unique_ptr<net::URLRequestJobFactory::ProtocolHandler>(
+ new CustomProtocolHandler(m_browserContextAdapter)));
+ }
+}
+
+void ProfileIODataQt::setRequestContextData(content::ProtocolHandlerMap *protocolHandlers,
+ content::URLRequestInterceptorScopedVector request_interceptors)
+{
+ Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+ Q_ASSERT(!m_initialized);
+ m_requestInterceptors = std::move(request_interceptors);
+ std::swap(m_protocolHandlers, *protocolHandlers);
+}
+
+void ProfileIODataQt::setFullConfiguration()
+{
+ Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+ m_requestInterceptor = m_browserContextAdapter->requestInterceptor();
+ m_persistentCookiesPolicy = m_browserContextAdapter->persistentCookiesPolicy();
+ m_cookiesPath = m_browserContextAdapter->cookiesPath();
+ m_channelIdPath = m_browserContextAdapter->channelIdPath();
+ m_httpAcceptLanguage = m_browserContextAdapter->httpAcceptLanguage();
+ m_httpUserAgent = m_browserContextAdapter->httpUserAgent();
+ m_httpCacheType = m_browserContextAdapter->httpCacheType();
+ m_httpCachePath = m_browserContextAdapter->httpCachePath();
+ m_httpCacheMaxSize = m_browserContextAdapter->httpCacheMaxSize();
+ m_customUrlSchemes = m_browserContextAdapter->customUrlSchemes();
+}
+
+void ProfileIODataQt::updateStorageSettings()
+{
+ Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+
+ QMutexLocker lock(&m_mutex);
+ setFullConfiguration();
+
+ if (!m_updateAllStorage) {
+ m_updateAllStorage = true;
+ // 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().
+ Q_ASSERT(m_proxyConfigService == 0);
+ m_proxyConfigService =
+ new ProxyConfigServiceQt(
+ net::ProxyService::CreateSystemProxyConfigService(
+ content::BrowserThread::GetTaskRunnerForThread(content::BrowserThread::IO)));
+ m_proxyResolverFactory = ChromeMojoProxyResolverFactory::CreateWithStrongBinding();
+
+ if (m_initialized)
+ content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE,
+ base::Bind(&ProfileIODataQt::generateAllStorage, m_weakPtr));
+ }
+}
+
+void ProfileIODataQt::updateCookieStore()
+{
+ Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+ QMutexLocker lock(&m_mutex);
+ m_persistentCookiesPolicy = m_browserContextAdapter->persistentCookiesPolicy();
+ m_cookiesPath = m_browserContextAdapter->cookiesPath();
+ m_channelIdPath = m_browserContextAdapter->channelIdPath();
+
+ if (m_initialized && !m_updateAllStorage && !m_updateCookieStore) {
+ m_updateCookieStore = true;
+ m_updateHttpCache = true;
+ content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE,
+ base::Bind(&ProfileIODataQt::generateCookieStore, m_weakPtr));
+ }
+}
+
+void ProfileIODataQt::updateUserAgent()
+{
+ Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+ QMutexLocker lock(&m_mutex);
+ m_httpAcceptLanguage = m_browserContextAdapter->httpAcceptLanguage();
+ m_httpUserAgent = m_browserContextAdapter->httpUserAgent();
+
+ if (m_initialized && !m_updateAllStorage && !m_updateUserAgent) {
+ m_updateUserAgent = true;
+ content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE,
+ base::Bind(&ProfileIODataQt::generateUserAgent, m_weakPtr));
+ }
+}
+
+void ProfileIODataQt::updateHttpCache()
+{
+ Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+ QMutexLocker lock(&m_mutex);
+ m_httpCacheType = m_browserContextAdapter->httpCacheType();
+ m_httpCachePath = m_browserContextAdapter->httpCachePath();
+ m_httpCacheMaxSize = m_browserContextAdapter->httpCacheMaxSize();
+
+ if (m_httpCacheType == BrowserContextAdapter::NoCache) {
+ content::BrowsingDataRemover *remover =
+ content::BrowserContext::GetBrowsingDataRemover(m_browserContextAdapter->browserContext());
+ remover->Remove(base::Time(), base::Time::Max(),
+ content::BrowsingDataRemover::DATA_TYPE_CACHE,
+ content::BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB |
+ content::BrowsingDataRemover::ORIGIN_TYPE_PROTECTED_WEB);
+ }
+
+ if (m_initialized && !m_updateAllStorage && !m_updateHttpCache) {
+ m_updateHttpCache = true;
+ content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE,
+ base::Bind(&ProfileIODataQt::generateHttpCache, m_weakPtr));
+ }
+}
+
+void ProfileIODataQt::updateJobFactory()
+{
+ Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+ QMutexLocker lock(&m_mutex);
+
+ m_customUrlSchemes = m_browserContextAdapter->customUrlSchemes();
+
+ if (m_initialized && !m_updateJobFactory) {
+ m_updateJobFactory = true;
+ content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE,
+ base::Bind(&ProfileIODataQt::regenerateJobFactory, m_weakPtr));
+ }
+}
+
+void ProfileIODataQt::updateRequestInterceptor()
+{
+ Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+ QMutexLocker lock(&m_mutex);
+ m_requestInterceptor = m_browserContextAdapter->requestInterceptor();
+ // We in this case do not need to regenerate any Chromium classes.
+}
+} // namespace QtWebEngineCore
diff --git a/src/core/profile_io_data_qt.h b/src/core/profile_io_data_qt.h
new file mode 100644
index 000000000..d29fefa24
--- /dev/null
+++ b/src/core/profile_io_data_qt.h
@@ -0,0 +1,145 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtWebEngine module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef PROFILE_IO_DATA_QT_H
+#define PROFILE_IO_DATA_QT_H
+
+#include "browser_context_adapter.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/custom_handlers/protocol_handler_registry.h"
+#include "services/proxy_resolver/public/interfaces/proxy_resolver.mojom.h"
+#include <QtCore/QString>
+#include <QtCore/QPointer>
+#include <QtCore/QMutex>
+
+namespace net {
+class DhcpProxyScriptFetcherFactory;
+class HttpAuthPreferences;
+class HttpNetworkSession;
+class NetworkDelegate;
+class ProxyConfigService;
+class URLRequestContext;
+class URLRequestContextStorage;
+class URLRequestJobFactoryImpl;
+}
+
+namespace QtWebEngineCore {
+
+class ProfileQt;
+
+// ProfileIOData contains data that lives on the IOthread
+// we still use shared memebers and use mutex which breaks
+// idea for this object, but this is wip.
+
+class ProfileIODataQt {
+
+public:
+ ProfileIODataQt(ProfileQt *profile); // runs on ui thread
+ virtual ~ProfileIODataQt();
+
+ content::ResourceContext *resourceContext();
+ net::URLRequestContext *urlRequestContext();
+ void initializeOnIOThread();
+ void initializeOnUIThread(); // runs on ui thread
+ void shutdownOnUIThread(); // runs on ui thread
+
+ void cancelAllUrlRequests();
+ void generateAllStorage();
+ void generateStorage();
+ void generateCookieStore();
+ void generateHttpCache();
+ void generateUserAgent();
+ void generateJobFactory();
+ void regenerateJobFactory();
+
+ void setRequestContextData(content::ProtocolHandlerMap *protocolHandlers,
+ content::URLRequestInterceptorScopedVector request_interceptors);
+ void setFullConfiguration(); // runs on ui thread
+ void updateStorageSettings(); // runs on ui thread
+ void updateUserAgent(); // runs on ui thread
+ void updateCookieStore(); // runs on ui thread
+ void updateHttpCache(); // runs on ui thread
+ void updateJobFactory(); // runs on ui thread
+ void updateRequestInterceptor(); // runs on ui thread
+
+private:
+ ProfileQt *m_profile;
+ std::unique_ptr<net::URLRequestContextStorage> m_storage;
+ std::unique_ptr<net::NetworkDelegate> m_networkDelegate;
+ std::unique_ptr<content::ResourceContext> m_resourceContext;
+ std::unique_ptr<net::URLRequestContext> m_urlRequestContext;
+ std::unique_ptr<net::HttpNetworkSession> m_httpNetworkSession;
+ std::unique_ptr<ProtocolHandlerRegistry::JobInterceptorFactory> m_protocolHandlerInterceptor;
+ std::unique_ptr<net::DhcpProxyScriptFetcherFactory> m_dhcpProxyScriptFetcherFactory;
+ std::unique_ptr<net::HttpAuthPreferences> m_httpAuthPreferences;
+ std::unique_ptr<net::URLRequestJobFactory> m_jobFactory;
+ base::WeakPtr<ProfileIODataQt> m_weakPtr;
+ scoped_refptr<CookieMonsterDelegateQt> m_cookieDelegate;
+ content::URLRequestInterceptorScopedVector m_requestInterceptors;
+ content::ProtocolHandlerMap m_protocolHandlers;
+ proxy_resolver::mojom::ProxyResolverFactoryPtr m_proxyResolverFactory;
+ net::URLRequestJobFactoryImpl *m_baseJobFactory = nullptr;
+ QAtomicPointer<net::ProxyConfigService> m_proxyConfigService;
+ QPointer<BrowserContextAdapter> m_browserContextAdapter; // never dereferenced in IO thread and it is passed by qpointer
+ BrowserContextAdapter::PersistentCookiesPolicy m_persistentCookiesPolicy;
+ QString m_cookiesPath;
+ QString m_channelIdPath;
+ QString m_httpAcceptLanguage;
+ QString m_httpUserAgent;
+ BrowserContextAdapter::HttpCacheType m_httpCacheType;
+ QString m_httpCachePath;
+ QList<QByteArray> m_customUrlSchemes;
+ QList<QByteArray> m_installedCustomSchemes;
+ QWebEngineUrlRequestInterceptor* m_requestInterceptor = nullptr;
+ QMutex m_mutex;
+ int m_httpCacheMaxSize = 0;
+ bool m_initialized = false;
+ bool m_updateAllStorage = false;
+ bool m_updateCookieStore = false;
+ bool m_updateHttpCache = false;
+ bool m_updateJobFactory = false;
+ bool m_updateUserAgent = false;
+ bool m_ignoreCertificateErrors = false;
+ base::WeakPtrFactory<ProfileIODataQt> m_weakPtrFactory; // this should be always the last member
+ friend class NetworkDelegateQt;
+ DISALLOW_COPY_AND_ASSIGN(ProfileIODataQt);
+};
+} // namespace QtWebEngineCore
+
+#endif // PROFILE_IO_DATA_QT_H
diff --git a/src/core/profile_qt.cpp b/src/core/profile_qt.cpp
index 75ba69e01..128caa523 100644
--- a/src/core/profile_qt.cpp
+++ b/src/core/profile_qt.cpp
@@ -46,7 +46,6 @@
#include "net/url_request_context_getter_qt.h"
#include "permission_manager_qt.h"
#include "qtwebenginecoreglobal_p.h"
-#include "resource_context_qt.h"
#include "type_conversion.h"
#include "web_engine_library_info.h"
@@ -56,6 +55,7 @@
#include "net/proxy/proxy_config_service.h"
#include "base/base_paths.h"
+#include "components/keyed_service/content/browser_context_dependency_manager.h"
#include "components/prefs/pref_member.h"
#include "components/prefs/pref_service.h"
#include "components/prefs/in_memory_pref_store.h"
@@ -72,7 +72,8 @@
namespace QtWebEngineCore {
ProfileQt::ProfileQt(BrowserContextAdapter *adapter)
- : m_adapter(adapter)
+ : m_profileIOData(new ProfileIODataQt(this)),
+ m_adapter(adapter)
{
PrefServiceFactory factory;
factory.set_user_prefs(new InMemoryPrefStore);
@@ -89,12 +90,22 @@ ProfileQt::ProfileQt(BrowserContextAdapter *adapter)
#endif //ENABLE_SPELLCHECK
m_prefService = factory.Create(registry);
user_prefs::UserPrefs::Set(this, m_prefService.get());
+
+ // Mark the context as live. This prevents the use-after-free DCHECK in
+ // AssertBrowserContextWasntDestroyed from being triggered when a new
+ // ProfileQt object is allocated at the same address as a previously
+ // destroyed one. Needs to be called after WebEngineContext initialization.
+ BrowserContextDependencyManager::GetInstance()->MarkBrowserContextLive(this);
}
ProfileQt::~ProfileQt()
{
- if (resourceContext)
- content::BrowserThread::DeleteSoon(content::BrowserThread::IO, FROM_HERE, resourceContext.release());
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+ BrowserContextDependencyManager::GetInstance()->DestroyBrowserContextServices(this);
+ ShutdownStoragePartitions();
+ m_profileIOData->shutdownOnUIThread();
+ //Should be deleted by IO Thread
+ m_profileIOData.release();
}
PrefService* ProfileQt::GetPrefs()
@@ -119,12 +130,12 @@ bool ProfileQt::IsOffTheRecord() const
net::URLRequestContextGetter *ProfileQt::GetRequestContext()
{
- return url_request_getter_.get();
+ return m_urlRequestContextGetter.get();
}
net::URLRequestContextGetter *ProfileQt::CreateMediaRequestContext()
{
- return url_request_getter_.get();
+ return m_urlRequestContextGetter.get();
}
net::URLRequestContextGetter *ProfileQt::CreateMediaRequestContextForStoragePartition(const base::FilePath&, bool)
@@ -135,9 +146,7 @@ net::URLRequestContextGetter *ProfileQt::CreateMediaRequestContextForStoragePart
content::ResourceContext *ProfileQt::GetResourceContext()
{
- if (!resourceContext)
- resourceContext.reset(new ResourceContextQt(this));
- return resourceContext.get();
+ return m_profileIOData->resourceContext();
}
content::DownloadManagerDelegate *ProfileQt::GetDownloadManagerDelegate()
@@ -147,25 +156,25 @@ content::DownloadManagerDelegate *ProfileQt::GetDownloadManagerDelegate()
content::BrowserPluginGuestManager *ProfileQt::GetGuestManager()
{
- return 0;
+ return nullptr;
}
storage::SpecialStoragePolicy *ProfileQt::GetSpecialStoragePolicy()
{
QT_NOT_YET_IMPLEMENTED
- return 0;
+ return nullptr;
}
content::PushMessagingService *ProfileQt::GetPushMessagingService()
{
- return 0;
+ return nullptr;
}
content::SSLHostStateDelegate* ProfileQt::GetSSLHostStateDelegate()
{
- if (!sslHostStateDelegate)
- sslHostStateDelegate.reset(new SSLHostStateDelegateQt());
- return sslHostStateDelegate.get();
+ if (!m_sslHostStateDelegate)
+ m_sslHostStateDelegate.reset(new SSLHostStateDelegateQt());
+ return m_sslHostStateDelegate.get();
}
std::unique_ptr<content::ZoomLevelDelegate> ProfileQt::CreateZoomLevelDelegate(const base::FilePath&)
@@ -185,23 +194,26 @@ content::BackgroundSyncController* ProfileQt::GetBackgroundSyncController()
content::BrowsingDataRemoverDelegate *ProfileQt::GetBrowsingDataRemoverDelegate()
{
- return new BrowsingDataRemoverDelegateQt;
+ return new BrowsingDataRemoverDelegateQt();
}
content::PermissionManager *ProfileQt::GetPermissionManager()
{
- if (!permissionManager)
- permissionManager.reset(new PermissionManagerQt());
- return permissionManager.get();
+ if (!m_permissionManager)
+ m_permissionManager.reset(new PermissionManagerQt());
+ return m_permissionManager.get();
}
net::URLRequestContextGetter *ProfileQt::CreateRequestContext(
content::ProtocolHandlerMap *protocol_handlers,
content::URLRequestInterceptorScopedVector request_interceptors)
{
- url_request_getter_ = new URLRequestContextGetterQt(m_adapter, protocol_handlers,
- std::move(request_interceptors));
- return url_request_getter_.get();
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+ DCHECK(!m_urlRequestContextGetter.get());
+ m_profileIOData->setRequestContextData(protocol_handlers, std::move(request_interceptors));
+ m_profileIOData->updateStorageSettings();
+ m_urlRequestContextGetter = new URLRequestContextGetterQt(m_profileIOData.get());
+ return m_urlRequestContextGetter.get();
}
net::URLRequestContextGetter *ProfileQt::CreateRequestContextForStoragePartition(
diff --git a/src/core/profile_qt.h b/src/core/profile_qt.h
index fdcdf9e8a..76bb596c0 100644
--- a/src/core/profile_qt.h
+++ b/src/core/profile_qt.h
@@ -44,7 +44,7 @@
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/resource_context.h"
#include "net/url_request/url_request_context.h"
-
+#include "profile_io_data_qt.h"
#include <QtGlobal>
QT_BEGIN_NAMESPACE
@@ -58,7 +58,6 @@ namespace QtWebEngineCore {
class BrowserContextAdapter;
class PermissionManagerQt;
class SSLHostStateDelegateQt;
-class URLRequestContextGetterQt;
class ProfileQt : public Profile
{
@@ -113,12 +112,12 @@ public:
private:
friend class ContentBrowserClientQt;
friend class WebContentsAdapter;
- std::unique_ptr<content::ResourceContext> resourceContext;
- scoped_refptr<URLRequestContextGetterQt> url_request_getter_;
- std::unique_ptr<PermissionManagerQt> permissionManager;
- std::unique_ptr<SSLHostStateDelegateQt> sslHostStateDelegate;
- BrowserContextAdapter *m_adapter;
+ scoped_refptr<net::URLRequestContextGetter> m_urlRequestContextGetter;
+ std::unique_ptr<PermissionManagerQt> m_permissionManager;
+ std::unique_ptr<SSLHostStateDelegateQt> m_sslHostStateDelegate;
std::unique_ptr<PrefService> m_prefService;
+ std::unique_ptr<ProfileIODataQt> m_profileIOData;
+ BrowserContextAdapter *m_adapter;
friend class BrowserContextAdapter;
DISALLOW_COPY_AND_ASSIGN(ProfileQt);
diff --git a/src/core/resource_context_qt.cpp b/src/core/resource_context_qt.cpp
index a906d74c0..8b909812f 100644
--- a/src/core/resource_context_qt.cpp
+++ b/src/core/resource_context_qt.cpp
@@ -39,24 +39,36 @@
#include "resource_context_qt.h"
+#include "content/public/browser/browser_thread.h"
#include "content/public/browser/storage_partition.h"
+#include "net/dns/host_resolver.h"
+#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_context_getter.h"
+#include "profile_io_data_qt.h"
-#include "profile_qt.h"
+#include <qglobal.h>
namespace QtWebEngineCore {
+ResourceContextQt::ResourceContextQt(ProfileIODataQt *io_data)
+ : m_io_data(io_data)
+{
+
+}
+
net::HostResolver *ResourceContextQt::GetHostResolver()
{
+ DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
return GetRequestContext()->host_resolver();
}
net::URLRequestContext* ResourceContextQt::GetRequestContext()
{
- Q_ASSERT(context);
+ Q_ASSERT(m_io_data);
+ DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
// FIXME: This is the only remaining use of GetRequestContext(),
// but we are on the wrong thread for calling BrowserContext::GetDefaultStoragePartition
- return context->GetRequestContext()->GetURLRequestContext();
+ return m_io_data->urlRequestContext();
}
} // namespace QtWebEngineCore
diff --git a/src/core/resource_context_qt.h b/src/core/resource_context_qt.h
index edbba4e0f..d47b1c627 100644
--- a/src/core/resource_context_qt.h
+++ b/src/core/resource_context_qt.h
@@ -42,28 +42,18 @@
#include "content/public/browser/resource_context.h"
-namespace net {
-class URLRequestContextGetter;
-}
-
-class GURL;
-
namespace QtWebEngineCore {
-class ProfileQt;
+
+class ProfileIODataQt;
class ResourceContextQt : public content::ResourceContext
{
public:
- ResourceContextQt(ProfileQt *ctx)
- : context(ctx)
- {}
-
+ ResourceContextQt(ProfileIODataQt *io_data);
net::HostResolver *GetHostResolver() override;
net::URLRequestContext *GetRequestContext() override;
-
private:
- ProfileQt *context;
-
+ ProfileIODataQt* m_io_data;
DISALLOW_COPY_AND_ASSIGN(ResourceContextQt);
};