blob: 68be09ad2689c085a1e2c3009767d3b7c3f2219e [file] [log] [blame]
/****************************************************************************
**
** 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/post_task.h"
#include "components/certificate_transparency/ct_known_logs.h"
#include "components/network_session_configurator/common/network_features.h"
#include "content/public/browser/browser_task_traits.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 "chrome/common/chrome_switches.h"
#include "components/proxy_config/pref_proxy_config_tracker_impl.h"
#include "net/cert/cert_verifier.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/cert_net/cert_net_fetcher_impl.h"
#include "net/ftp/ftp_auth_cache.h"
#include "net/dns/host_resolver_manager.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/http/transport_security_persister.h"
#include "net/proxy_resolution/dhcp_pac_file_fetcher_factory.h"
#include "net/proxy_resolution/pac_file_fetcher_impl.h"
#include "net/proxy_resolution/proxy_config_service.h"
#include "net/proxy_resolution/proxy_resolution_service.h"
#include "net/ssl/ssl_config_service_defaults.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 "services/file/user_id_map.h"
#include "services/network/proxy_service_mojo.h"
#include "services/network/restricted_cookie_manager.h"
#include "net/client_cert_override.h"
#include "net/client_cert_store_data.h"
#include "net/cookie_monster_delegate_qt.h"
#include "net/custom_protocol_handler.h"
#include "net/network_delegate_qt.h"
#include "net/proxy_config_service_qt.h"
#include "net/restricted_cookie_manager_qt.h"
#include "net/url_request_context_getter_qt.h"
#include "profile_qt.h"
#include "resource_context_qt.h"
#include "type_conversion.h"
#if defined(USE_NSS_CERTS)
#include "net/cert_net/nss_ocsp.h"
#endif
#if defined(OS_LINUX) || defined(OS_MACOSX)
#include "net/cert/cert_net_fetcher.h"
#include "net/cert_net/cert_net_fetcher_impl.h"
#endif
#include <mutex>
namespace QtWebEngineCore {
static scoped_refptr<net::CertNetFetcherImpl> s_certNetFetcher;
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.proxy_resolution_service != second.proxy_resolution_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_user_agent_settings != second.http_user_agent_settings)
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.proxy_resolution_service = urlRequestContext->proxy_resolution_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_user_agent_settings = urlRequestContext->http_user_agent_settings();
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),
#if QT_CONFIG(ssl)
m_clientCertificateStoreData(new ClientCertificateStoreData),
#endif
m_removerObserver(this),
m_weakPtrFactory(this)
{
if (content::BrowserThread::IsThreadInitialized(content::BrowserThread::UI))
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
}
ProfileIODataQt::~ProfileIODataQt()
{
if (content::BrowserThread::IsThreadInitialized(content::BrowserThread::IO))
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
if (m_useForGlobalCertificateVerification) {
#if defined(USE_NSS_CERTS)
net::SetURLRequestContextForNSSHttpIO(nullptr);
#endif
if (s_certNetFetcher) {
s_certNetFetcher->Shutdown();
s_certNetFetcher.reset();
}
}
if (m_urlRequestContext) {
if (m_urlRequestContext->proxy_resolution_service())
m_urlRequestContext->proxy_resolution_service()->OnShutdown();
m_restrictedCookieManagerBindings.CloseAllBindings();
cancelAllUrlRequests();
}
m_resourceContext.reset();
if (m_cookieDelegate)
m_cookieDelegate->setCookieMonster(0); // this will let CookieMonsterDelegateQt be deleted
m_networkDelegate.reset();
delete m_proxyConfigService.fetchAndStoreAcquire(0);
}
QPointer<ProfileAdapter> ProfileIODataQt::profileAdapter()
{
return m_profileAdapter;
}
void ProfileIODataQt::shutdownOnUIThread()
{
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
#if QT_CONFIG(ssl)
delete m_clientCertificateStoreData;
m_clientCertificateStoreData = nullptr;
#endif
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();
}
#if BUILDFLAG(ENABLE_EXTENSIONS)
extensions::ExtensionSystemQt* ProfileIODataQt::GetExtensionSystem()
{
return m_profile->GetExtensionSystem();
}
#endif // BUILDFLAG(ENABLE_EXTENSIONS)
base::WeakPtr<ProfileIODataQt> ProfileIODataQt::getWeakPtrOnUIThread()
{
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
return m_weakPtr;
}
void ProfileIODataQt::initializeOnIOThread()
{
m_networkDelegate.reset(new NetworkDelegateQt(this));
m_hostResolver = net::HostResolver::CreateStandaloneResolver(nullptr);
m_urlRequestContext.reset(new net::URLRequestContext());
m_urlRequestContext->set_network_delegate(m_networkDelegate.get());
m_urlRequestContext->set_enable_brotli(true);
m_urlRequestContext->set_host_resolver(m_hostResolver.get());
// this binds factory to io thread
m_weakPtr = m_weakPtrFactory.GetWeakPtr();
const std::lock_guard<QRecursiveMutex> lock(m_mutex);
generateAllStorage();
generateJobFactory();
setGlobalCertificateVerification();
m_initialized = true;
}
void ProfileIODataQt::initializeOnUIThread()
{
m_profileAdapter = m_profile->profileAdapter();
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
m_resourceContext.reset(new ResourceContextQt(this));
ProtocolHandlerRegistry* protocolHandlerRegistry =
ProtocolHandlerRegistryFactory::GetForBrowserContext(m_profile);
DCHECK(protocolHandlerRegistry);
m_protocolHandlerRegistryIOThreadDelegate = protocolHandlerRegistry->io_thread_delegate();
m_cookieDelegate = new CookieMonsterDelegateQt();
m_cookieDelegate->setClient(m_profile->profileAdapter()->cookieStore());
createProxyConfig();
}
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));
const std::lock_guard<QRecursiveMutex> 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);
// Q_ASSERT(!m_mutex.tryLock()); // assert locked
// We must stop all requests before deleting their backends.
if (m_storage) {
m_urlRequestContext->proxy_resolution_service()->OnShutdown();
m_restrictedCookieManagerBindings.CloseAllBindings();
m_cookieDelegate->setCookieMonster(nullptr);
m_storage->set_cookie_store(nullptr);
cancelAllUrlRequests();
// we need to get rid of dangling pointer due to coming storage deletion
m_urlRequestContext->set_http_transaction_factory(nullptr);
m_httpNetworkSession.reset();
m_transportSecurityPersister.reset();
}
m_storage.reset(new net::URLRequestContextStorage(m_urlRequestContext.get()));
net::ProxyConfigService *proxyConfigService = m_proxyConfigService.fetchAndStoreAcquire(0);
Q_ASSERT(proxyConfigService);
std::unique_ptr<net::CertVerifier> cert_verifier = net::CertVerifier::CreateDefault(s_certNetFetcher);
net::CertVerifier::Config config;
// Enable revocation checking:
config.enable_rev_checking = true;
// Mirroring Android WebView (we have no beef with Symantec, and our users might use them):
config.disable_symantec_enforcement = true;
cert_verifier->SetConfig(config);
m_storage->set_cert_verifier(std::move(cert_verifier));
std::unique_ptr<net::MultiLogCTVerifier> ct_verifier(new net::MultiLogCTVerifier());
std::vector<scoped_refptr<const net::CTLogVerifier>> ct_logs;
for (const auto &ct_log : certificate_transparency::GetKnownLogs()) {
scoped_refptr<const net::CTLogVerifier> log_verifier =
net::CTLogVerifier::Create(std::string(ct_log.log_key, ct_log.log_key_length),
ct_log.log_name);
if (!log_verifier)
continue;
ct_logs.push_back(std::move(log_verifier));
}
ct_verifier->AddLogs(ct_logs);
m_storage->set_cert_transparency_verifier(std::move(ct_verifier));
m_storage->set_ct_policy_enforcer(base::WrapUnique(new net::DefaultCTPolicyEnforcer()));
m_storage->set_ssl_config_service(std::make_unique<net::SSLConfigServiceDefaults>());
if (!m_httpAuthPreferences) {
m_httpAuthPreferences.reset(new net::HttpAuthPreferences());
std::string serverWhitelist = base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(switches::kAuthServerWhitelist);
m_httpAuthPreferences->SetServerWhitelist(serverWhitelist);
}
m_storage->set_http_auth_handler_factory(net::HttpAuthHandlerFactory::CreateDefault(
m_httpAuthPreferences.get()));
m_storage->set_transport_security_state(std::make_unique<net::TransportSecurityState>());
if (!m_dataPath.isEmpty()) {
scoped_refptr<base::SequencedTaskRunner> background_task_runner(
base::CreateSequencedTaskRunnerWithTraits(
{base::MayBlock(),
base::TaskPriority::BEST_EFFORT,
base::TaskShutdownBehavior::BLOCK_SHUTDOWN}));
m_transportSecurityPersister =
std::make_unique<net::TransportSecurityPersister>(
m_urlRequestContext->transport_security_state(),
toFilePath(m_dataPath),
background_task_runner);
};
m_storage->set_http_server_properties(std::unique_ptr<net::HttpServerProperties>(
new net::HttpServerPropertiesImpl));
// The System Proxy Resolver has issues on Windows with unconfigured network cards,
// which is why we want to use the v8 one
if (!m_dhcpPacFileFetcherFactory)
m_dhcpPacFileFetcherFactory.reset(new net::DhcpPacFileFetcherFactory);
proxy_resolver::mojom::ProxyResolverFactoryPtr proxyResolver(std::move(m_proxyResolverFactoryInterface));
m_storage->set_proxy_resolution_service(network::CreateProxyResolutionServiceUsingMojoFactory(
std::move(proxyResolver),
std::unique_ptr<net::ProxyConfigService>(proxyConfigService),
net::PacFileFetcherImpl::CreateWithFileUrlSupport(m_urlRequestContext.get()),
m_dhcpPacFileFetcherFactory->Create(m_urlRequestContext.get()),
m_urlRequestContext->host_resolver(),
nullptr /* NetLog */,
m_urlRequestContext->network_delegate()));
m_storage->set_ftp_auth_cache(std::make_unique<net::FtpAuthCache>());
}
void ProfileIODataQt::generateCookieStore()
{
Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
Q_ASSERT(m_urlRequestContext);
const std::lock_guard<QRecursiveMutex> lock(m_mutex);
// FIXME: Add code to remove the old channel-id database.
std::unique_ptr<net::CookieStore> cookieStore;
switch (m_persistentCookiesPolicy) {
case ProfileAdapter::NoPersistentCookies:
cookieStore = content::CreateCookieStore(
content::CookieStoreConfig(
base::FilePath(),
false,
false,
nullptr),
nullptr);
break;
case ProfileAdapter::AllowPersistentCookies:
cookieStore = content::CreateCookieStore(
content::CookieStoreConfig(
toFilePath(m_cookiesPath),
false,
true,
nullptr),
nullptr);
break;
case ProfileAdapter::ForcePersistentCookies:
cookieStore = content::CreateCookieStore(
content::CookieStoreConfig(
toFilePath(m_cookiesPath),
true,
true,
nullptr),
nullptr);
break;
}
net::CookieMonster * const cookieMonster = static_cast<net::CookieMonster*>(cookieStore.get());
m_cookieDelegate->setCookieMonster(cookieMonster);
m_storage->set_cookie_store(std::move(cookieStore));
const std::vector<std::string> cookieableSchemes(kCookieableSchemes,
kCookieableSchemes + base::size(kCookieableSchemes));
cookieMonster->SetCookieableSchemes(cookieableSchemes, base::DoNothing());
}
void ProfileIODataQt::generateUserAgent()
{
Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
Q_ASSERT(m_urlRequestContext);
Q_ASSERT(m_storage);
const std::lock_guard<QRecursiveMutex> lock(m_mutex);
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);
const std::lock_guard<QRecursiveMutex> lock(m_mutex);
net::HttpCache::DefaultBackend* main_backend = 0;
switch (m_httpCacheType) {
case ProfileAdapter::MemoryHttpCache:
main_backend =
new net::HttpCache::DefaultBackend(
net::MEMORY_CACHE,
net::CACHE_BACKEND_DEFAULT,
base::FilePath(),
m_httpCacheMaxSize
);
break;
case ProfileAdapter::DiskHttpCache:
main_backend =
new net::HttpCache::DefaultBackend(
net::DISK_CACHE,
net::CACHE_BACKEND_DEFAULT,
toFilePath(m_httpCachePath),
m_httpCacheMaxSize
);
break;
case ProfileAdapter::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())) {
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);
const std::lock_guard<QRecursiveMutex> 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::BEST_EFFORT,
base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN}));
jobFactory->SetProtocolHandler(url::kFileScheme,
std::make_unique<net::FileProtocolHandler>(taskRunner));
jobFactory->SetProtocolHandler(url::kFtpScheme,
net::FtpProtocolHandler::Create(m_urlRequestContext->host_resolver(), m_urlRequestContext->ftp_auth_cache()));
m_installedCustomSchemes = m_customUrlSchemes;
for (const QByteArray &scheme : qAsConst(m_installedCustomSchemes)) {
jobFactory->SetProtocolHandler(scheme.toStdString(),
std::unique_ptr<net::URLRequestJobFactory::ProtocolHandler>(
new CustomProtocolHandler(m_profileAdapter)));
}
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();
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);
const std::lock_guard<QRecursiveMutex> lock(m_mutex);
m_updateJobFactory = false;
if (m_customUrlSchemes == m_installedCustomSchemes)
return;
for (const QByteArray &scheme : qAsConst(m_installedCustomSchemes)) {
m_baseJobFactory->SetProtocolHandler(scheme.toStdString(), nullptr);
}
m_installedCustomSchemes = m_customUrlSchemes;
for (const QByteArray &scheme : qAsConst(m_installedCustomSchemes)) {
m_baseJobFactory->SetProtocolHandler(scheme.toStdString(),
std::unique_ptr<net::URLRequestJobFactory::ProtocolHandler>(
new CustomProtocolHandler(m_profileAdapter)));
}
}
void ProfileIODataQt::setGlobalCertificateVerification()
{
Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
const std::lock_guard<QRecursiveMutex> lock(m_mutex);
if (m_useForGlobalCertificateVerification) {
#if defined(USE_NSS_CERTS)
// Set request context used by NSS for OCSP requests.
net::SetURLRequestContextForNSSHttpIO(m_urlRequestContext.get());
#endif
if (!s_certNetFetcher)
s_certNetFetcher = base::MakeRefCounted<net::CertNetFetcherImpl>();
s_certNetFetcher->SetURLRequestContext(m_urlRequestContext.get());
}
}
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_persistentCookiesPolicy = m_profileAdapter->persistentCookiesPolicy();
m_cookiesPath = m_profileAdapter->cookiesPath();
m_httpAcceptLanguage = m_profileAdapter->httpAcceptLanguage();
m_httpUserAgent = m_profileAdapter->httpUserAgent();
m_httpCacheType = m_profileAdapter->httpCacheType();
m_httpCachePath = m_profileAdapter->httpCachePath();
m_httpCacheMaxSize = m_profileAdapter->httpCacheMaxSize();
m_customUrlSchemes = m_profileAdapter->customUrlSchemes();
m_useForGlobalCertificateVerification = m_profileAdapter->isUsedForGlobalCertificateVerification();
m_dataPath = m_profileAdapter->dataPath();
}
void ProfileIODataQt::requestStorageGeneration() {
Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
const std::lock_guard<QRecursiveMutex> lock(m_mutex);
if (m_initialized && !m_updateAllStorage) {
m_updateAllStorage = true;
createProxyConfig();
base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::IO},
base::BindOnce(&ProfileIODataQt::generateAllStorage, m_weakPtr));
}
}
// TODO(miklocek): mojofy ProxyConfigServiceQt
void ProfileIODataQt::createProxyConfig()
{
Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
const std::lock_guard<QRecursiveMutex> lock(m_mutex);
// 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);
net::ProxyConfigWithAnnotation initialConfig;
ProxyPrefs::ConfigState initialConfigState = PrefProxyConfigTrackerImpl::ReadPrefConfig(
m_profileAdapter->profile()->GetPrefs(), &initialConfig);
m_proxyConfigService =
new ProxyConfigServiceQt(
net::ProxyResolutionService::CreateSystemProxyConfigService(
base::CreateSingleThreadTaskRunnerWithTraits({content::BrowserThread::IO})),
initialConfig, initialConfigState);
//pass interface to io thread
m_proxyResolverFactoryInterface = ChromeMojoProxyResolverFactory::CreateWithSelfOwnedReceiver();
}
void ProfileIODataQt::updateStorageSettings()
{
Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
const std::lock_guard<QRecursiveMutex> lock(m_mutex);
setFullConfiguration();
base::Token groupId = content::BrowserContext::GetServiceInstanceGroupFor(m_profile);
if (file::GetUserDirForInstanceGroup(groupId) != toFilePath(m_profileAdapter->dataPath())) {
file::ForgetServiceInstanceGroupUserDirAssociation(groupId);
file::AssociateServiceInstanceGroupWithUserDir(groupId, toFilePath(m_profileAdapter->dataPath()));
}
if (!m_pendingStorageRequestGeneration)
requestStorageGeneration();
}
void ProfileIODataQt::updateCookieStore()
{
Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
const std::lock_guard<QRecursiveMutex> lock(m_mutex);
m_persistentCookiesPolicy = m_profileAdapter->persistentCookiesPolicy();
m_cookiesPath = m_profileAdapter->cookiesPath();
if (!m_pendingStorageRequestGeneration)
requestStorageGeneration();
}
void ProfileIODataQt::updateUserAgent()
{
Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
const std::lock_guard<QRecursiveMutex> lock(m_mutex);
m_httpAcceptLanguage = m_profileAdapter->httpAcceptLanguage();
m_httpUserAgent = m_profileAdapter->httpUserAgent();
if (!m_pendingStorageRequestGeneration)
requestStorageGeneration();
}
void ProfileIODataQt::updateHttpCache()
{
Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
const std::lock_guard<QRecursiveMutex> lock(m_mutex);
m_httpCacheType = m_profileAdapter->httpCacheType();
m_httpCachePath = m_profileAdapter->httpCachePath();
m_httpCacheMaxSize = m_profileAdapter->httpCacheMaxSize();
if (m_httpCacheType == ProfileAdapter::NoCache) {
m_pendingStorageRequestGeneration = true;
content::BrowsingDataRemover *remover =
content::BrowserContext::GetBrowsingDataRemover(m_profileAdapter->profile());
remover->AddObserver(&m_removerObserver);
remover->RemoveAndReply(base::Time(), base::Time::Max(),
content::BrowsingDataRemover::DATA_TYPE_CACHE,
content::BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB |
content::BrowsingDataRemover::ORIGIN_TYPE_PROTECTED_WEB,
&m_removerObserver);
return;
}
if (!m_pendingStorageRequestGeneration)
requestStorageGeneration();
}
void ProfileIODataQt::updateJobFactory()
{
Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
const std::lock_guard<QRecursiveMutex> lock(m_mutex);
m_customUrlSchemes = m_profileAdapter->customUrlSchemes();
if (m_initialized && !m_updateJobFactory) {
m_updateJobFactory = true;
base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::IO},
base::BindOnce(&ProfileIODataQt::regenerateJobFactory, m_weakPtr));
}
}
void ProfileIODataQt::updateRequestInterceptor()
{
Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
const std::lock_guard<QRecursiveMutex> lock(m_mutex);
m_requestInterceptor = m_profileAdapter->requestInterceptor();
m_hasPageInterceptors = m_profileAdapter->hasPageRequestInterceptor();
if (m_requestInterceptor)
m_isInterceptorDeprecated = m_requestInterceptor->property("deprecated").toBool();
else
m_isInterceptorDeprecated = false;
// We in this case do not need to regenerate any Chromium classes.
}
bool ProfileIODataQt::isInterceptorDeprecated() const
{
return m_isInterceptorDeprecated;
}
QWebEngineUrlRequestInterceptor *ProfileIODataQt::acquireInterceptor()
{
m_mutex.lock();
return m_requestInterceptor;
}
QWebEngineUrlRequestInterceptor *ProfileIODataQt::requestInterceptor()
{
return m_requestInterceptor;
}
bool ProfileIODataQt::hasPageInterceptors()
{
// used in NetworkDelegateQt::OnBeforeURLRequest
Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
return m_hasPageInterceptors;
}
void ProfileIODataQt::releaseInterceptor()
{
m_mutex.unlock();
}
bool ProfileIODataQt::canSetCookie(const QUrl &firstPartyUrl, const QByteArray &cookieLine, const QUrl &url) const
{
return m_cookieDelegate->canSetCookie(firstPartyUrl,cookieLine, url);
}
bool ProfileIODataQt::canGetCookies(const QUrl &firstPartyUrl, const QUrl &url) const
{
return m_cookieDelegate->canGetCookies(firstPartyUrl, url);
}
void ProfileIODataQt::updateUsedForGlobalCertificateVerification()
{
Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
const std::lock_guard<QRecursiveMutex> lock(m_mutex);
if (m_useForGlobalCertificateVerification == m_profileAdapter->isUsedForGlobalCertificateVerification())
return;
m_useForGlobalCertificateVerification = m_profileAdapter->isUsedForGlobalCertificateVerification();
if (m_useForGlobalCertificateVerification)
base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::IO},
base::BindOnce(&ProfileIODataQt::setGlobalCertificateVerification, m_weakPtr));
}
#if QT_CONFIG(ssl)
ClientCertificateStoreData *ProfileIODataQt::clientCertificateStoreData()
{
return m_clientCertificateStoreData;
}
#endif
std::unique_ptr<net::ClientCertStore> ProfileIODataQt::CreateClientCertStore()
{
#if QT_CONFIG(ssl)
return std::unique_ptr<net::ClientCertStore>(new ClientCertOverrideStore(m_clientCertificateStoreData));
#else
return nullptr;
#endif
}
void ProfileIODataQt::CreateRestrictedCookieManager(network::mojom::RestrictedCookieManagerRequest request,
network::mojom::RestrictedCookieManagerRole role,
const url::Origin &origin,
bool is_service_worker,
int32_t process_id,
int32_t routing_id)
{
Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
m_restrictedCookieManagerBindings.AddBinding(
std::make_unique<RestrictedCookieManagerQt>(
m_weakPtr,
role, urlRequestContext()->cookie_store(),
&m_cookieSettings, origin,
is_service_worker, process_id, routing_id),
std::move(request));
}
// static
ProfileIODataQt *ProfileIODataQt::FromBrowserContext(content::BrowserContext *browser_context)
{
Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
return static_cast<ProfileQt *>(browser_context)->m_profileIOData.get();
}
// static
ProfileIODataQt *ProfileIODataQt::FromResourceContext(content::ResourceContext *resource_context)
{
Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
return static_cast<ResourceContextQt *>(resource_context)->m_io_data;
}
void ProfileIODataQt::removeBrowsingDataRemoverObserver()
{
content::BrowsingDataRemover *remover =
content::BrowserContext::GetBrowsingDataRemover(m_profileAdapter->profile());
remover->RemoveObserver(&m_removerObserver);
}
BrowsingDataRemoverObserverQt::BrowsingDataRemoverObserverQt(ProfileIODataQt *profileIOData)
: m_profileIOData(profileIOData)
{
}
void BrowsingDataRemoverObserverQt::OnBrowsingDataRemoverDone()
{
Q_ASSERT(m_profileIOData->m_pendingStorageRequestGeneration);
m_profileIOData->requestStorageGeneration();
m_profileIOData->removeBrowsingDataRemoverObserver();
m_profileIOData->m_pendingStorageRequestGeneration = false;
}
} // namespace QtWebEngineCore