| /**************************************************************************** |
| ** |
| ** 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 |