diff options
author | droger <droger@chromium.org> | 2015-12-10 09:48:39 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-12-10 17:49:24 +0000 |
commit | 7fbc7a27199c559d07f7a4a6da745a0e712e8d68 (patch) | |
tree | 7a3dc939278313fcaa127003963d9127464bf47d /ios | |
parent | 972507434589250e845a8c38a0d220eb3d5aed5c (diff) | |
download | chromium_src-7fbc7a27199c559d07f7a4a6da745a0e712e8d68.zip chromium_src-7fbc7a27199c559d07f7a4a6da745a0e712e8d68.tar.gz chromium_src-7fbc7a27199c559d07f7a4a6da745a0e712e8d68.tar.bz2 |
Upstream ChromeBrowserStateIOData and related classes.
BUG=560816
Review URL: https://codereview.chromium.org/1515613002
Cr-Commit-Position: refs/heads/master@{#364393}
Diffstat (limited to 'ios')
13 files changed, 2025 insertions, 0 deletions
diff --git a/ios/chrome/browser/BUILD.gn b/ios/chrome/browser/BUILD.gn index c16f90f..e096b28 100644 --- a/ios/chrome/browser/BUILD.gn +++ b/ios/chrome/browser/BUILD.gn @@ -68,6 +68,12 @@ source_set("browser") { "browser_state/browser_state_keyed_service_factories.mm", "browser_state/browser_state_otr_helper.cc", "browser_state/browser_state_otr_helper.h", + "browser_state/chrome_browser_state_impl_io_data.cc", + "browser_state/chrome_browser_state_impl_io_data.h", + "browser_state/chrome_browser_state_io_data.cc", + "browser_state/chrome_browser_state_io_data.h", + "browser_state/off_the_record_chrome_browser_state_io_data.h", + "browser_state/off_the_record_chrome_browser_state_io_data.mm", "browser_state_metrics/browser_state_metrics.cc", "browser_state_metrics/browser_state_metrics.h", "browsing_data_change_listening.h", @@ -227,6 +233,8 @@ source_set("browser") { "net/ios_chrome_http_user_agent_settings.h", "net/ios_chrome_network_delegate.cc", "net/ios_chrome_network_delegate.h", + "net/ios_chrome_url_request_context_getter.cc", + "net/ios_chrome_url_request_context_getter.h", "net/metrics_network_client.h", "net/metrics_network_client.mm", "net/metrics_network_client_manager.h", @@ -455,6 +463,7 @@ source_set("browser") { "//base", "//base:prefs", "//breakpad:client", + "//components/about_handler", "//components/autofill/core/browser", "//components/autofill/core/common", "//components/autofill/ios/browser", @@ -464,6 +473,7 @@ source_set("browser") { "//components/browser_sync/common", "//components/component_updater", "//components/content_settings/core/browser", + "//components/cookie_config", "//components/crash/core/browser", "//components/crash/core/common", "//components/data_reduction_proxy/core/common", diff --git a/ios/chrome/browser/DEPS b/ios/chrome/browser/DEPS index c7e2072..20716e4 100644 --- a/ios/chrome/browser/DEPS +++ b/ios/chrome/browser/DEPS @@ -1,6 +1,7 @@ include_rules = [ "+breakpad/src/client/ios", "+breakpad/src/common", + "+components/about_handler", "+components/autofill/core/browser", "+components/autofill/core/common", "+components/autofill/ios/browser", @@ -9,6 +10,7 @@ include_rules = [ "+components/browser_sync/common", "+components/component_updater", "+components/content_settings/core", + "+components/cookie_config", "+components/crash/core/browser", "+components/crash/core/common", "+components/data_reduction_proxy/core/browser", diff --git a/ios/chrome/browser/browser_state/chrome_browser_state_impl_io_data.cc b/ios/chrome/browser/browser_state/chrome_browser_state_impl_io_data.cc new file mode 100644 index 0000000..c009611 --- /dev/null +++ b/ios/chrome/browser/browser_state/chrome_browser_state_impl_io_data.cc @@ -0,0 +1,412 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ios/chrome/browser/browser_state/chrome_browser_state_impl_io_data.h" + +#include <set> + +#include "base/bind.h" +#include "base/callback.h" +#include "base/logging.h" +#include "base/memory/scoped_ptr.h" +#include "base/prefs/json_pref_store.h" +#include "base/prefs/pref_filter.h" +#include "base/prefs/pref_service.h" +#include "base/sequenced_task_runner.h" +#include "base/threading/sequenced_worker_pool.h" +#include "base/threading/worker_pool.h" +#include "components/cookie_config/cookie_store_util.h" +#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.h" +#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_settings.h" +#include "components/data_reduction_proxy/core/browser/data_store_impl.h" +#include "components/domain_reliability/monitor.h" +#include "components/net_log/chrome_net_log.h" +#include "ios/chrome/browser/application_context.h" +#include "ios/chrome/browser/chrome_constants.h" +#include "ios/chrome/browser/data_reduction_proxy/ios_chrome_data_reduction_proxy_io_data.h" +#include "ios/chrome/browser/data_reduction_proxy/ios_chrome_data_reduction_proxy_settings.h" +#include "ios/chrome/browser/data_reduction_proxy/ios_chrome_data_reduction_proxy_settings_factory.h" +#include "ios/chrome/browser/ios_chrome_io_thread.h" +#include "ios/chrome/browser/net/cookie_util.h" +#include "ios/chrome/browser/net/http_server_properties_manager_factory.h" +#include "ios/chrome/browser/net/ios_chrome_network_delegate.h" +#include "ios/chrome/browser/net/ios_chrome_url_request_context_getter.h" +#include "ios/chrome/browser/pref_names.h" +#include "ios/net/cookies/cookie_store_ios.h" +#include "ios/public/provider/chrome/browser/browser_state/chrome_browser_state.h" +#include "ios/web/public/web_thread.h" +#include "net/base/cache_type.h" +#include "net/base/sdch_manager.h" +#include "net/extras/sqlite/sqlite_channel_id_store.h" +#include "net/http/http_cache.h" +#include "net/http/http_network_session.h" +#include "net/http/http_server_properties_manager.h" +#include "net/sdch/sdch_owner.h" +#include "net/ssl/channel_id_service.h" +#include "net/ssl/default_channel_id_store.h" +#include "net/url_request/url_request_intercepting_job_factory.h" +#include "net/url_request/url_request_job_factory_impl.h" + +ChromeBrowserStateImplIOData::Handle::Handle( + ios::ChromeBrowserState* browser_state) + : io_data_(new ChromeBrowserStateImplIOData), + browser_state_(browser_state), + initialized_(false) { + DCHECK_CURRENTLY_ON_WEB_THREAD(web::WebThread::UI); + DCHECK(browser_state); +} + +ChromeBrowserStateImplIOData::Handle::~Handle() { + DCHECK_CURRENTLY_ON_WEB_THREAD(web::WebThread::UI); + if (io_data_->http_server_properties_manager_) + io_data_->http_server_properties_manager_->ShutdownOnPrefThread(); + + // io_data_->data_reduction_proxy_io_data() might be NULL if Init() was + // never called. + if (io_data_->data_reduction_proxy_io_data()) + io_data_->data_reduction_proxy_io_data()->ShutdownOnUIThread(); + + io_data_->ShutdownOnUIThread(GetAllContextGetters().Pass()); +} + +void ChromeBrowserStateImplIOData::Handle::Init( + const base::FilePath& cookie_path, + const base::FilePath& channel_id_path, + const base::FilePath& cache_path, + int cache_max_size, + const base::FilePath& profile_path) { + DCHECK_CURRENTLY_ON_WEB_THREAD(web::WebThread::UI); + DCHECK(!io_data_->lazy_params_); + + LazyParams* lazy_params = new LazyParams(); + + lazy_params->cookie_path = cookie_path; + lazy_params->channel_id_path = channel_id_path; + lazy_params->cache_path = cache_path; + lazy_params->cache_max_size = cache_max_size; + io_data_->lazy_params_.reset(lazy_params); + + // Keep track of profile path and cache sizes separately so we can use them + // on demand when creating storage isolated URLRequestContextGetters. + io_data_->profile_path_ = profile_path; + io_data_->app_cache_max_size_ = cache_max_size; + + io_data_->InitializeMetricsEnabledStateOnUIThread(); + + // TODO(tbansal): Move this to IO thread once the data reduction proxy + // params are unified into a single object. + bool enable_quic_for_data_reduction_proxy = + IOSChromeIOThread::ShouldEnableQuicForDataReductionProxy(); + + io_data_->set_data_reduction_proxy_io_data( + CreateIOSChromeDataReductionProxyIOData( + GetApplicationContext()->GetIOSChromeIOThread()->net_log(), + browser_state_->GetPrefs(), + web::WebThread::GetTaskRunnerForThread(web::WebThread::IO), + web::WebThread::GetTaskRunnerForThread(web::WebThread::UI), + enable_quic_for_data_reduction_proxy) + .Pass()); + + base::SequencedWorkerPool* pool = web::WebThread::GetBlockingPool(); + scoped_refptr<base::SequencedTaskRunner> db_task_runner = + pool->GetSequencedTaskRunnerWithShutdownBehavior( + pool->GetSequenceToken(), + base::SequencedWorkerPool::SKIP_ON_SHUTDOWN); + scoped_ptr<data_reduction_proxy::DataStore> store( + new data_reduction_proxy::DataStoreImpl(profile_path)); + IOSChromeDataReductionProxySettingsFactory::GetForBrowserState(browser_state_) + ->InitDataReductionProxySettings( + io_data_->data_reduction_proxy_io_data(), browser_state_->GetPrefs(), + browser_state_->GetRequestContext(), store.Pass(), + web::WebThread::GetTaskRunnerForThread(web::WebThread::UI), + db_task_runner); +} + +scoped_refptr<IOSChromeURLRequestContextGetter> +ChromeBrowserStateImplIOData::Handle::CreateMainRequestContextGetter( + ProtocolHandlerMap* protocol_handlers, + PrefService* local_state, + IOSChromeIOThread* io_thread) const { + DCHECK_CURRENTLY_ON_WEB_THREAD(web::WebThread::UI); + LazyInitialize(); + DCHECK(!main_request_context_getter_.get()); + main_request_context_getter_ = + IOSChromeURLRequestContextGetter::Create(io_data_, protocol_handlers); + + return main_request_context_getter_; +} + +scoped_refptr<IOSChromeURLRequestContextGetter> +ChromeBrowserStateImplIOData::Handle::CreateIsolatedAppRequestContextGetter( + const base::FilePath& partition_path) const { + DCHECK_CURRENTLY_ON_WEB_THREAD(web::WebThread::UI); + // Check that the partition_path is not the same as the base profile path. We + // expect isolated partition, which will never go to the default profile path. + CHECK(partition_path != browser_state_->GetStatePath()); + LazyInitialize(); + + // Keep a map of request context getters, one per requested storage partition. + IOSChromeURLRequestContextGetterMap::iterator iter = + app_request_context_getter_map_.find(partition_path); + if (iter != app_request_context_getter_map_.end()) + return iter->second; + + IOSChromeURLRequestContextGetter* context = + IOSChromeURLRequestContextGetter::CreateForIsolatedApp( + browser_state_->GetRequestContext(), io_data_, partition_path); + app_request_context_getter_map_[partition_path] = context; + return context; +} + +ChromeBrowserStateIOData* ChromeBrowserStateImplIOData::Handle::io_data() + const { + LazyInitialize(); + return io_data_; +} + +void ChromeBrowserStateImplIOData::Handle::ClearNetworkingHistorySince( + base::Time time, + const base::Closure& completion) { + DCHECK_CURRENTLY_ON_WEB_THREAD(web::WebThread::UI); + LazyInitialize(); + + web::WebThread::PostTask( + web::WebThread::IO, FROM_HERE, + base::Bind( + &ChromeBrowserStateImplIOData::ClearNetworkingHistorySinceOnIOThread, + base::Unretained(io_data_), time, completion)); +} + +void ChromeBrowserStateImplIOData::Handle::LazyInitialize() const { + DCHECK_CURRENTLY_ON_WEB_THREAD(web::WebThread::UI); + if (initialized_) + return; + + // Set initialized_ to true at the beginning in case any of the objects + // below try to get the ResourceContext pointer. + initialized_ = true; + PrefService* pref_service = browser_state_->GetPrefs(); + io_data_->http_server_properties_manager_ = + HttpServerPropertiesManagerFactory::CreateManager(pref_service); + io_data_->set_http_server_properties(scoped_ptr<net::HttpServerProperties>( + io_data_->http_server_properties_manager_)); + io_data_->safe_browsing_enabled()->Init(prefs::kSafeBrowsingEnabled, + pref_service); + io_data_->safe_browsing_enabled()->MoveToThread( + web::WebThread::GetTaskRunnerForThread(web::WebThread::IO)); + io_data_->InitializeOnUIThread(browser_state_); +} + +scoped_ptr<ChromeBrowserStateIOData::IOSChromeURLRequestContextGetterVector> +ChromeBrowserStateImplIOData::Handle::GetAllContextGetters() { + IOSChromeURLRequestContextGetterMap::iterator iter; + scoped_ptr<IOSChromeURLRequestContextGetterVector> context_getters( + new IOSChromeURLRequestContextGetterVector()); + + iter = app_request_context_getter_map_.begin(); + for (; iter != app_request_context_getter_map_.end(); ++iter) + context_getters->push_back(iter->second); + + if (main_request_context_getter_.get()) + context_getters->push_back(main_request_context_getter_); + + return context_getters.Pass(); +} + +ChromeBrowserStateImplIOData::LazyParams::LazyParams() : cache_max_size(0) {} + +ChromeBrowserStateImplIOData::LazyParams::~LazyParams() {} + +ChromeBrowserStateImplIOData::ChromeBrowserStateImplIOData() + : ChromeBrowserStateIOData( + ios::ChromeBrowserStateType::REGULAR_BROWSER_STATE), + http_server_properties_manager_(nullptr), + app_cache_max_size_(0) {} + +ChromeBrowserStateImplIOData::~ChromeBrowserStateImplIOData() {} + +void ChromeBrowserStateImplIOData::InitializeInternal( + scoped_ptr<IOSChromeNetworkDelegate> chrome_network_delegate, + ProfileParams* profile_params, + ProtocolHandlerMap* protocol_handlers) const { + // Set up a persistent store for use by the network stack on the IO thread. + base::FilePath network_json_store_filepath( + profile_path_.Append(kIOSChromeNetworkPersistentStateFilename)); + network_json_store_ = new JsonPrefStore( + network_json_store_filepath, + JsonPrefStore::GetTaskRunnerForFile(network_json_store_filepath, + web::WebThread::GetBlockingPool()), + scoped_ptr<PrefFilter>()); + network_json_store_->ReadPrefsAsync(nullptr); + + net::URLRequestContext* main_context = main_request_context(); + + IOSChromeIOThread* const io_thread = profile_params->io_thread; + IOSChromeIOThread::Globals* const io_thread_globals = io_thread->globals(); + + ApplyProfileParamsToContext(main_context); + + if (http_server_properties_manager_) + http_server_properties_manager_->InitializeOnNetworkThread(); + + main_context->set_transport_security_state(transport_security_state()); + + main_context->set_net_log(io_thread->net_log()); + + network_delegate_ = + data_reduction_proxy_io_data() + ->CreateNetworkDelegate(chrome_network_delegate.Pass(), true) + .Pass(); + + main_context->set_network_delegate(network_delegate_.get()); + + main_context->set_http_server_properties(http_server_properties()); + + main_context->set_host_resolver(io_thread_globals->host_resolver.get()); + + main_context->set_http_auth_handler_factory( + io_thread_globals->http_auth_handler_factory.get()); + + main_context->set_proxy_service(proxy_service()); + main_context->set_backoff_manager( + io_thread_globals->url_request_backoff_manager.get()); + + scoped_refptr<net::CookieStore> cookie_store = NULL; + net::ChannelIDService* channel_id_service = NULL; + + // Set up cookie store. + if (!cookie_store.get()) { + DCHECK(!lazy_params_->cookie_path.empty()); + cookie_util::CookieStoreConfig ios_cookie_config( + lazy_params_->cookie_path, + cookie_util::CookieStoreConfig::RESTORED_SESSION_COOKIES, + cookie_util::CookieStoreConfig::COOKIE_STORE_IOS, + cookie_config::GetCookieCryptoDelegate()); + cookie_store = cookie_util::CreateCookieStore(ios_cookie_config); + + if (profile_params->path.BaseName().value() == + kIOSChromeInitialBrowserState) { + // Enable metrics on the default profile, not secondary profiles. + static_cast<net::CookieStoreIOS*>(cookie_store.get()) + ->SetMetricsEnabled(); + } + } + + main_context->set_cookie_store(cookie_store.get()); + + // Set up server bound cert service. + if (!channel_id_service) { + DCHECK(!lazy_params_->channel_id_path.empty()); + + scoped_refptr<net::SQLiteChannelIDStore> channel_id_db = + new net::SQLiteChannelIDStore( + lazy_params_->channel_id_path, + web::WebThread::GetBlockingPool()->GetSequencedTaskRunner( + web::WebThread::GetBlockingPool()->GetSequenceToken())); + channel_id_service = new net::ChannelIDService( + new net::DefaultChannelIDStore(channel_id_db.get()), + base::WorkerPool::GetTaskRunner(true)); + } + + set_channel_id_service(channel_id_service); + main_context->set_channel_id_service(channel_id_service); + + scoped_ptr<net::HttpCache::BackendFactory> main_backend( + new net::HttpCache::DefaultBackend( + net::DISK_CACHE, net::CACHE_BACKEND_BLOCKFILE, + lazy_params_->cache_path, lazy_params_->cache_max_size, + web::WebThread::GetTaskRunnerForThread(web::WebThread::CACHE))); + http_network_session_ = CreateHttpNetworkSession(*profile_params); + main_http_factory_ = + CreateMainHttpFactory(http_network_session_.get(), main_backend.Pass()); + main_context->set_http_transaction_factory(main_http_factory_.get()); + + scoped_ptr<net::URLRequestJobFactoryImpl> main_job_factory( + new net::URLRequestJobFactoryImpl()); + InstallProtocolHandlers(main_job_factory.get(), protocol_handlers); + + // The data reduction proxy interceptor should be as close to the network as + // possible. + URLRequestInterceptorScopedVector request_interceptors; + request_interceptors.insert( + request_interceptors.begin(), + data_reduction_proxy_io_data()->CreateInterceptor().release()); + main_job_factory_ = SetUpJobFactoryDefaults(main_job_factory.Pass(), + request_interceptors.Pass(), + main_context->network_delegate()); + main_context->set_job_factory(main_job_factory_.get()); + main_context->set_network_quality_estimator( + io_thread_globals->network_quality_estimator.get()); + + // Setup SDCH for this profile. + sdch_manager_.reset(new net::SdchManager); + sdch_policy_.reset(new net::SdchOwner(sdch_manager_.get(), main_context)); + main_context->set_sdch_manager(sdch_manager_.get()); + sdch_policy_->EnablePersistentStorage(network_json_store_.get()); + + lazy_params_.reset(); +} + +net::URLRequestContext* +ChromeBrowserStateImplIOData::InitializeAppRequestContext( + net::URLRequestContext* main_context) const { + // Copy most state from the main context. + AppRequestContext* context = new AppRequestContext(); + context->CopyFrom(main_context); + + // Use a separate HTTP disk cache for isolated apps. + scoped_ptr<net::HttpCache::BackendFactory> app_backend = + net::HttpCache::DefaultBackend::InMemory(0); + scoped_ptr<net::HttpCache> app_http_cache = + CreateHttpFactory(http_network_session_.get(), app_backend.Pass()); + + cookie_util::CookieStoreConfig ios_cookie_config( + base::FilePath(), + cookie_util::CookieStoreConfig::EPHEMERAL_SESSION_COOKIES, + cookie_util::CookieStoreConfig::COOKIE_STORE_IOS, nullptr); + scoped_refptr<net::CookieStore> cookie_store = + cookie_util::CreateCookieStore(ios_cookie_config); + + // Transfer ownership of the cookies and cache to AppRequestContext. + context->SetCookieStore(cookie_store.get()); + context->SetHttpTransactionFactory(app_http_cache.Pass()); + + scoped_ptr<net::URLRequestJobFactoryImpl> job_factory( + new net::URLRequestJobFactoryImpl()); + // The data reduction proxy interceptor should be as close to the network as + // possible. + URLRequestInterceptorScopedVector request_interceptors; + request_interceptors.insert( + request_interceptors.begin(), + data_reduction_proxy_io_data()->CreateInterceptor().release()); + scoped_ptr<net::URLRequestJobFactory> top_job_factory( + SetUpJobFactoryDefaults(job_factory.Pass(), request_interceptors.Pass(), + main_context->network_delegate())); + context->SetJobFactory(top_job_factory.Pass()); + + return context; +} + +net::URLRequestContext* +ChromeBrowserStateImplIOData::AcquireIsolatedAppRequestContext( + net::URLRequestContext* main_context) const { + // We create per-app contexts on demand, unlike the others above. + net::URLRequestContext* app_request_context = + InitializeAppRequestContext(main_context); + DCHECK(app_request_context); + return app_request_context; +} + +void ChromeBrowserStateImplIOData::ClearNetworkingHistorySinceOnIOThread( + base::Time time, + const base::Closure& completion) { + DCHECK_CURRENTLY_ON_WEB_THREAD(web::WebThread::IO); + DCHECK(initialized()); + + DCHECK(transport_security_state()); + // Completes synchronously. + transport_security_state()->DeleteAllDynamicDataSince(time); + DCHECK(http_server_properties_manager_); + http_server_properties_manager_->Clear(completion); +} diff --git a/ios/chrome/browser/browser_state/chrome_browser_state_impl_io_data.h b/ios/chrome/browser/browser_state/chrome_browser_state_impl_io_data.h new file mode 100644 index 0000000..e374a43 --- /dev/null +++ b/ios/chrome/browser/browser_state/chrome_browser_state_impl_io_data.h @@ -0,0 +1,161 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_BROWSER_STATE_CHROME_BROWSER_STATE_IMPL_IO_DATA_H_ +#define IOS_CHROME_BROWSER_BROWSER_STATE_CHROME_BROWSER_STATE_IMPL_IO_DATA_H_ + +#include "base/basictypes.h" +#include "base/callback_forward.h" +#include "base/memory/ref_counted.h" +#include "base/prefs/pref_store.h" +#include "ios/chrome/browser/browser_state/chrome_browser_state_io_data.h" +#include "ios/chrome/browser/net/net_types.h" + +class JsonPrefStore; + +namespace data_reduction_proxy { +class DataReductionProxyNetworkDelegate; +} + +namespace ios { +class ChromeBrowserState; +} + +namespace net { +class HttpNetworkSession; +class HttpServerPropertiesManager; +class HttpTransactionFactory; +class SdchManager; +class SdchOwner; +} // namespace net + +class ChromeBrowserStateImplIOData : public ChromeBrowserStateIOData { + public: + class Handle { + public: + explicit Handle(ios::ChromeBrowserState* browser_state); + ~Handle(); + + // Init() must be called before ~Handle(). It records most of the + // parameters needed to construct a ChromeURLRequestContextGetter. + void Init(const base::FilePath& cookie_path, + const base::FilePath& channel_id_path, + const base::FilePath& cache_path, + int cache_max_size, + const base::FilePath& profile_path); + + // These Create*ContextGetter() functions are only exposed because the + // circular relationship between ChromeBrowserState, + // ChromeBrowserStateIOData::Handle, and the + // IOSChromeURLRequestContextGetter factories requires ChromeBrowserState be + // able to call these functions. + scoped_refptr<IOSChromeURLRequestContextGetter> + CreateMainRequestContextGetter(ProtocolHandlerMap* protocol_handlers, + PrefService* local_state, + IOSChromeIOThread* io_thread) const; + scoped_refptr<IOSChromeURLRequestContextGetter> + CreateIsolatedAppRequestContextGetter( + const base::FilePath& partition_path) const; + + ChromeBrowserStateIOData* io_data() const; + + // Deletes all network related data since |time|. It deletes transport + // security state since |time| and also deletes HttpServerProperties data. + // Works asynchronously, however if the |completion| callback is non-null, + // it will be posted on the UI thread once the removal process completes. + void ClearNetworkingHistorySince(base::Time time, + const base::Closure& completion); + + private: + typedef std::map<base::FilePath, + scoped_refptr<IOSChromeURLRequestContextGetter>> + IOSChromeURLRequestContextGetterMap; + + // Lazily initialize ProfileParams. We do this on the calls to + // Get*RequestContextGetter(), so we only initialize ProfileParams right + // before posting a task to the IO thread to start using them. This prevents + // objects that are supposed to be deleted on the IO thread, but are created + // on the UI thread from being unnecessarily initialized. + void LazyInitialize() const; + + // Collect references to context getters in reverse order, i.e. last item + // will be main request getter. This list is passed to |io_data_| + // for invalidation on IO thread. + scoped_ptr<IOSChromeURLRequestContextGetterVector> GetAllContextGetters(); + + // The getters will be invalidated on the IO thread before + // ChromeBrowserStateIOData instance is deleted. + mutable scoped_refptr<IOSChromeURLRequestContextGetter> + main_request_context_getter_; + mutable IOSChromeURLRequestContextGetterMap app_request_context_getter_map_; + ChromeBrowserStateImplIOData* const io_data_; + + ios::ChromeBrowserState* const browser_state_; + + mutable bool initialized_; + + DISALLOW_COPY_AND_ASSIGN(Handle); + }; + + private: + friend class base::RefCountedThreadSafe<ChromeBrowserStateImplIOData>; + + struct LazyParams { + LazyParams(); + ~LazyParams(); + + // All of these parameters are intended to be read on the IO thread. + base::FilePath cookie_path; + base::FilePath channel_id_path; + base::FilePath cache_path; + int cache_max_size; + }; + + ChromeBrowserStateImplIOData(); + ~ChromeBrowserStateImplIOData() override; + + void InitializeInternal( + scoped_ptr<IOSChromeNetworkDelegate> chrome_network_delegate, + ProfileParams* profile_params, + ProtocolHandlerMap* protocol_handlers) const override; + net::URLRequestContext* InitializeAppRequestContext( + net::URLRequestContext* main_context) const override; + net::URLRequestContext* AcquireIsolatedAppRequestContext( + net::URLRequestContext* main_context) const override; + + // Deletes all network related data since |time|. It deletes transport + // security state since |time| and also deletes HttpServerProperties data. + // Works asynchronously, however if the |completion| callback is non-null, + // it will be posted on the UI thread once the removal process completes. + void ClearNetworkingHistorySinceOnIOThread(base::Time time, + const base::Closure& completion); + + mutable scoped_ptr<data_reduction_proxy::DataReductionProxyNetworkDelegate> + network_delegate_; + + // Lazy initialization params. + mutable scoped_ptr<LazyParams> lazy_params_; + + mutable scoped_refptr<JsonPrefStore> network_json_store_; + + mutable scoped_ptr<net::HttpNetworkSession> http_network_session_; + mutable scoped_ptr<net::HttpTransactionFactory> main_http_factory_; + + // Same as |ChromeBrowserState::http_server_properties_|, owned there to + // maintain destruction ordering. + mutable net::HttpServerPropertiesManager* http_server_properties_manager_; + + mutable scoped_ptr<net::URLRequestJobFactory> main_job_factory_; + + mutable scoped_ptr<net::SdchManager> sdch_manager_; + mutable scoped_ptr<net::SdchOwner> sdch_policy_; + + // Parameters needed for isolated apps. + base::FilePath profile_path_; + int app_cache_max_size_; + + DISALLOW_COPY_AND_ASSIGN(ChromeBrowserStateImplIOData); +}; + +#endif // IOS_CHROME_BROWSER_BROWSER_STATE_CHROME_BROWSER_STATE_IMPL_IO_DATA_H_ diff --git a/ios/chrome/browser/browser_state/chrome_browser_state_io_data.cc b/ios/chrome/browser/browser_state/chrome_browser_state_io_data.cc new file mode 100644 index 0000000..0706b78 --- /dev/null +++ b/ios/chrome/browser/browser_state/chrome_browser_state_io_data.cc @@ -0,0 +1,488 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ios/chrome/browser/browser_state/chrome_browser_state_io_data.h" + +#include <string> + +#include "base/basictypes.h" +#include "base/bind.h" +#include "base/bind_helpers.h" +#include "base/callback.h" +#include "base/command_line.h" +#include "base/compiler_specific.h" +#include "base/debug/alias.h" +#include "base/logging.h" +#include "base/path_service.h" +#include "base/prefs/pref_service.h" +#include "base/stl_util.h" +#include "base/strings/string_number_conversions.h" +#include "base/strings/string_util.h" +#include "base/thread_task_runner_handle.h" +#include "base/threading/sequenced_worker_pool.h" +#include "components/about_handler/about_protocol_handler.h" +#include "components/content_settings/core/browser/content_settings_provider.h" +#include "components/content_settings/core/browser/cookie_settings.h" +#include "components/content_settings/core/browser/host_content_settings_map.h" +#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.h" +#include "components/metrics/metrics_pref_names.h" +#include "components/net_log/chrome_net_log.h" +#include "components/signin/core/common/signin_pref_names.h" +#include "components/sync_driver/pref_names.h" +#include "ios/chrome/browser/application_context.h" +#include "ios/chrome/browser/chrome_url_constants.h" +#include "ios/chrome/browser/content_settings/cookie_settings_factory.h" +#include "ios/chrome/browser/content_settings/host_content_settings_map_factory.h" +#include "ios/chrome/browser/ios_chrome_io_thread.h" +#include "ios/chrome/browser/net/ios_chrome_http_user_agent_settings.h" +#include "ios/chrome/browser/net/ios_chrome_network_delegate.h" +#include "ios/chrome/browser/net/ios_chrome_url_request_context_getter.h" +#include "ios/chrome/browser/net/proxy_service_factory.h" +#include "ios/public/provider/chrome/browser/browser_state/chrome_browser_state.h" +#include "ios/web/public/web_thread.h" +#include "net/base/keygen_handler.h" +#include "net/base/network_quality_estimator.h" +#include "net/cert/cert_verifier.h" +#include "net/cert/multi_log_ct_verifier.h" +#include "net/cookies/canonical_cookie.h" +#include "net/http/http_network_session.h" +#include "net/http/http_transaction_factory.h" +#include "net/http/http_util.h" +#include "net/http/transport_security_persister.h" +#include "net/proxy/proxy_config_service_fixed.h" +#include "net/proxy/proxy_script_fetcher_impl.h" +#include "net/proxy/proxy_service.h" +#include "net/ssl/channel_id_service.h" +#include "net/url_request/certificate_report_sender.h" +#include "net/url_request/data_protocol_handler.h" +#include "net/url_request/file_protocol_handler.h" +#include "net/url_request/url_request.h" +#include "net/url_request/url_request_context.h" +#include "net/url_request/url_request_context_builder.h" +#include "net/url_request/url_request_intercepting_job_factory.h" +#include "net/url_request/url_request_interceptor.h" +#include "net/url_request/url_request_job_factory_impl.h" + +namespace { + +// For safe shutdown, must be called before the ChromeBrowserStateIOData is +// destroyed. +void NotifyContextGettersOfShutdownOnIO( + scoped_ptr<ChromeBrowserStateIOData::IOSChromeURLRequestContextGetterVector> + getters) { + DCHECK_CURRENTLY_ON_WEB_THREAD(web::WebThread::IO); + ChromeBrowserStateIOData::IOSChromeURLRequestContextGetterVector::iterator + iter; + for (auto& chrome_context_getter : *getters) + chrome_context_getter->NotifyContextShuttingDown(); +} + +} // namespace + +void ChromeBrowserStateIOData::InitializeOnUIThread( + ios::ChromeBrowserState* browser_state) { + DCHECK_CURRENTLY_ON_WEB_THREAD(web::WebThread::UI); + PrefService* pref_service = browser_state->GetPrefs(); + scoped_ptr<ProfileParams> params(new ProfileParams); + params->path = browser_state->GetOriginalChromeBrowserState()->GetStatePath(); + + params->io_thread = GetApplicationContext()->GetIOSChromeIOThread(); + + params->cookie_settings = + ios::CookieSettingsFactory::GetForBrowserState(browser_state); + params->host_content_settings_map = + ios::HostContentSettingsMapFactory::GetForBrowserState(browser_state); + params->ssl_config_service = browser_state->GetSSLConfigService(); + + params->proxy_config_service = + ios::ProxyServiceFactory::CreateProxyConfigService( + browser_state->GetProxyConfigTracker()); + + params->browser_state = browser_state; + profile_params_.reset(params.release()); + + IOSChromeNetworkDelegate::InitializePrefsOnUIThread(&enable_do_not_track_, + pref_service); + + scoped_refptr<base::SingleThreadTaskRunner> io_task_runner = + web::WebThread::GetTaskRunnerForThread(web::WebThread::IO); + + chrome_http_user_agent_settings_.reset( + new IOSChromeHttpUserAgentSettings(pref_service)); + + // These members are used only for sign in, which is not enabled + // in incognito mode. So no need to initialize them. + if (!IsOffTheRecord()) { + google_services_user_account_id_.Init(prefs::kGoogleServicesUserAccountId, + pref_service); + google_services_user_account_id_.MoveToThread(io_task_runner); + + sync_disabled_.Init(sync_driver::prefs::kSyncManaged, pref_service); + sync_disabled_.MoveToThread(io_task_runner); + + signin_allowed_.Init(prefs::kSigninAllowed, pref_service); + signin_allowed_.MoveToThread(io_task_runner); + } + + initialized_on_UI_thread_ = true; +} + +ChromeBrowserStateIOData::AppRequestContext::AppRequestContext() {} + +void ChromeBrowserStateIOData::AppRequestContext::SetCookieStore( + net::CookieStore* cookie_store) { + cookie_store_ = cookie_store; + set_cookie_store(cookie_store); +} + +void ChromeBrowserStateIOData::AppRequestContext::SetHttpTransactionFactory( + scoped_ptr<net::HttpTransactionFactory> http_factory) { + http_factory_ = http_factory.Pass(); + set_http_transaction_factory(http_factory_.get()); +} + +void ChromeBrowserStateIOData::AppRequestContext::SetJobFactory( + scoped_ptr<net::URLRequestJobFactory> job_factory) { + job_factory_ = job_factory.Pass(); + set_job_factory(job_factory_.get()); +} + +ChromeBrowserStateIOData::AppRequestContext::~AppRequestContext() { + AssertNoURLRequests(); +} + +ChromeBrowserStateIOData::ProfileParams::ProfileParams() + : io_thread(nullptr), browser_state(nullptr) {} + +ChromeBrowserStateIOData::ProfileParams::~ProfileParams() {} + +ChromeBrowserStateIOData::ChromeBrowserStateIOData( + ios::ChromeBrowserStateType browser_state_type) + : initialized_(false), + initialized_on_UI_thread_(false), + browser_state_type_(browser_state_type) { + DCHECK_CURRENTLY_ON_WEB_THREAD(web::WebThread::UI); +} + +ChromeBrowserStateIOData::~ChromeBrowserStateIOData() { + if (web::WebThread::IsMessageLoopValid(web::WebThread::IO)) + DCHECK_CURRENTLY_ON_WEB_THREAD(web::WebThread::IO); + + // Pull the contents of the request context maps onto the stack for sanity + // checking of values in a minidump. http://crbug.com/260425 + size_t num_app_contexts = app_request_context_map_.size(); + size_t current_context = 0; + static const size_t kMaxCachedContexts = 20; + net::URLRequestContext* app_context_cache[kMaxCachedContexts] = {0}; + void* app_context_vtable_cache[kMaxCachedContexts] = {0}; + void* tmp_vtable = nullptr; + base::debug::Alias(&num_app_contexts); + base::debug::Alias(¤t_context); + base::debug::Alias(app_context_cache); + base::debug::Alias(app_context_vtable_cache); + base::debug::Alias(&tmp_vtable); + + current_context = 0; + for (URLRequestContextMap::const_iterator + it = app_request_context_map_.begin(); + current_context < kMaxCachedContexts && + it != app_request_context_map_.end(); + ++it, ++current_context) { + app_context_cache[current_context] = it->second; + memcpy(&app_context_vtable_cache[current_context], + static_cast<void*>(it->second), sizeof(void*)); + } + + // Destroy certificate_report_sender_ before main_request_context_, + // since the former has a reference to the latter. + if (transport_security_state_) + transport_security_state_->SetReportSender(nullptr); + certificate_report_sender_.reset(); + + // TODO(ajwong): These AssertNoURLRequests() calls are unnecessary since they + // are already done in the URLRequestContext destructor. + if (main_request_context_) + main_request_context_->AssertNoURLRequests(); + + current_context = 0; + for (URLRequestContextMap::iterator it = app_request_context_map_.begin(); + it != app_request_context_map_.end(); ++it) { + if (current_context < kMaxCachedContexts) { + CHECK_EQ(app_context_cache[current_context], it->second); + memcpy(&tmp_vtable, static_cast<void*>(it->second), sizeof(void*)); + CHECK_EQ(app_context_vtable_cache[current_context], tmp_vtable); + } + it->second->AssertNoURLRequests(); + delete it->second; + current_context++; + } +} + +// static +bool ChromeBrowserStateIOData::IsHandledProtocol(const std::string& scheme) { + DCHECK_EQ(scheme, base::ToLowerASCII(scheme)); + static const char* const kProtocolList[] = { + url::kFileScheme, kChromeUIScheme, url::kDataScheme, url::kAboutScheme, + }; + for (size_t i = 0; i < arraysize(kProtocolList); ++i) { + if (scheme == kProtocolList[i]) + return true; + } + return net::URLRequest::IsHandledProtocol(scheme); +} + +// static +void ChromeBrowserStateIOData::InstallProtocolHandlers( + net::URLRequestJobFactoryImpl* job_factory, + ProtocolHandlerMap* protocol_handlers) { + for (ProtocolHandlerMap::iterator it = protocol_handlers->begin(); + it != protocol_handlers->end(); ++it) { + bool set_protocol = job_factory->SetProtocolHandler( + it->first, make_scoped_ptr(it->second.release())); + DCHECK(set_protocol); + } + protocol_handlers->clear(); +} + +net::URLRequestContext* ChromeBrowserStateIOData::GetMainRequestContext() + const { + DCHECK(initialized_); + return main_request_context_.get(); +} + +net::URLRequestContext* ChromeBrowserStateIOData::GetIsolatedAppRequestContext( + net::URLRequestContext* main_context, + const base::FilePath& partition_path) const { + DCHECK(initialized_); + net::URLRequestContext* context = nullptr; + if (ContainsKey(app_request_context_map_, partition_path)) { + context = app_request_context_map_[partition_path]; + } else { + context = AcquireIsolatedAppRequestContext(main_context); + app_request_context_map_[partition_path] = context; + } + DCHECK(context); + return context; +} + +content_settings::CookieSettings* ChromeBrowserStateIOData::GetCookieSettings() + const { + DCHECK(initialized_); + return cookie_settings_.get(); +} + +HostContentSettingsMap* ChromeBrowserStateIOData::GetHostContentSettingsMap() + const { + DCHECK(initialized_); + return host_content_settings_map_.get(); +} + +bool ChromeBrowserStateIOData::IsOffTheRecord() const { + return browser_state_type() == + ios::ChromeBrowserStateType::INCOGNITO_BROWSER_STATE; +} + +void ChromeBrowserStateIOData::InitializeMetricsEnabledStateOnUIThread() { + DCHECK_CURRENTLY_ON_WEB_THREAD(web::WebThread::UI); + // Prep the PrefMember and send it to the IO thread, since this value will be + // read from there. + enable_metrics_.Init(metrics::prefs::kMetricsReportingEnabled, + GetApplicationContext()->GetLocalState()); + enable_metrics_.MoveToThread( + web::WebThread::GetTaskRunnerForThread(web::WebThread::IO)); +} + +bool ChromeBrowserStateIOData::GetMetricsEnabledStateOnIOThread() const { + DCHECK_CURRENTLY_ON_WEB_THREAD(web::WebThread::IO); + return enable_metrics_.GetValue(); +} + +bool ChromeBrowserStateIOData::IsDataReductionProxyEnabled() const { + return data_reduction_proxy_io_data() && + data_reduction_proxy_io_data()->IsEnabled(); +} + +void ChromeBrowserStateIOData::set_data_reduction_proxy_io_data( + scoped_ptr<data_reduction_proxy::DataReductionProxyIOData> + data_reduction_proxy_io_data) const { + data_reduction_proxy_io_data_ = data_reduction_proxy_io_data.Pass(); +} + +base::WeakPtr<net::HttpServerProperties> +ChromeBrowserStateIOData::http_server_properties() const { + return http_server_properties_->GetWeakPtr(); +} + +void ChromeBrowserStateIOData::set_http_server_properties( + scoped_ptr<net::HttpServerProperties> http_server_properties) const { + http_server_properties_ = http_server_properties.Pass(); +} + +void ChromeBrowserStateIOData::Init( + ProtocolHandlerMap* protocol_handlers) const { + // The basic logic is implemented here. The specific initialization + // is done in InitializeInternal(), implemented by subtypes. Static helper + // functions have been provided to assist in common operations. + DCHECK_CURRENTLY_ON_WEB_THREAD(web::WebThread::IO); + DCHECK(!initialized_); + + // TODO(jhawkins): Remove once crbug.com/102004 is fixed. + CHECK(initialized_on_UI_thread_); + + // TODO(jhawkins): Return to DCHECK once crbug.com/102004 is fixed. + CHECK(profile_params_.get()); + + IOSChromeIOThread* const io_thread = profile_params_->io_thread; + IOSChromeIOThread::Globals* const io_thread_globals = io_thread->globals(); + + // Create the common request contexts. + main_request_context_.reset(new net::URLRequestContext()); + + scoped_ptr<IOSChromeNetworkDelegate> network_delegate( + new IOSChromeNetworkDelegate()); + + network_delegate->set_cookie_settings(profile_params_->cookie_settings.get()); + network_delegate->set_enable_do_not_track(&enable_do_not_track_); + + // NOTE: Proxy service uses the default io thread network delegate, not the + // delegate just created. + proxy_service_ = ios::ProxyServiceFactory::CreateProxyService( + io_thread->net_log(), nullptr, + io_thread_globals->system_network_delegate.get(), + profile_params_->proxy_config_service.Pass(), + true /* quick_check_enabled */); + transport_security_state_.reset(new net::TransportSecurityState()); + base::SequencedWorkerPool* pool = web::WebThread::GetBlockingPool(); + transport_security_persister_.reset(new net::TransportSecurityPersister( + transport_security_state_.get(), profile_params_->path, + pool->GetSequencedTaskRunnerWithShutdownBehavior( + pool->GetSequenceToken(), base::SequencedWorkerPool::BLOCK_SHUTDOWN), + IsOffTheRecord())); + + certificate_report_sender_.reset(new net::CertificateReportSender( + main_request_context_.get(), + net::CertificateReportSender::DO_NOT_SEND_COOKIES)); + transport_security_state_->SetReportSender(certificate_report_sender_.get()); + + // Take ownership over these parameters. + cookie_settings_ = profile_params_->cookie_settings; + host_content_settings_map_ = profile_params_->host_content_settings_map; + + main_request_context_->set_cert_verifier( + io_thread_globals->cert_verifier.get()); + + InitializeInternal(network_delegate.Pass(), profile_params_.get(), + protocol_handlers); + + profile_params_.reset(); + initialized_ = true; +} + +void ChromeBrowserStateIOData::ApplyProfileParamsToContext( + net::URLRequestContext* context) const { + context->set_http_user_agent_settings(chrome_http_user_agent_settings_.get()); + context->set_ssl_config_service(profile_params_->ssl_config_service.get()); +} + +scoped_ptr<net::URLRequestJobFactory> +ChromeBrowserStateIOData::SetUpJobFactoryDefaults( + scoped_ptr<net::URLRequestJobFactoryImpl> job_factory, + URLRequestInterceptorScopedVector request_interceptors, + net::NetworkDelegate* network_delegate) const { + // NOTE(willchan): Keep these protocol handlers in sync with + // ChromeBrowserStateIOData::IsHandledProtocol(). + bool set_protocol = job_factory->SetProtocolHandler( + url::kFileScheme, + make_scoped_ptr(new net::FileProtocolHandler( + web::WebThread::GetBlockingPool()->GetTaskRunnerWithShutdownBehavior( + base::SequencedWorkerPool::SKIP_ON_SHUTDOWN)))); + DCHECK(set_protocol); + + set_protocol = job_factory->SetProtocolHandler( + url::kDataScheme, make_scoped_ptr(new net::DataProtocolHandler())); + DCHECK(set_protocol); + + job_factory->SetProtocolHandler( + url::kAboutScheme, + make_scoped_ptr(new about_handler::AboutProtocolHandler())); + + // Set up interceptors in the reverse order. + scoped_ptr<net::URLRequestJobFactory> top_job_factory = job_factory.Pass(); + for (URLRequestInterceptorScopedVector::reverse_iterator i = + request_interceptors.rbegin(); + i != request_interceptors.rend(); ++i) { + top_job_factory.reset(new net::URLRequestInterceptingJobFactory( + top_job_factory.Pass(), make_scoped_ptr(*i))); + } + request_interceptors.weak_clear(); + return top_job_factory.Pass(); +} + +void ChromeBrowserStateIOData::ShutdownOnUIThread( + scoped_ptr<IOSChromeURLRequestContextGetterVector> context_getters) { + DCHECK_CURRENTLY_ON_WEB_THREAD(web::WebThread::UI); + + google_services_user_account_id_.Destroy(); + enable_referrers_.Destroy(); + enable_do_not_track_.Destroy(); + enable_metrics_.Destroy(); + safe_browsing_enabled_.Destroy(); + sync_disabled_.Destroy(); + signin_allowed_.Destroy(); + if (chrome_http_user_agent_settings_) + chrome_http_user_agent_settings_->CleanupOnUIThread(); + + if (!context_getters->empty()) { + if (web::WebThread::IsMessageLoopValid(web::WebThread::IO)) { + web::WebThread::PostTask(web::WebThread::IO, FROM_HERE, + base::Bind(&NotifyContextGettersOfShutdownOnIO, + base::Passed(&context_getters))); + } + } + + bool posted = web::WebThread::DeleteSoon(web::WebThread::IO, FROM_HERE, this); + if (!posted) + delete this; +} + +void ChromeBrowserStateIOData::set_channel_id_service( + net::ChannelIDService* channel_id_service) const { + channel_id_service_.reset(channel_id_service); +} + +scoped_ptr<net::HttpNetworkSession> +ChromeBrowserStateIOData::CreateHttpNetworkSession( + const ProfileParams& profile_params) const { + net::HttpNetworkSession::Params params; + net::URLRequestContext* context = main_request_context(); + + IOSChromeIOThread* const io_thread = profile_params.io_thread; + + io_thread->InitializeNetworkSessionParams(¶ms); + net::URLRequestContextBuilder::SetHttpNetworkSessionComponents(context, + ¶ms); + if (!IsOffTheRecord()) { + params.socket_performance_watcher_factory = + io_thread->globals()->network_quality_estimator.get(); + } + if (data_reduction_proxy_io_data_.get()) + params.proxy_delegate = data_reduction_proxy_io_data_->proxy_delegate(); + + return scoped_ptr<net::HttpNetworkSession>( + new net::HttpNetworkSession(params)); +} + +scoped_ptr<net::HttpCache> ChromeBrowserStateIOData::CreateMainHttpFactory( + net::HttpNetworkSession* session, + scoped_ptr<net::HttpCache::BackendFactory> main_backend) const { + return scoped_ptr<net::HttpCache>( + new net::HttpCache(session, main_backend.Pass(), true)); +} + +scoped_ptr<net::HttpCache> ChromeBrowserStateIOData::CreateHttpFactory( + net::HttpNetworkSession* shared_session, + scoped_ptr<net::HttpCache::BackendFactory> backend) const { + return scoped_ptr<net::HttpCache>( + new net::HttpCache(shared_session, backend.Pass(), true)); +} diff --git a/ios/chrome/browser/browser_state/chrome_browser_state_io_data.h b/ios/chrome/browser/browser_state/chrome_browser_state_io_data.h new file mode 100644 index 0000000..26f0017 --- /dev/null +++ b/ios/chrome/browser/browser_state/chrome_browser_state_io_data.h @@ -0,0 +1,328 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_BROWSER_STATE_CHROME_BROWSER_STATE_IO_DATA_H_ +#define IOS_CHROME_BROWSER_BROWSER_STATE_CHROME_BROWSER_STATE_IO_DATA_H_ + +#include <map> +#include <string> +#include <vector> + +#include "base/basictypes.h" +#include "base/callback_forward.h" +#include "base/files/file_path.h" +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" +#include "base/memory/weak_ptr.h" +#include "base/prefs/pref_member.h" +#include "components/content_settings/core/common/content_settings_types.h" +#include "ios/chrome/browser/ios_chrome_io_thread.h" +#include "ios/chrome/browser/net/net_types.h" +#include "net/cert/ct_verifier.h" +#include "net/cookies/cookie_monster.h" +#include "net/http/http_cache.h" +#include "net/http/http_network_session.h" +#include "net/url_request/url_request_context.h" +#include "net/url_request/url_request_interceptor.h" +#include "net/url_request/url_request_job_factory.h" + +class HostContentSettingsMap; +class IOSChromeHttpUserAgentSettings; +class IOSChromeNetworkDelegate; +class IOSChromeURLRequestContextGetter; + +namespace content_settings { +class CookieSettings; +} + +namespace data_reduction_proxy { +class DataReductionProxyIOData; +} + +namespace ios { +class ChromeBrowserState; +enum class ChromeBrowserStateType; +} + +namespace net { +class CertificateReportSender; +class CertVerifier; +class ChannelIDService; +class CookieStore; +class HttpServerProperties; +class HttpTransactionFactory; +class ProxyConfigService; +class ProxyService; +class ServerBoundCertService; +class SSLConfigService; +class TransportSecurityPersister; +class TransportSecurityState; +class URLRequestJobFactoryImpl; +} // namespace net + +// Conceptually speaking, the ChromeBrowserStateIOData represents data that +// lives on the IO thread that is owned by a ChromeBrowserState, such as, but +// not limited to, network objects like CookieMonster, HttpTransactionFactory, +// etc. +// ChromeBrowserState owns ChromeBrowserStateIOData, but will make sure to +// delete it on the IO thread. +class ChromeBrowserStateIOData { + public: + typedef std::vector<scoped_refptr<IOSChromeURLRequestContextGetter>> + IOSChromeURLRequestContextGetterVector; + + virtual ~ChromeBrowserStateIOData(); + + // Returns true if |scheme| is handled in Chrome, or by default handlers in + // net::URLRequest. + static bool IsHandledProtocol(const std::string& scheme); + + // Utility to install additional WebUI handlers into the |job_factory|. + // Ownership of the handlers is transfered from |protocol_handlers| + // to the |job_factory|. + static void InstallProtocolHandlers( + net::URLRequestJobFactoryImpl* job_factory, + ProtocolHandlerMap* protocol_handlers); + + // Initializes the ChromeBrowserStateIOData object and primes the + // RequestContext generation. Must be called prior to any of the Get*() + // methods other than GetResouceContext or GetMetricsEnabledStateOnIOThread. + void Init(ProtocolHandlerMap* protocol_handlers) const; + + net::URLRequestContext* GetMainRequestContext() const; + net::URLRequestContext* GetIsolatedAppRequestContext( + net::URLRequestContext* main_context, + const base::FilePath& partition_path) const; + + // These are useful when the Chrome layer is called from the content layer + // with a content::ResourceContext, and they want access to Chrome data for + // that browser state. + content_settings::CookieSettings* GetCookieSettings() const; + HostContentSettingsMap* GetHostContentSettingsMap() const; + + StringPrefMember* google_services_account_id() const { + return &google_services_user_account_id_; + } + + BooleanPrefMember* safe_browsing_enabled() const { + return &safe_browsing_enabled_; + } + + net::TransportSecurityState* transport_security_state() const { + return transport_security_state_.get(); + } + + ios::ChromeBrowserStateType browser_state_type() const { + return browser_state_type_; + } + + bool IsOffTheRecord() const; + + // Initialize the member needed to track the metrics enabled state. This is + // only to be called on the UI thread. + void InitializeMetricsEnabledStateOnUIThread(); + + // Returns whether or not metrics reporting is enabled in the browser instance + // on which this browser state resides. This is safe for use from the IO + // thread, and should only be called from there. + bool GetMetricsEnabledStateOnIOThread() const; + + bool IsDataReductionProxyEnabled() const; + + data_reduction_proxy::DataReductionProxyIOData* data_reduction_proxy_io_data() + const { + return data_reduction_proxy_io_data_.get(); + } + + protected: + // A URLRequestContext for apps that owns its cookie store and HTTP factory, + // to ensure they are deleted. + class AppRequestContext : public net::URLRequestContext { + public: + AppRequestContext(); + + void SetCookieStore(net::CookieStore* cookie_store); + void SetHttpTransactionFactory( + scoped_ptr<net::HttpTransactionFactory> http_factory); + void SetJobFactory(scoped_ptr<net::URLRequestJobFactory> job_factory); + + private: + ~AppRequestContext() override; + + scoped_refptr<net::CookieStore> cookie_store_; + scoped_ptr<net::HttpTransactionFactory> http_factory_; + scoped_ptr<net::URLRequestJobFactory> job_factory_; + }; + + // Created on the UI thread, read on the IO thread during + // ChromeBrowserStateIOData lazy initialization. + struct ProfileParams { + ProfileParams(); + ~ProfileParams(); + + base::FilePath path; + IOSChromeIOThread* io_thread; + scoped_refptr<content_settings::CookieSettings> cookie_settings; + scoped_refptr<HostContentSettingsMap> host_content_settings_map; + scoped_refptr<net::SSLConfigService> ssl_config_service; + scoped_refptr<net::CookieMonsterDelegate> cookie_monster_delegate; + + // We need to initialize the ProxyConfigService from the UI thread + // because on linux it relies on initializing things through gconf, + // and needs to be on the main thread. + scoped_ptr<net::ProxyConfigService> proxy_config_service; + + // The browser state this struct was populated from. It's passed as a void* + // to ensure it's not accidently used on the IO thread. + void* browser_state; + }; + + explicit ChromeBrowserStateIOData( + ios::ChromeBrowserStateType browser_state_type); + + void InitializeOnUIThread(ios::ChromeBrowserState* browser_state); + void ApplyProfileParamsToContext(net::URLRequestContext* context) const; + + scoped_ptr<net::URLRequestJobFactory> SetUpJobFactoryDefaults( + scoped_ptr<net::URLRequestJobFactoryImpl> job_factory, + URLRequestInterceptorScopedVector request_interceptors, + net::NetworkDelegate* network_delegate) const; + + // Called when the ChromeBrowserState is destroyed. |context_getters| must + // include all URLRequestContextGetters that refer to the + // ChromeBrowserStateIOData's URLRequestContexts. Triggers destruction of the + // ChromeBrowserStateIOData and shuts down |context_getters| safely on the IO + // thread. + // TODO(mmenke): Passing all those URLRequestContextGetters around like this + // is really silly. Can we do something cleaner? + void ShutdownOnUIThread( + scoped_ptr<IOSChromeURLRequestContextGetterVector> context_getters); + + // A ChannelIDService object is created by a derived class of + // ChromeBrowserStateIOData, and the derived class calls this method to set + // the channel_id_service_ member and transfers ownership to the base class. + void set_channel_id_service(net::ChannelIDService* channel_id_service) const; + + void set_data_reduction_proxy_io_data( + scoped_ptr<data_reduction_proxy::DataReductionProxyIOData> + data_reduction_proxy_io_data) const; + + net::ProxyService* proxy_service() const { return proxy_service_.get(); } + + base::WeakPtr<net::HttpServerProperties> http_server_properties() const; + + void set_http_server_properties( + scoped_ptr<net::HttpServerProperties> http_server_properties) const; + + net::URLRequestContext* main_request_context() const { + return main_request_context_.get(); + } + + bool initialized() const { return initialized_; } + + scoped_ptr<net::HttpNetworkSession> CreateHttpNetworkSession( + const ProfileParams& profile_params) const; + + // Creates main network transaction factory. + scoped_ptr<net::HttpCache> CreateMainHttpFactory( + net::HttpNetworkSession* session, + scoped_ptr<net::HttpCache::BackendFactory> main_backend) const; + + // Creates network transaction factory. + scoped_ptr<net::HttpCache> CreateHttpFactory( + net::HttpNetworkSession* shared_session, + scoped_ptr<net::HttpCache::BackendFactory> backend) const; + + private: + typedef std::map<base::FilePath, net::URLRequestContext*> + URLRequestContextMap; + + // -------------------------------------------- + // Virtual interface for subtypes to implement: + // -------------------------------------------- + + // Does the actual initialization of the ChromeBrowserStateIOData subtype. + // Subtypes should use the static helper functions above to implement this. + virtual void InitializeInternal( + scoped_ptr<IOSChromeNetworkDelegate> chrome_network_delegate, + ProfileParams* profile_params, + ProtocolHandlerMap* protocol_handlers) const = 0; + + // Does an on-demand initialization of a RequestContext for the given + // isolated app. + virtual net::URLRequestContext* InitializeAppRequestContext( + net::URLRequestContext* main_context) const = 0; + + // These functions are used to transfer ownership of the lazily initialized + // context from ChromeBrowserStateIOData to the URLRequestContextGetter. + virtual net::URLRequestContext* AcquireIsolatedAppRequestContext( + net::URLRequestContext* main_context) const = 0; + + // The order *DOES* matter for the majority of these member variables, so + // don't move them around unless you know what you're doing! + // General rules: + // * ResourceContext references the URLRequestContexts, so + // URLRequestContexts must outlive ResourceContext, hence ResourceContext + // should be destroyed first. + // * URLRequestContexts reference a whole bunch of members, so + // URLRequestContext needs to be destroyed before them. + // * Therefore, ResourceContext should be listed last, and then the + // URLRequestContexts, and then the URLRequestContext members. + // * Note that URLRequestContext members have a directed dependency graph + // too, so they must themselves be ordered correctly. + + // Tracks whether or not we've been lazily initialized. + mutable bool initialized_; + + // Data from the UI thread from the ChromeBrowserState, used to initialize + // ChromeBrowserStateIOData. Deleted after lazy initialization. + mutable scoped_ptr<ProfileParams> profile_params_; + + mutable StringPrefMember google_services_user_account_id_; + + // Member variables which are pointed to by the various context objects. + mutable BooleanPrefMember enable_referrers_; + mutable BooleanPrefMember enable_do_not_track_; + mutable BooleanPrefMember safe_browsing_enabled_; + mutable BooleanPrefMember sync_disabled_; + mutable BooleanPrefMember signin_allowed_; + + BooleanPrefMember enable_metrics_; + + // Pointed to by URLRequestContext. + mutable scoped_ptr<net::ChannelIDService> channel_id_service_; + + mutable scoped_ptr<data_reduction_proxy::DataReductionProxyIOData> + data_reduction_proxy_io_data_; + + mutable scoped_ptr<net::ProxyService> proxy_service_; + mutable scoped_ptr<net::TransportSecurityState> transport_security_state_; + mutable scoped_ptr<net::CTVerifier> cert_transparency_verifier_; + mutable scoped_ptr<net::HttpServerProperties> http_server_properties_; + mutable scoped_ptr<net::TransportSecurityPersister> + transport_security_persister_; + mutable scoped_ptr<net::CertificateReportSender> certificate_report_sender_; + + // These are only valid in between LazyInitialize() and their accessor being + // called. + mutable scoped_ptr<net::URLRequestContext> main_request_context_; + // One URLRequestContext per isolated app for main and media requests. + mutable URLRequestContextMap app_request_context_map_; + + mutable scoped_refptr<content_settings::CookieSettings> cookie_settings_; + + mutable scoped_refptr<HostContentSettingsMap> host_content_settings_map_; + + mutable scoped_ptr<IOSChromeHttpUserAgentSettings> + chrome_http_user_agent_settings_; + + // TODO(jhawkins): Remove once crbug.com/102004 is fixed. + bool initialized_on_UI_thread_; + + const ios::ChromeBrowserStateType browser_state_type_; + + DISALLOW_COPY_AND_ASSIGN(ChromeBrowserStateIOData); +}; + +#endif // IOS_CHROME_BROWSER_BROWSER_STATE_CHROME_BROWSER_STATE_IO_DATA_H_ diff --git a/ios/chrome/browser/browser_state/off_the_record_chrome_browser_state_io_data.h b/ios/chrome/browser/browser_state/off_the_record_chrome_browser_state_io_data.h new file mode 100644 index 0000000..3f4dc41 --- /dev/null +++ b/ios/chrome/browser/browser_state/off_the_record_chrome_browser_state_io_data.h @@ -0,0 +1,119 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_BROWSER_STATE_OFF_THE_RECORD_CHROME_BROWSER_STATE_IO_DATA_H_ +#define IOS_CHROME_BROWSER_BROWSER_STATE_OFF_THE_RECORD_CHROME_BROWSER_STATE_IO_DATA_H_ + +#include "base/basictypes.h" +#include "base/callback.h" +#include "base/containers/hash_tables.h" +#include "base/files/file_path.h" +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" +#include "ios/chrome/browser/browser_state/chrome_browser_state_io_data.h" +#include "ios/chrome/browser/net/net_types.h" + +class IOSChromeURLRequestContextGetter; + +namespace ios { +class ChromeBrowserState; +} + +namespace net { +class HttpNetworkSession; +class HttpTransactionFactory; +class SdchManager; +class SdchOwner; +class URLRequestContext; +} // namespace net + +// OffTheRecordChromeBrowserState owns a +// OffTheRecordChromeBrowserStateIOData::Handle, which holds a reference to the +// OffTheRecordChromeBrowserStateIOData. +// OffTheRecordChromeBrowserStateIOData is intended to own all the objects owned +// by OffTheRecordChromeBrowserState which live on the IO thread, such as, but +// not limited to, network objects like CookieMonster, HttpTransactionFactory, +// etc. +// OffTheRecordChromeBrowserStateIOData is owned by the +// OffTheRecordChromeBrowserState and OffTheRecordChromeBrowserStateIOData's +// IOSChromeURLRequestContexts. When all of them go away, then +// ChromeBrowserStateIOData will be deleted. Note that the +// OffTheRecordChromeBrowserStateIOData will typically outlive the browser state +// it is "owned" by, so it's important for OffTheRecordChromeBrowserStateIOData +// not to hold any references to the browser state beyond what's used by +// LazyParams (which should be deleted after lazy initialization). +class OffTheRecordChromeBrowserStateIOData : public ChromeBrowserStateIOData { + public: + class Handle { + public: + explicit Handle(ios::ChromeBrowserState* browser_state); + ~Handle(); + + scoped_refptr<IOSChromeURLRequestContextGetter> + CreateMainRequestContextGetter(ProtocolHandlerMap* protocol_handlers) const; + + // Clears the HTTP cache associated with the incognito browser state. + void DoomIncognitoCache(); + + ChromeBrowserStateIOData* io_data() const; + + private: + // Lazily initialize ProfileParams. We do this on the calls to + // Get*RequestContextGetter(), so we only initialize ProfileParams right + // before posting a task to the IO thread to start using them. This prevents + // objects that are supposed to be deleted on the IO thread, but are created + // on the UI thread from being unnecessarily initialized. + void LazyInitialize() const; + + // Collect references to context getters in reverse order, i.e. last item + // will be main request getter. This list is passed to |io_data_| + // for invalidation on IO thread. + scoped_ptr<IOSChromeURLRequestContextGetterVector> GetAllContextGetters(); + + // The getters will be invalidated on the IO thread before + // ProfileIOData instance is deleted. + mutable scoped_refptr<IOSChromeURLRequestContextGetter> + main_request_context_getter_; + OffTheRecordChromeBrowserStateIOData* const io_data_; + + ios::ChromeBrowserState* const browser_state_; + + mutable bool initialized_; + + DISALLOW_COPY_AND_ASSIGN(Handle); + }; + + private: + friend class base::RefCountedThreadSafe<OffTheRecordChromeBrowserStateIOData>; + + OffTheRecordChromeBrowserStateIOData(); + ~OffTheRecordChromeBrowserStateIOData() override; + + void InitializeInternal( + scoped_ptr<IOSChromeNetworkDelegate> chrome_network_delegate, + ProfileParams* profile_params, + ProtocolHandlerMap* protocol_handlers) const override; + net::URLRequestContext* InitializeAppRequestContext( + net::URLRequestContext* main_context) const override; + net::URLRequestContext* AcquireIsolatedAppRequestContext( + net::URLRequestContext* main_context) const override; + + mutable scoped_ptr<IOSChromeNetworkDelegate> network_delegate_; + + mutable scoped_ptr<net::HttpNetworkSession> http_network_session_; + mutable scoped_ptr<net::HttpTransactionFactory> main_http_factory_; + + mutable scoped_ptr<net::URLRequestJobFactory> main_job_factory_; + + // Server bound certificates and cookies are persisted to the disk on iOS. + base::FilePath cookie_path_; + base::FilePath channel_id_path_; + + mutable scoped_ptr<net::SdchManager> sdch_manager_; + mutable scoped_ptr<net::SdchOwner> sdch_policy_; + + DISALLOW_COPY_AND_ASSIGN(OffTheRecordChromeBrowserStateIOData); +}; + +#endif // IOS_CHROME_BROWSER_BROWSER_STATE_OFF_THE_RECORD_CHROME_BROWSER_STATE_IO_DATA_H_ diff --git a/ios/chrome/browser/browser_state/off_the_record_chrome_browser_state_io_data.mm b/ios/chrome/browser/browser_state/off_the_record_chrome_browser_state_io_data.mm new file mode 100644 index 0000000..086f950 --- /dev/null +++ b/ios/chrome/browser/browser_state/off_the_record_chrome_browser_state_io_data.mm @@ -0,0 +1,237 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ios/chrome/browser/browser_state/off_the_record_chrome_browser_state_io_data.h" + +#import <UIKit/UIkit.h> + +#include "base/bind.h" +#include "base/command_line.h" +#include "base/logging.h" +#include "base/mac/bind_objc_block.h" +#include "base/prefs/pref_service.h" +#include "base/stl_util.h" +#include "base/threading/worker_pool.h" +#include "components/net_log/chrome_net_log.h" +#include "ios/chrome/browser/chrome_constants.h" +#include "ios/chrome/browser/ios_chrome_io_thread.h" +#include "ios/chrome/browser/net/cookie_util.h" +#include "ios/chrome/browser/net/ios_chrome_network_delegate.h" +#include "ios/chrome/browser/net/ios_chrome_url_request_context_getter.h" +#include "ios/chrome/browser/pref_names.h" +#include "ios/public/provider/chrome/browser/browser_state/chrome_browser_state.h" +#include "ios/web/public/web_thread.h" +#include "net/base/sdch_manager.h" +#include "net/disk_cache/disk_cache.h" +#include "net/extras/sqlite/sqlite_channel_id_store.h" +#include "net/ftp/ftp_network_layer.h" +#include "net/http/http_cache.h" +#include "net/http/http_network_session.h" +#include "net/http/http_server_properties_impl.h" +#include "net/sdch/sdch_owner.h" +#include "net/ssl/channel_id_service.h" +#include "net/ssl/default_channel_id_store.h" +#include "net/url_request/url_request_job_factory_impl.h" + +namespace { + +// Callback doing nothing, called by DoomIncognitoCache() below. +void DoNothing(int rv) {} + +// Called by the notification center on memory warnings. +void OnMemoryWarningReceived(CFNotificationCenterRef center, + void* observer, + CFStringRef name, + const void* object, + CFDictionaryRef userInfo) { + OffTheRecordChromeBrowserStateIOData::Handle* handle = + (OffTheRecordChromeBrowserStateIOData::Handle*)observer; + handle->DoomIncognitoCache(); +} + +} // namespace + +void OffTheRecordChromeBrowserStateIOData::Handle::DoomIncognitoCache() { + // The cache for the incognito profile is in RAM. + scoped_refptr<net::URLRequestContextGetter> getter = + main_request_context_getter_; + web::WebThread::PostTask( + web::WebThread::IO, FROM_HERE, base::BindBlock(^{ + DCHECK_CURRENTLY_ON_WEB_THREAD(web::WebThread::IO); + net::HttpCache* cache = getter->GetURLRequestContext() + ->http_transaction_factory() + ->GetCache(); + if (!cache->GetCurrentBackend()) + return; + cache->GetCurrentBackend()->DoomAllEntries(base::Bind(&DoNothing)); + })); +} + +OffTheRecordChromeBrowserStateIOData::Handle::Handle( + ios::ChromeBrowserState* browser_state) + : io_data_(new OffTheRecordChromeBrowserStateIOData()), + browser_state_(browser_state), + initialized_(false) { + DCHECK_CURRENTLY_ON_WEB_THREAD(web::WebThread::UI); + DCHECK(browser_state); + io_data_->cookie_path_ = + browser_state->GetStatePath().Append(kIOSChromeCookieFilename); + io_data_->channel_id_path_ = + browser_state->GetStatePath().Append(kIOSChromeChannelIDFilename); +} + +OffTheRecordChromeBrowserStateIOData::Handle::~Handle() { + DCHECK_CURRENTLY_ON_WEB_THREAD(web::WebThread::UI); + + // Stop listening to notifications. + CFNotificationCenterRemoveObserver(CFNotificationCenterGetLocalCenter(), this, + nullptr, nullptr); + + io_data_->ShutdownOnUIThread(GetAllContextGetters().Pass()); +} + +scoped_refptr<IOSChromeURLRequestContextGetter> +OffTheRecordChromeBrowserStateIOData::Handle::CreateMainRequestContextGetter( + ProtocolHandlerMap* protocol_handlers) const { + DCHECK_CURRENTLY_ON_WEB_THREAD(web::WebThread::UI); + LazyInitialize(); + DCHECK(!main_request_context_getter_.get()); + main_request_context_getter_ = + IOSChromeURLRequestContextGetter::Create(io_data_, protocol_handlers); + return main_request_context_getter_; +} + +ChromeBrowserStateIOData* +OffTheRecordChromeBrowserStateIOData::Handle::io_data() const { + LazyInitialize(); + return io_data_; +} + +void OffTheRecordChromeBrowserStateIOData::Handle::LazyInitialize() const { + if (initialized_) + return; + + // Set initialized_ to true at the beginning in case any of the objects + // below try to get the ResourceContext pointer. + initialized_ = true; + io_data_->safe_browsing_enabled()->Init(prefs::kSafeBrowsingEnabled, + browser_state_->GetPrefs()); + io_data_->safe_browsing_enabled()->MoveToThread( + web::WebThread::GetTaskRunnerForThread(web::WebThread::IO)); + io_data_->InitializeOnUIThread(browser_state_); + + // Once initialized, listen to memory warnings. + CFNotificationCenterAddObserver( + CFNotificationCenterGetLocalCenter(), this, &OnMemoryWarningReceived, + static_cast<CFStringRef>( + UIApplicationDidReceiveMemoryWarningNotification), + nullptr, CFNotificationSuspensionBehaviorCoalesce); +} + +scoped_ptr<ChromeBrowserStateIOData::IOSChromeURLRequestContextGetterVector> +OffTheRecordChromeBrowserStateIOData::Handle::GetAllContextGetters() { + scoped_ptr<IOSChromeURLRequestContextGetterVector> context_getters( + new IOSChromeURLRequestContextGetterVector()); + if (main_request_context_getter_.get()) + context_getters->push_back(main_request_context_getter_); + + return context_getters.Pass(); +} + +OffTheRecordChromeBrowserStateIOData::OffTheRecordChromeBrowserStateIOData() + : ChromeBrowserStateIOData( + ios::ChromeBrowserStateType::INCOGNITO_BROWSER_STATE) {} + +OffTheRecordChromeBrowserStateIOData::~OffTheRecordChromeBrowserStateIOData() {} + +void OffTheRecordChromeBrowserStateIOData::InitializeInternal( + scoped_ptr<IOSChromeNetworkDelegate> chrome_network_delegate, + ProfileParams* profile_params, + ProtocolHandlerMap* protocol_handlers) const { + net::URLRequestContext* main_context = main_request_context(); + + IOSChromeIOThread* const io_thread = profile_params->io_thread; + IOSChromeIOThread::Globals* const io_thread_globals = io_thread->globals(); + + ApplyProfileParamsToContext(main_context); + + main_context->set_transport_security_state(transport_security_state()); + + main_context->set_net_log(io_thread->net_log()); + + main_context->set_network_delegate(chrome_network_delegate.get()); + + network_delegate_ = chrome_network_delegate.Pass(); + + main_context->set_host_resolver(io_thread_globals->host_resolver.get()); + main_context->set_http_auth_handler_factory( + io_thread_globals->http_auth_handler_factory.get()); + main_context->set_proxy_service(proxy_service()); + + main_context->set_cert_transparency_verifier( + io_thread_globals->cert_transparency_verifier.get()); + main_context->set_backoff_manager( + io_thread_globals->url_request_backoff_manager.get()); + + // For incognito, we use the default non-persistent HttpServerPropertiesImpl. + set_http_server_properties(scoped_ptr<net::HttpServerProperties>( + new net::HttpServerPropertiesImpl())); + main_context->set_http_server_properties(http_server_properties()); + + // For incognito, we use a non-persistent channel ID store. + scoped_refptr<net::DefaultChannelIDStore::PersistentStore> channel_id_store; + + // On iOS, certificates are persisted to the disk in incognito. + DCHECK(!channel_id_path_.empty()); + channel_id_store = new net::SQLiteChannelIDStore( + channel_id_path_, + web::WebThread::GetTaskRunnerForThread(web::WebThread::DB)); + + net::ChannelIDService* channel_id_service = new net::ChannelIDService( + new net::DefaultChannelIDStore(channel_id_store.get()), + base::WorkerPool::GetTaskRunner(true)); + set_channel_id_service(channel_id_service); + main_context->set_channel_id_service(channel_id_service); + + main_context->set_cookie_store( + cookie_util::CreateCookieStore(cookie_util::CookieStoreConfig( + cookie_path_, + cookie_util::CookieStoreConfig::RESTORED_SESSION_COOKIES, + cookie_util::CookieStoreConfig::COOKIE_STORE_IOS, nullptr))); + + http_network_session_ = CreateHttpNetworkSession(*profile_params); + main_http_factory_ = CreateMainHttpFactory( + http_network_session_.get(), net::HttpCache::DefaultBackend::InMemory(0)); + + main_context->set_http_transaction_factory(main_http_factory_.get()); + + scoped_ptr<net::URLRequestJobFactoryImpl> main_job_factory( + new net::URLRequestJobFactoryImpl()); + + InstallProtocolHandlers(main_job_factory.get(), protocol_handlers); + URLRequestInterceptorScopedVector empty_interceptors; + main_job_factory_ = SetUpJobFactoryDefaults(main_job_factory.Pass(), + empty_interceptors.Pass(), + main_context->network_delegate()); + main_context->set_job_factory(main_job_factory_.get()); + + // Setup SDCH for this profile. + sdch_manager_.reset(new net::SdchManager); + sdch_policy_.reset(new net::SdchOwner(sdch_manager_.get(), main_context)); + main_context->set_sdch_manager(sdch_manager_.get()); +} + +net::URLRequestContext* +OffTheRecordChromeBrowserStateIOData::InitializeAppRequestContext( + net::URLRequestContext* main_context) const { + NOTREACHED(); + return nullptr; +} + +net::URLRequestContext* +OffTheRecordChromeBrowserStateIOData::AcquireIsolatedAppRequestContext( + net::URLRequestContext* main_context) const { + NOTREACHED(); + return nullptr; +} diff --git a/ios/chrome/browser/net/ios_chrome_url_request_context_getter.cc b/ios/chrome/browser/net/ios_chrome_url_request_context_getter.cc new file mode 100644 index 0000000..dd2f88c --- /dev/null +++ b/ios/chrome/browser/net/ios_chrome_url_request_context_getter.cc @@ -0,0 +1,139 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ios/chrome/browser/net/ios_chrome_url_request_context_getter.h" + +#include "base/bind.h" +#include "base/compiler_specific.h" +#include "base/message_loop/message_loop.h" +#include "ios/chrome/browser/browser_state/chrome_browser_state_io_data.h" +#include "ios/chrome/browser/ios_chrome_io_thread.h" +#include "ios/web/public/web_thread.h" +#include "net/cookies/cookie_store.h" + +class IOSChromeURLRequestContextFactory { + public: + IOSChromeURLRequestContextFactory() {} + virtual ~IOSChromeURLRequestContextFactory() {} + + // Called to create a new instance (will only be called once). + virtual net::URLRequestContext* Create() = 0; + + protected: + DISALLOW_COPY_AND_ASSIGN(IOSChromeURLRequestContextFactory); +}; + +namespace { + +// ---------------------------------------------------------------------------- +// Helper factories +// ---------------------------------------------------------------------------- + +// Factory that creates the main URLRequestContext. +class FactoryForMain : public IOSChromeURLRequestContextFactory { + public: + FactoryForMain(const ChromeBrowserStateIOData* io_data, + ProtocolHandlerMap* protocol_handlers) + : io_data_(io_data) { + std::swap(protocol_handlers_, *protocol_handlers); + } + + net::URLRequestContext* Create() override { + io_data_->Init(&protocol_handlers_); + return io_data_->GetMainRequestContext(); + } + + private: + const ChromeBrowserStateIOData* const io_data_; + ProtocolHandlerMap protocol_handlers_; +}; + +// Factory that creates the URLRequestContext for a given isolated app. +class FactoryForIsolatedApp : public IOSChromeURLRequestContextFactory { + public: + FactoryForIsolatedApp(const ChromeBrowserStateIOData* io_data, + const base::FilePath& partition_path, + net::URLRequestContextGetter* main_context) + : io_data_(io_data), + partition_path_(partition_path), + main_request_context_getter_(main_context) {} + + net::URLRequestContext* Create() override { + // We will copy most of the state from the main request context. + // + // Note that this factory is one-shot. After Create() is called once, the + // factory is actually destroyed. Thus it is safe to destructively pass + // state onwards. + return io_data_->GetIsolatedAppRequestContext( + main_request_context_getter_->GetURLRequestContext(), partition_path_); + } + + private: + const ChromeBrowserStateIOData* const io_data_; + const base::FilePath partition_path_; + scoped_refptr<net::URLRequestContextGetter> main_request_context_getter_; +}; + +} // namespace + +// ---------------------------------------------------------------------------- +// IOSChromeURLRequestContextGetter +// ---------------------------------------------------------------------------- + +IOSChromeURLRequestContextGetter::IOSChromeURLRequestContextGetter( + scoped_ptr<IOSChromeURLRequestContextFactory> factory) + : factory_(std::move(factory)), url_request_context_(nullptr) { + DCHECK(factory_); +} + +IOSChromeURLRequestContextGetter::~IOSChromeURLRequestContextGetter() { + // NotifyContextShuttingDown() must have been called. + DCHECK(!factory_.get()); + DCHECK(!url_request_context_); +} + +// Lazily create a URLRequestContext using our factory. +net::URLRequestContext* +IOSChromeURLRequestContextGetter::GetURLRequestContext() { + DCHECK_CURRENTLY_ON_WEB_THREAD(web::WebThread::IO); + + if (factory_.get()) { + DCHECK(!url_request_context_); + url_request_context_ = factory_->Create(); + factory_.reset(); + } + + return url_request_context_; +} + +void IOSChromeURLRequestContextGetter::NotifyContextShuttingDown() { + DCHECK_CURRENTLY_ON_WEB_THREAD(web::WebThread::IO); + + factory_.reset(); + url_request_context_ = nullptr; + URLRequestContextGetter::NotifyContextShuttingDown(); +} + +scoped_refptr<base::SingleThreadTaskRunner> +IOSChromeURLRequestContextGetter::GetNetworkTaskRunner() const { + return web::WebThread::GetTaskRunnerForThread(web::WebThread::IO); +} + +// static +IOSChromeURLRequestContextGetter* IOSChromeURLRequestContextGetter::Create( + const ChromeBrowserStateIOData* io_data, + ProtocolHandlerMap* protocol_handlers) { + return new IOSChromeURLRequestContextGetter( + make_scoped_ptr(new FactoryForMain(io_data, protocol_handlers))); +} + +// static +IOSChromeURLRequestContextGetter* +IOSChromeURLRequestContextGetter::CreateForIsolatedApp( + net::URLRequestContextGetter* main_context, + const ChromeBrowserStateIOData* io_data, + const base::FilePath& partition_path) { + return new IOSChromeURLRequestContextGetter(make_scoped_ptr( + new FactoryForIsolatedApp(io_data, partition_path, main_context))); +} diff --git a/ios/chrome/browser/net/ios_chrome_url_request_context_getter.h b/ios/chrome/browser/net/ios_chrome_url_request_context_getter.h new file mode 100644 index 0000000..531490d --- /dev/null +++ b/ios/chrome/browser/net/ios_chrome_url_request_context_getter.h @@ -0,0 +1,72 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_NET_IOS_CHROME_URL_REQUEST_CONTEXT_GETTER_H_ +#define IOS_CHROME_BROWSER_NET_IOS_CHROME_URL_REQUEST_CONTEXT_GETTER_H_ + +#include "base/macros.h" +#include "base/memory/scoped_ptr.h" +#include "ios/chrome/browser/net/net_types.h" +#include "net/url_request/url_request_context.h" +#include "net/url_request/url_request_context_getter.h" + +class ChromeBrowserStateIOData; +class IOSChromeURLRequestContextFactory; + +// A net::URLRequestContextGetter subclass used by the browser. This returns a +// subclass of net::URLRequestContext which can be used to store extra +// information about requests. +// +// Most methods are expected to be called on the UI thread, except for +// the destructor and GetURLRequestContext(). +class IOSChromeURLRequestContextGetter : public net::URLRequestContextGetter { + public: + // Constructs a ChromeURLRequestContextGetter that will use |factory| to + // create the URLRequestContext. + explicit IOSChromeURLRequestContextGetter( + scoped_ptr<IOSChromeURLRequestContextFactory> factory); + + // Note that GetURLRequestContext() can only be called from the IO + // thread (it will assert otherwise). + // GetIOMessageLoopProxy however can be called from any thread. + // + // net::URLRequestContextGetter implementation. + net::URLRequestContext* GetURLRequestContext() override; + scoped_refptr<base::SingleThreadTaskRunner> GetNetworkTaskRunner() + const override; + + // Create an instance for use with an 'original' (non-OTR) profile. This is + // expected to get called on the UI thread. + static IOSChromeURLRequestContextGetter* Create( + const ChromeBrowserStateIOData* io_data, + ProtocolHandlerMap* protocol_handlers); + + // Create an instance for an original profile for an app with isolated + // storage. This is expected to get called on UI thread. + static IOSChromeURLRequestContextGetter* CreateForIsolatedApp( + net::URLRequestContextGetter* main_context, + const ChromeBrowserStateIOData* io_data, + const base::FilePath& partition_path); + + // Discard reference to URLRequestContext and inform observers of shutdown. + // Must be called before destruction. May only be called on IO thread. + void NotifyContextShuttingDown(); + + private: + ~IOSChromeURLRequestContextGetter() override; + + // Deferred logic for creating a URLRequestContext. + // Access only from the IO thread. + scoped_ptr<IOSChromeURLRequestContextFactory> factory_; + + // NULL before initialization and after invalidation. + // Otherwise, it is the URLRequestContext instance that + // was lazily created by GetURLRequestContext(). + // Access only from the IO thread. + net::URLRequestContext* url_request_context_; + + DISALLOW_COPY_AND_ASSIGN(IOSChromeURLRequestContextGetter); +}; + +#endif // IOS_CHROME_BROWSER_NET_IOS_CHROME_URL_REQUEST_CONTEXT_GETTER_H_ diff --git a/ios/chrome/browser/net/net_types.h b/ios/chrome/browser/net/net_types.h new file mode 100644 index 0000000..7cab4c6 --- /dev/null +++ b/ios/chrome/browser/net/net_types.h @@ -0,0 +1,29 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_NET_NET_TYPES_H_ +#define IOS_CHROME_BROWSER_NET_NET_TYPES_H_ + +#include <map> +#include <string> + +#include "base/memory/linked_ptr.h" +#include "base/memory/scoped_vector.h" +#include "net/url_request/url_request_job_factory.h" + +namespace net { +class URLRequestInterceptor; +} + +// A mapping from the scheme name to the protocol handler that services its +// content. +typedef std::map<std::string, + linked_ptr<net::URLRequestJobFactory::ProtocolHandler>> + ProtocolHandlerMap; + +// A scoped vector of protocol interceptors. +typedef ScopedVector<net::URLRequestInterceptor> + URLRequestInterceptorScopedVector; + +#endif // IOS_CHROME_BROWSER_NET_NET_TYPES_H_ diff --git a/ios/chrome/ios_chrome.gyp b/ios/chrome/ios_chrome.gyp index 5aa1b71..5f744bb 100644 --- a/ios/chrome/ios_chrome.gyp +++ b/ios/chrome/ios_chrome.gyp @@ -46,6 +46,7 @@ '../../base/base.gyp:base', '../../base/base.gyp:base_prefs', '../../breakpad/breakpad.gyp:breakpad_client', + '../../components/components.gyp:about_handler', '../../components/components.gyp:autofill_core_browser', '../../components/components.gyp:autofill_core_common', '../../components/components.gyp:autofill_ios_browser', @@ -55,6 +56,7 @@ '../../components/components.gyp:browser_sync_common', '../../components/components.gyp:component_updater', '../../components/components.gyp:content_settings_core_browser', + '../../components/components.gyp:cookie_config', '../../components/components.gyp:crash_core_browser', '../../components/components.gyp:crash_core_common', '../../components/components.gyp:data_reduction_proxy_core_browser', @@ -190,6 +192,12 @@ 'browser/browser_state/browser_state_keyed_service_factories.mm', 'browser/browser_state/browser_state_otr_helper.cc', 'browser/browser_state/browser_state_otr_helper.h', + 'browser/browser_state/chrome_browser_state_impl_io_data.cc', + 'browser/browser_state/chrome_browser_state_impl_io_data.h', + 'browser/browser_state/chrome_browser_state_io_data.cc', + 'browser/browser_state/chrome_browser_state_io_data.h', + 'browser/browser_state/off_the_record_chrome_browser_state_io_data.h', + 'browser/browser_state/off_the_record_chrome_browser_state_io_data.mm', 'browser/browser_state_metrics/browser_state_metrics.cc', 'browser/browser_state_metrics/browser_state_metrics.h', 'browser/browsing_data/ios_chrome_browsing_data_remover.cc', @@ -355,10 +363,13 @@ 'browser/net/ios_chrome_http_user_agent_settings.h', 'browser/net/ios_chrome_network_delegate.cc', 'browser/net/ios_chrome_network_delegate.h', + 'browser/net/ios_chrome_url_request_context_getter.cc', + 'browser/net/ios_chrome_url_request_context_getter.h', 'browser/net/metrics_network_client.h', 'browser/net/metrics_network_client.mm', 'browser/net/metrics_network_client_manager.h', 'browser/net/metrics_network_client_manager.mm', + 'browser/net/net_types.h', 'browser/net/proxy_service_factory.cc', 'browser/net/proxy_service_factory.h', 'browser/net/retryable_url_fetcher.h', diff --git a/ios/public/provider/chrome/browser/browser_state/chrome_browser_state.h b/ios/public/provider/chrome/browser/browser_state/chrome_browser_state.h index ab7be32..bdb1374 100644 --- a/ios/public/provider/chrome/browser/browser_state/chrome_browser_state.h +++ b/ios/public/provider/chrome/browser/browser_state/chrome_browser_state.h @@ -13,6 +13,7 @@ #include "base/memory/ref_counted.h" #include "ios/web/public/browser_state.h" +class PrefProxyConfigTracker; class PrefService; namespace base { @@ -20,6 +21,10 @@ class SequencedTaskRunner; class Time; } +namespace net { +class SSLConfigService; +} + namespace syncable_prefs { class PrefServiceSyncable; } @@ -30,6 +35,11 @@ class WebUIIOS; namespace ios { +enum class ChromeBrowserStateType { + REGULAR_BROWSER_STATE, + INCOGNITO_BROWSER_STATE, +}; + // This class is a Chrome-specific extension of the BrowserState interface. class ChromeBrowserState : public web::BrowserState { public: @@ -84,6 +94,13 @@ class ChromeBrowserState : public web::BrowserState { // Returns an identifier of the browser state for debugging. std::string GetDebugName(); + // Returns the helper object that provides the proxy configuration service + // access to the the proxy configuration possibly defined by preferences. + virtual PrefProxyConfigTracker* GetProxyConfigTracker() = 0; + + // Returns the SSLConfigService for this browser state. + virtual net::SSLConfigService* GetSSLConfigService() = 0; + protected: ChromeBrowserState() {} |