diff options
Diffstat (limited to 'chrome/browser/profiles')
-rw-r--r-- | chrome/browser/profiles/off_the_record_profile_io_data.cc | 188 | ||||
-rw-r--r-- | chrome/browser/profiles/off_the_record_profile_io_data.h | 110 | ||||
-rw-r--r-- | chrome/browser/profiles/profile.cc | 52 | ||||
-rw-r--r-- | chrome/browser/profiles/profile_impl.cc | 49 | ||||
-rw-r--r-- | chrome/browser/profiles/profile_impl.h | 6 | ||||
-rw-r--r-- | chrome/browser/profiles/profile_impl_io_data.cc | 282 | ||||
-rw-r--r-- | chrome/browser/profiles/profile_impl_io_data.h | 114 | ||||
-rw-r--r-- | chrome/browser/profiles/profile_io_data.cc | 405 | ||||
-rw-r--r-- | chrome/browser/profiles/profile_io_data.h | 207 |
9 files changed, 1139 insertions, 274 deletions
diff --git a/chrome/browser/profiles/off_the_record_profile_io_data.cc b/chrome/browser/profiles/off_the_record_profile_io_data.cc new file mode 100644 index 0000000..ac8cf03 --- /dev/null +++ b/chrome/browser/profiles/off_the_record_profile_io_data.cc @@ -0,0 +1,188 @@ +// Copyright (c) 2011 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 "chrome/browser/profiles/off_the_record_profile_io_data.h" + +#include "base/command_line.h" +#include "base/logging.h" +#include "build/build_config.h" +#include "chrome/browser/browser_process.h" +#include "chrome/browser/browser_thread.h" +#include "chrome/browser/io_thread.h" +#include "chrome/browser/net/chrome_cookie_policy.h" +#include "chrome/browser/net/chrome_dns_cert_provenance_checker_factory.h" +#include "chrome/browser/net/chrome_net_log.h" +#include "chrome/browser/net/chrome_url_request_context.h" +#include "chrome/common/url_constants.h" +#include "net/ftp/ftp_network_layer.h" +#include "net/http/http_cache.h" + +OffTheRecordProfileIOData::Handle::Handle(Profile* profile) + : io_data_(new OffTheRecordProfileIOData), + profile_(profile), + initialized_(false) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK(profile); + DCHECK(!io_data_->lazy_params_.get()); + LazyParams* lazy_params = new LazyParams; + lazy_params->io_thread = g_browser_process->io_thread(); + io_data_->lazy_params_.reset(lazy_params); +} + +OffTheRecordProfileIOData::Handle::~Handle() { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + if (main_request_context_getter_) + main_request_context_getter_->CleanupOnUIThread(); + if (extensions_request_context_getter_) + extensions_request_context_getter_->CleanupOnUIThread(); +} + +scoped_refptr<ChromeURLRequestContextGetter> +OffTheRecordProfileIOData::Handle::GetMainRequestContextGetter() const { + // TODO(oshima): Re-enable when ChromeOS only accesses the profile on the UI + // thread. +#if !defined(OS_CHROMEOS) + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); +#endif // defined(OS_CHROMEOS) + LazyInitialize(); + if (!main_request_context_getter_) { + main_request_context_getter_ = + ChromeURLRequestContextGetter::CreateOffTheRecord(profile_, io_data_); + } + return main_request_context_getter_; +} + +scoped_refptr<ChromeURLRequestContextGetter> +OffTheRecordProfileIOData::Handle::GetExtensionsRequestContextGetter() const { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + LazyInitialize(); + if (!extensions_request_context_getter_) { + extensions_request_context_getter_ = + ChromeURLRequestContextGetter::CreateOffTheRecordForExtensions( + profile_, io_data_); + } + return extensions_request_context_getter_; +} + +void OffTheRecordProfileIOData::Handle::LazyInitialize() const { + if (!initialized_) { + InitializeProfileParams(profile_, &io_data_->lazy_params_->profile_params); + initialized_ = true; + } +} + +OffTheRecordProfileIOData::LazyParams::LazyParams() : io_thread(NULL) {} +OffTheRecordProfileIOData::LazyParams::~LazyParams() {} + +OffTheRecordProfileIOData::OffTheRecordProfileIOData() + : ProfileIOData(true), + initialized_(false) {} +OffTheRecordProfileIOData::~OffTheRecordProfileIOData() {} + +void OffTheRecordProfileIOData::LazyInitializeInternal() const { + main_request_context_ = new RequestContext; + extensions_request_context_ = new RequestContext; + + IOThread* const io_thread = lazy_params_->io_thread; + IOThread::Globals* const io_thread_globals = io_thread->globals(); + const ProfileParams& profile_params = lazy_params_->profile_params; + const CommandLine& command_line = *CommandLine::ForCurrentProcess(); + + ApplyProfileParamsToContext(profile_params, main_request_context_); + ApplyProfileParamsToContext(profile_params, extensions_request_context_); + profile_params.appcache_service->set_request_context(main_request_context_); + + scoped_refptr<ChromeCookiePolicy> cookie_policy = + new ChromeCookiePolicy(profile_params.host_content_settings_map); + main_request_context_->set_chrome_cookie_policy(cookie_policy); + extensions_request_context_->set_chrome_cookie_policy(cookie_policy); + + main_request_context_->set_net_log(lazy_params_->io_thread->net_log()); + extensions_request_context_->set_net_log(lazy_params_->io_thread->net_log()); + + main_request_context_->set_host_resolver( + io_thread_globals->host_resolver.get()); + main_request_context_->set_cert_verifier( + io_thread_globals->cert_verifier.get()); + main_request_context_->set_dnsrr_resolver( + io_thread_globals->dnsrr_resolver.get()); + // TODO(willchan): Enable this when we can support ExtensionIOEventRouter for + // OTR profiles. +#if 0 + main_request_context_->set_network_delegate( + &io_thread_globals->network_delegate); +#endif + main_request_context_->set_http_auth_handler_factory( + io_thread_globals->http_auth_handler_factory.get()); + + dns_cert_checker_.reset( + CreateDnsCertProvenanceChecker(io_thread_globals->dnsrr_resolver.get(), + main_request_context_)); + main_request_context_->set_dns_cert_checker(dns_cert_checker_.get()); + + main_request_context_->set_proxy_service( + CreateProxyService( + io_thread->net_log(), + io_thread_globals->proxy_script_fetcher_context.get(), + lazy_params_->profile_params.proxy_config_service.release(), + command_line)); + + main_request_context_->set_cookie_store( + new net::CookieMonster(NULL, profile_params.cookie_monster_delegate)); + // All we care about for extensions is the cookie store. For incognito, we + // use a non-persistent cookie store. + + net::CookieMonster* extensions_cookie_store = + new net::CookieMonster(NULL, NULL); + // Enable cookies for devtools and extension URLs. + const char* schemes[] = {chrome::kChromeDevToolsScheme, + chrome::kExtensionScheme}; + extensions_cookie_store->SetCookieableSchemes(schemes, 2); + + extensions_request_context_->set_cookie_store( + new net::CookieMonster(NULL, NULL)); + + net::HttpCache::BackendFactory* main_backend = + net::HttpCache::DefaultBackend::InMemory(0); + net::HttpCache* cache = + new net::HttpCache(main_request_context_->host_resolver(), + main_request_context_->cert_verifier(), + main_request_context_->dnsrr_resolver(), + main_request_context_->dns_cert_checker(), + main_request_context_->proxy_service(), + main_request_context_->ssl_config_service(), + main_request_context_->http_auth_handler_factory(), + main_request_context_->network_delegate(), + main_request_context_->net_log(), + main_backend); + + main_http_factory_.reset(cache); + main_request_context_->set_http_transaction_factory(cache); + main_request_context_->set_ftp_transaction_factory( + new net::FtpNetworkLayer(main_request_context_->host_resolver())); +} + +scoped_refptr<ChromeURLRequestContext> +OffTheRecordProfileIOData::AcquireMainRequestContext() const { + DCHECK(main_request_context_); + scoped_refptr<ChromeURLRequestContext> context = main_request_context_; + main_request_context_->set_profile_io_data(this); + main_request_context_ = NULL; + return context; +} + +scoped_refptr<ChromeURLRequestContext> +OffTheRecordProfileIOData::AcquireMediaRequestContext() const { + NOTREACHED(); + return NULL; +} + +scoped_refptr<ChromeURLRequestContext> +OffTheRecordProfileIOData::AcquireExtensionsRequestContext() const { + DCHECK(extensions_request_context_); + scoped_refptr<ChromeURLRequestContext> context = extensions_request_context_; + extensions_request_context_->set_profile_io_data(this); + extensions_request_context_ = NULL; + return context; +} diff --git a/chrome/browser/profiles/off_the_record_profile_io_data.h b/chrome/browser/profiles/off_the_record_profile_io_data.h new file mode 100644 index 0000000..6ce50f3 --- /dev/null +++ b/chrome/browser/profiles/off_the_record_profile_io_data.h @@ -0,0 +1,110 @@ +// Copyright (c) 2011 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 CHROME_BROWSER_PROFILES_OFF_THE_RECORD_PROFILE_IO_DATA_H_ +#define CHROME_BROWSER_PROFILES_OFF_THE_RECORD_PROFILE_IO_DATA_H_ +#pragma once + +#include "base/basictypes.h" +#include "base/file_path.h" +#include "base/ref_counted.h" +#include "base/scoped_ptr.h" +#include "chrome/browser/profiles/profile_io_data.h" + +class ChromeURLRequestContext; +class ChromeURLRequestContextGetter; +class IOThread; +class Profile; + +// OffTheRecordProfile owns a OffTheRecordProfileIOData::Handle, which holds a +// reference to the OffTheRecordProfileIOData. OffTheRecordProfileIOData is +// intended to own all the objects owned by OffTheRecordProfile which live on +// the IO thread, such as, but not limited to, network objects like +// CookieMonster, HttpTransactionFactory, etc. OffTheRecordProfileIOData is +// owned by the OffTheRecordProfile and OffTheRecordProfileIOData's +// ChromeURLRequestContexts. When all of them go away, then ProfileIOData will +// be deleted. Note that the OffTheRecordProfileIOData will typically outlive +// the Profile it is "owned" by, so it's important for OffTheRecordProfileIOData +// not to hold any references to the Profile beyond what's used by LazyParams +// (which should be deleted after lazy initialization). + +class OffTheRecordProfileIOData : public ProfileIOData { + public: + class Handle { + public: + explicit Handle(Profile* profile); + ~Handle(); + + scoped_refptr<ChromeURLRequestContextGetter> + GetMainRequestContextGetter() const; + scoped_refptr<ChromeURLRequestContextGetter> + GetExtensionsRequestContextGetter() 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; + + // Ordering is important here. Do not reorder unless you know what you're + // doing. We need to release |io_data_| *before* the getters, because we + // want to make sure that the last reference for |io_data_| is on the IO + // thread. The getters will be deleted on the IO thread, so they will + // release their refs to their contexts, which will release the last refs to + // the ProfileIOData on the IO thread. + mutable scoped_refptr<ChromeURLRequestContextGetter> + main_request_context_getter_; + mutable scoped_refptr<ChromeURLRequestContextGetter> + extensions_request_context_getter_; + const scoped_refptr<OffTheRecordProfileIOData> io_data_; + + Profile* const profile_; + + mutable bool initialized_; + + DISALLOW_COPY_AND_ASSIGN(Handle); + }; + + private: + friend class base::RefCountedThreadSafe<OffTheRecordProfileIOData>; + + struct LazyParams { + LazyParams(); + ~LazyParams(); + + IOThread* io_thread; + ProfileParams profile_params; + }; + + OffTheRecordProfileIOData(); + ~OffTheRecordProfileIOData(); + + // Lazily initializes ProfileIOData. + virtual void LazyInitializeInternal() const; + virtual scoped_refptr<ChromeURLRequestContext> + AcquireMainRequestContext() const; + virtual scoped_refptr<ChromeURLRequestContext> + AcquireMediaRequestContext() const; + virtual scoped_refptr<ChromeURLRequestContext> + AcquireExtensionsRequestContext() const; + + // Lazy initialization params. + mutable scoped_ptr<LazyParams> lazy_params_; + + mutable bool initialized_; + mutable scoped_refptr<RequestContext> main_request_context_; + // NOTE: |media_request_context_| just points to the same context that + // |main_request_context_| points to. + mutable scoped_refptr<RequestContext> media_request_context_; + mutable scoped_refptr<RequestContext> extensions_request_context_; + + mutable scoped_ptr<net::DnsCertProvenanceChecker> dns_cert_checker_; + mutable scoped_ptr<net::HttpTransactionFactory> main_http_factory_; + + DISALLOW_COPY_AND_ASSIGN(OffTheRecordProfileIOData); +}; + +#endif // CHROME_BROWSER_PROFILES_OFF_THE_RECORD_PROFILE_IO_DATA_H_ diff --git a/chrome/browser/profiles/profile.cc b/chrome/browser/profiles/profile.cc index d54c56c..0d96782 100644 --- a/chrome/browser/profiles/profile.cc +++ b/chrome/browser/profiles/profile.cc @@ -7,26 +7,32 @@ #include <string> #include "base/command_line.h" +#include "base/compiler_specific.h" #include "base/file_path.h" #include "base/file_util.h" #include "base/path_service.h" #include "base/scoped_ptr.h" #include "base/string_util.h" +#include "build/build_config.h" +#include "chrome/browser/appcache/chrome_appcache_service.h" #include "chrome/browser/background_contents_service.h" #include "chrome/browser/browser_list.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/browser_thread.h" #include "chrome/browser/chrome_blob_storage_context.h" #include "chrome/browser/dom_ui/chrome_url_data_manager.h" +#include "chrome/browser/content_settings/host_content_settings_map.h" #include "chrome/browser/download/download_manager.h" #include "chrome/browser/extensions/extension_message_service.h" #include "chrome/browser/extensions/extension_pref_store.h" #include "chrome/browser/extensions/extension_process_manager.h" #include "chrome/browser/file_system/browser_file_system_helper.h" +#include "chrome/browser/host_zoom_map.h" #include "chrome/browser/in_process_webkit/webkit_context.h" -#include "chrome/browser/net/chrome_url_request_context.h" #include "chrome/browser/net/pref_proxy_config_service.h" #include "chrome/browser/notifications/desktop_notification_service.h" +#include "chrome/browser/prefs/pref_service.h" +#include "chrome/browser/profiles/off_the_record_profile_io_data.h" #include "chrome/browser/ssl/ssl_host_state.h" #include "chrome/browser/sync/profile_sync_service.h" #include "chrome/browser/themes/browser_theme_provider.h" @@ -70,12 +76,6 @@ URLRequestContextGetter* Profile::default_request_context_; namespace { -// TODO(pathorn): Duplicated in profile_impl.cc -void CleanupRequestContext(ChromeURLRequestContextGetter* context) { - if (context) - context->CleanupOnUIThread(); -} - } // namespace Profile::Profile() @@ -157,8 +157,10 @@ class OffTheRecordProfileImpl : public Profile, explicit OffTheRecordProfileImpl(Profile* real_profile) : profile_(real_profile), prefs_(real_profile->GetOffTheRecordPrefs()), - start_time_(Time::Now()) { - request_context_ = ChromeURLRequestContextGetter::CreateOffTheRecord(this); + ALLOW_THIS_IN_INITIALIZER_LIST(io_data_(this)), + start_time_(Time::Now()), + db_tracker_(new webkit_database::DatabaseTracker( + profile_->GetPath(), true)) { extension_process_manager_.reset(ExtensionProcessManager::Create(this)); BrowserList::AddObserver(this); @@ -167,15 +169,20 @@ class OffTheRecordProfileImpl : public Profile, new BackgroundContentsService(this, CommandLine::ForCurrentProcess())); DCHECK(real_profile->GetPrefs()->GetBoolean(prefs::kIncognitoEnabled)); + + // TODO(oshima): Remove the need to eagerly initialize the request context + // getter. chromeos::OnlineAttempt is illegally trying to access this + // Profile member from a thread other than the UI thread, so we need to + // prevent a race. +#if defined(OS_CHROMEOS) + GetRequestContext(); +#endif // defined(OS_CHROMEOS) } virtual ~OffTheRecordProfileImpl() { NotificationService::current()->Notify(NotificationType::PROFILE_DESTROYED, Source<Profile>(this), NotificationService::NoDetails()); - CleanupRequestContext(request_context_); - CleanupRequestContext(extensions_request_context_); - // Clean up all DB files/directories BrowserThread::PostTask( BrowserThread::FILE, FROM_HERE, @@ -231,10 +238,6 @@ class OffTheRecordProfileImpl : public Profile, } virtual webkit_database::DatabaseTracker* GetDatabaseTracker() { - if (!db_tracker_) { - db_tracker_ = new webkit_database::DatabaseTracker( - GetPath(), IsOffTheRecord()); - } return db_tracker_; } @@ -408,21 +411,16 @@ class OffTheRecordProfileImpl : public Profile, } virtual URLRequestContextGetter* GetRequestContext() { - return request_context_; + return io_data_.GetMainRequestContextGetter(); } virtual URLRequestContextGetter* GetRequestContextForMedia() { // In OTR mode, media request context is the same as the original one. - return request_context_; + return io_data_.GetMainRequestContextGetter(); } URLRequestContextGetter* GetRequestContextForExtensions() { - if (!extensions_request_context_) { - extensions_request_context_ = - ChromeURLRequestContextGetter::CreateOffTheRecordForExtensions(this); - } - - return extensions_request_context_; + return io_data_.GetExtensionsRequestContextGetter(); } virtual net::SSLConfigService* GetSSLConfigService() { @@ -678,11 +676,7 @@ class OffTheRecordProfileImpl : public Profile, scoped_ptr<ExtensionProcessManager> extension_process_manager_; - // The context to use for requests made from this OTR session. - scoped_refptr<ChromeURLRequestContextGetter> request_context_; - - // The context to use for requests made by an extension while in OTR mode. - scoped_refptr<ChromeURLRequestContextGetter> extensions_request_context_; + OffTheRecordProfileIOData::Handle io_data_; // The download manager that only stores downloaded items in memory. scoped_refptr<DownloadManager> download_manager_; diff --git a/chrome/browser/profiles/profile_impl.cc b/chrome/browser/profiles/profile_impl.cc index 15f9e9a..1505d22 100644 --- a/chrome/browser/profiles/profile_impl.cc +++ b/chrome/browser/profiles/profile_impl.cc @@ -5,6 +5,7 @@ #include "chrome/browser/profiles/profile_impl.h" #include "base/command_line.h" +#include "base/compiler_specific.h" #include "base/environment.h" #include "base/file_path.h" #include "base/file_util.h" @@ -245,6 +246,7 @@ ProfileImpl::ProfileImpl(const FilePath& path) : path_(path), visited_link_event_listener_(new VisitedLinkEventListener()), extension_devtools_manager_(NULL), + ALLOW_THIS_IN_INITIALIZER_LIST(io_data_(this)), host_content_settings_map_(NULL), host_zoom_map_(NULL), history_service_created_(false), @@ -279,26 +281,6 @@ ProfileImpl::ProfileImpl(const FilePath& path) chrome::GetUserCacheDirectory(path_, &base_cache_path_); file_util::CreateDirectory(base_cache_path_); - FilePath cookie_path = GetPath(); - cookie_path = cookie_path.Append(chrome::kCookieFilename); - FilePath cache_path = base_cache_path_; - int cache_max_size; - GetCacheParameters(kNormalContext, &cache_path, &cache_max_size); - cache_path = GetCachePath(cache_path); - - FilePath media_cache_path = base_cache_path_; - int media_cache_max_size; - GetCacheParameters(kMediaContext, &media_cache_path, &media_cache_max_size); - media_cache_path = GetMediaCachePath(media_cache_path); - - FilePath extensions_cookie_path = GetPath(); - extensions_cookie_path = - extensions_cookie_path.Append(chrome::kExtensionsCookieFilename); - - io_data_.Init(cookie_path, cache_path, cache_max_size, - media_cache_path, media_cache_max_size, extensions_cookie_path, - this); - // Listen for theme installations from our original profile. registrar_.Add(this, NotificationType::THEME_INSTALLED, Source<Profile>(GetOriginalProfile())); @@ -331,8 +313,6 @@ ProfileImpl::ProfileImpl(const FilePath& path) extension_io_event_router_ = new ExtensionIOEventRouter(this); extension_info_map_ = new ExtensionInfoMap(); - GetPolicyContext()->Initialize(); - clear_local_state_on_exit_ = prefs->GetBoolean(prefs::kClearSiteDataOnExit); // Log the profile size after a reasonable startup delay. @@ -340,6 +320,31 @@ ProfileImpl::ProfileImpl(const FilePath& path) new ProfileSizeTask(path_), 112000); InstantController::RecordMetrics(this); + + FilePath cookie_path = GetPath(); + cookie_path = cookie_path.Append(chrome::kCookieFilename); + FilePath cache_path = base_cache_path_; + int cache_max_size; + GetCacheParameters(kNormalContext, &cache_path, &cache_max_size); + cache_path = GetCachePath(cache_path); + + FilePath media_cache_path = base_cache_path_; + int media_cache_max_size; + GetCacheParameters(kMediaContext, &media_cache_path, &media_cache_max_size); + media_cache_path = GetMediaCachePath(media_cache_path); + + FilePath extensions_cookie_path = GetPath(); + extensions_cookie_path = + extensions_cookie_path.Append(chrome::kExtensionsCookieFilename); + + // Make sure we initialize the ProfileIOData after everything else has been + // initialized that we might be reading from the IO thread. + io_data_.Init(cookie_path, cache_path, cache_max_size, + media_cache_path, media_cache_max_size, extensions_cookie_path); + + // Initialize the ProfilePolicyContext after |io_data_| since it requires + // the URLRequestContextGetter to be initialized. + GetPolicyContext()->Initialize(); } void ProfileImpl::InitExtensions() { diff --git a/chrome/browser/profiles/profile_impl.h b/chrome/browser/profiles/profile_impl.h index 09ab45a..0934dbb 100644 --- a/chrome/browser/profiles/profile_impl.h +++ b/chrome/browser/profiles/profile_impl.h @@ -12,9 +12,9 @@ #include "base/ref_counted.h" #include "base/scoped_ptr.h" #include "base/timer.h" -#include "chrome/browser/profiles/profile.h" -#include "chrome/browser/profiles/profile_io_data.h" #include "chrome/browser/prefs/pref_change_registrar.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/profiles/profile_impl_io_data.h" #include "chrome/browser/spellcheck_host_observer.h" #include "chrome/common/notification_observer.h" #include "chrome/common/notification_registrar.h" @@ -217,7 +217,7 @@ class ProfileImpl : public Profile, scoped_ptr<ProfileSyncService> sync_service_; scoped_refptr<CloudPrintProxyService> cloud_print_proxy_service_; - ProfileIOData::Handle io_data_; + ProfileImplIOData::Handle io_data_; scoped_ptr<SSLConfigServiceManager> ssl_config_service_manager_; diff --git a/chrome/browser/profiles/profile_impl_io_data.cc b/chrome/browser/profiles/profile_impl_io_data.cc new file mode 100644 index 0000000..c746a63 --- /dev/null +++ b/chrome/browser/profiles/profile_impl_io_data.cc @@ -0,0 +1,282 @@ +// Copyright (c) 2011 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 "chrome/browser/profiles/profile_impl_io_data.h" + +#include "base/command_line.h" +#include "base/logging.h" +#include "chrome/browser/browser_process.h" +#include "chrome/browser/browser_thread.h" +#include "chrome/browser/io_thread.h" +#include "chrome/browser/net/chrome_cookie_policy.h" +#include "chrome/browser/net/chrome_dns_cert_provenance_checker_factory.h" +#include "chrome/browser/net/chrome_net_log.h" +#include "chrome/browser/net/sqlite_persistent_cookie_store.h" +#include "chrome/common/chrome_constants.h" +#include "chrome/common/chrome_switches.h" +#include "chrome/common/url_constants.h" +#include "net/ftp/ftp_network_layer.h" +#include "net/http/http_cache.h" + +ProfileImplIOData::Handle::Handle(Profile* profile) + : io_data_(new ProfileImplIOData), + profile_(profile), + initialized_(false) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK(profile); +} + +ProfileImplIOData::Handle::~Handle() { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + if (main_request_context_getter_) + main_request_context_getter_->CleanupOnUIThread(); + if (media_request_context_getter_) + media_request_context_getter_->CleanupOnUIThread(); + if (extensions_request_context_getter_) + extensions_request_context_getter_->CleanupOnUIThread(); +} + +void ProfileImplIOData::Handle::Init(const FilePath& cookie_path, + const FilePath& cache_path, + int cache_max_size, + const FilePath& media_cache_path, + int media_cache_max_size, + const FilePath& extensions_cookie_path) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK(!io_data_->lazy_params_.get()); + LazyParams* lazy_params = new LazyParams; + + lazy_params->cookie_path = cookie_path; + lazy_params->cache_path = cache_path; + lazy_params->cache_max_size = cache_max_size; + lazy_params->media_cache_path = media_cache_path; + lazy_params->media_cache_max_size = media_cache_max_size; + lazy_params->extensions_cookie_path = extensions_cookie_path; + + lazy_params->io_thread = g_browser_process->io_thread(); + + io_data_->lazy_params_.reset(lazy_params); +} + +scoped_refptr<ChromeURLRequestContextGetter> +ProfileImplIOData::Handle::GetMainRequestContextGetter() const { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + LazyInitialize(); + if (!main_request_context_getter_) { + main_request_context_getter_ = + ChromeURLRequestContextGetter::CreateOriginal( + profile_, io_data_); + } + return main_request_context_getter_; +} + +scoped_refptr<ChromeURLRequestContextGetter> +ProfileImplIOData::Handle::GetMediaRequestContextGetter() const { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + LazyInitialize(); + if (!media_request_context_getter_) { + media_request_context_getter_ = + ChromeURLRequestContextGetter::CreateOriginalForMedia( + profile_, io_data_); + } + return media_request_context_getter_; +} + +scoped_refptr<ChromeURLRequestContextGetter> +ProfileImplIOData::Handle::GetExtensionsRequestContextGetter() const { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + LazyInitialize(); + if (!extensions_request_context_getter_) { + extensions_request_context_getter_ = + ChromeURLRequestContextGetter::CreateOriginalForExtensions( + profile_, io_data_); + } + return extensions_request_context_getter_; +} + +void ProfileImplIOData::Handle::LazyInitialize() const { + if (!initialized_) { + InitializeProfileParams(profile_, &io_data_->lazy_params_->profile_params); + initialized_ = true; + } +} + +ProfileImplIOData::LazyParams::LazyParams() + : cache_max_size(0), + media_cache_max_size(0), + io_thread(NULL) {} +ProfileImplIOData::LazyParams::~LazyParams() {} + +ProfileImplIOData::ProfileImplIOData() : ProfileIOData(false) {} +ProfileImplIOData::~ProfileImplIOData() {} + +void ProfileImplIOData::LazyInitializeInternal() const { + main_request_context_ = new RequestContext; + media_request_context_ = new RequestContext; + extensions_request_context_ = new RequestContext; + + IOThread* const io_thread = lazy_params_->io_thread; + IOThread::Globals* const io_thread_globals = io_thread->globals(); + const ProfileParams& profile_params = lazy_params_->profile_params; + const CommandLine& command_line = *CommandLine::ForCurrentProcess(); + bool record_mode = chrome::kRecordModeEnabled && + command_line.HasSwitch(switches::kRecordMode); + bool playback_mode = command_line.HasSwitch(switches::kPlaybackMode); + + // Initialize context members. + + ApplyProfileParamsToContext(profile_params, main_request_context_); + ApplyProfileParamsToContext(profile_params, media_request_context_); + ApplyProfileParamsToContext(profile_params, extensions_request_context_); + profile_params.appcache_service->set_request_context(main_request_context_); + scoped_refptr<ChromeCookiePolicy> cookie_policy = + new ChromeCookiePolicy(profile_params.host_content_settings_map); + + main_request_context_->set_chrome_cookie_policy(cookie_policy); + media_request_context_->set_chrome_cookie_policy(cookie_policy); + extensions_request_context_->set_chrome_cookie_policy(cookie_policy); + + main_request_context_->set_net_log(lazy_params_->io_thread->net_log()); + media_request_context_->set_net_log(lazy_params_->io_thread->net_log()); + extensions_request_context_->set_net_log(lazy_params_->io_thread->net_log()); + + main_request_context_->set_host_resolver( + io_thread_globals->host_resolver.get()); + media_request_context_->set_host_resolver( + io_thread_globals->host_resolver.get()); + main_request_context_->set_cert_verifier( + io_thread_globals->cert_verifier.get()); + media_request_context_->set_cert_verifier( + io_thread_globals->cert_verifier.get()); + main_request_context_->set_dnsrr_resolver( + io_thread_globals->dnsrr_resolver.get()); + media_request_context_->set_dnsrr_resolver( + io_thread_globals->dnsrr_resolver.get()); + main_request_context_->set_network_delegate( + &io_thread_globals->network_delegate); + // TODO(willchan): Enable for media request context. +#if 0 + media_request_context_->set_network_delegate( + &io_thread_globals->network_delegate); +#endif + main_request_context_->set_http_auth_handler_factory( + io_thread_globals->http_auth_handler_factory.get()); + media_request_context_->set_http_auth_handler_factory( + io_thread_globals->http_auth_handler_factory.get()); + + dns_cert_checker_.reset( + CreateDnsCertProvenanceChecker(io_thread_globals->dnsrr_resolver.get(), + main_request_context_)); + main_request_context_->set_dns_cert_checker(dns_cert_checker_.get()); + media_request_context_->set_dns_cert_checker(dns_cert_checker_.get()); + + net::ProxyService* proxy_service = + CreateProxyService( + io_thread->net_log(), + io_thread_globals->proxy_script_fetcher_context.get(), + lazy_params_->profile_params.proxy_config_service.release(), + command_line); + main_request_context_->set_proxy_service(proxy_service); + media_request_context_->set_proxy_service(proxy_service); + + net::HttpCache::DefaultBackend* main_backend = + new net::HttpCache::DefaultBackend( + net::DISK_CACHE, + lazy_params_->cache_path, + lazy_params_->cache_max_size, + BrowserThread::GetMessageLoopProxyForThread(BrowserThread::CACHE)); + net::HttpCache* main_cache = new net::HttpCache( + main_request_context_->host_resolver(), + main_request_context_->cert_verifier(), + main_request_context_->dnsrr_resolver(), + main_request_context_->dns_cert_checker(), + main_request_context_->proxy_service(), + main_request_context_->ssl_config_service(), + main_request_context_->http_auth_handler_factory(), + main_request_context_->network_delegate(), + main_request_context_->net_log(), + main_backend); + + net::HttpCache::DefaultBackend* media_backend = + new net::HttpCache::DefaultBackend( + net::MEDIA_CACHE, lazy_params_->media_cache_path, + lazy_params_->media_cache_max_size, + BrowserThread::GetMessageLoopProxyForThread(BrowserThread::CACHE)); + net::HttpNetworkSession* main_network_session = main_cache->GetSession(); + net::HttpCache* media_cache = + new net::HttpCache(main_network_session, media_backend); + + scoped_refptr<net::CookieStore> cookie_store = NULL; + if (record_mode || playback_mode) { + // Don't use existing cookies and use an in-memory store. + cookie_store = new net::CookieMonster( + NULL, profile_params.cookie_monster_delegate); + main_cache->set_mode( + record_mode ? net::HttpCache::RECORD : net::HttpCache::PLAYBACK); + } + + // setup cookie store + if (!cookie_store) { + DCHECK(!lazy_params_->cookie_path.empty()); + + scoped_refptr<SQLitePersistentCookieStore> cookie_db = + new SQLitePersistentCookieStore(lazy_params_->cookie_path); + cookie_db->SetClearLocalStateOnExit( + profile_params.clear_local_state_on_exit); + cookie_store = + new net::CookieMonster(cookie_db.get(), + profile_params.cookie_monster_delegate); + } + + net::CookieMonster* extensions_cookie_store = + new net::CookieMonster( + new SQLitePersistentCookieStore( + lazy_params_->extensions_cookie_path), NULL); + // Enable cookies for devtools and extension URLs. + const char* schemes[] = {chrome::kChromeDevToolsScheme, + chrome::kExtensionScheme}; + extensions_cookie_store->SetCookieableSchemes(schemes, 2); + + main_request_context_->set_cookie_store(cookie_store); + media_request_context_->set_cookie_store(cookie_store); + extensions_request_context_->set_cookie_store( + extensions_cookie_store); + + main_http_factory_.reset(main_cache); + media_http_factory_.reset(media_cache); + main_request_context_->set_http_transaction_factory(main_cache); + media_request_context_->set_http_transaction_factory(media_cache); + + main_request_context_->set_ftp_transaction_factory( + new net::FtpNetworkLayer(io_thread_globals->host_resolver.get())); + + lazy_params_.reset(); +} + +scoped_refptr<ChromeURLRequestContext> +ProfileImplIOData::AcquireMainRequestContext() const { + DCHECK(main_request_context_); + scoped_refptr<ChromeURLRequestContext> context = main_request_context_; + main_request_context_->set_profile_io_data(this); + main_request_context_ = NULL; + return context; +} + +scoped_refptr<ChromeURLRequestContext> +ProfileImplIOData::AcquireMediaRequestContext() const { + DCHECK(media_request_context_); + scoped_refptr<ChromeURLRequestContext> context = media_request_context_; + media_request_context_->set_profile_io_data(this); + media_request_context_ = NULL; + return context; +} + +scoped_refptr<ChromeURLRequestContext> +ProfileImplIOData::AcquireExtensionsRequestContext() const { + DCHECK(extensions_request_context_); + scoped_refptr<ChromeURLRequestContext> context = extensions_request_context_; + extensions_request_context_->set_profile_io_data(this); + extensions_request_context_ = NULL; + return context; +} diff --git a/chrome/browser/profiles/profile_impl_io_data.h b/chrome/browser/profiles/profile_impl_io_data.h new file mode 100644 index 0000000..ffc5e82 --- /dev/null +++ b/chrome/browser/profiles/profile_impl_io_data.h @@ -0,0 +1,114 @@ +// Copyright (c) 2011 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 CHROME_BROWSER_PROFILES_PROFILE_IMPL_IO_DATA_H_ +#define CHROME_BROWSER_PROFILES_PROFILE_IMPL_IO_DATA_H_ +#pragma once + +#include "base/basictypes.h" +#include "base/ref_counted.h" +#include "chrome/browser/profiles/profile_io_data.h" + +class ProfileImplIOData : public ProfileIOData { + public: + class Handle { + public: + explicit Handle(Profile* profile); + ~Handle(); + + bool HasMainRequestContext() const { + return main_request_context_getter_ != NULL; + } + + // Init() must be called before ~Handle(). It records all the necessary + // parameters needed to construct a ChromeURLRequestContextGetter. + void Init(const FilePath& cookie_path, + const FilePath& cache_path, + int cache_max_size, + const FilePath& media_cache_path, + int media_cache_max_size, + const FilePath& extensions_cookie_path); + + scoped_refptr<ChromeURLRequestContextGetter> + GetMainRequestContextGetter() const; + scoped_refptr<ChromeURLRequestContextGetter> + GetMediaRequestContextGetter() const; + scoped_refptr<ChromeURLRequestContextGetter> + GetExtensionsRequestContextGetter() 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; + + // Ordering is important here. Do not reorder unless you know what you're + // doing. We need to release |io_data_| *before* the getters, because we + // want to make sure that the last reference for |io_data_| is on the IO + // thread. The getters will be deleted on the IO thread, so they will + // release their refs to their contexts, which will release the last refs to + // the ProfileIOData on the IO thread. + mutable scoped_refptr<ChromeURLRequestContextGetter> + main_request_context_getter_; + mutable scoped_refptr<ChromeURLRequestContextGetter> + media_request_context_getter_; + mutable scoped_refptr<ChromeURLRequestContextGetter> + extensions_request_context_getter_; + const scoped_refptr<ProfileImplIOData> io_data_; + + Profile* const profile_; + + mutable bool initialized_; + + DISALLOW_COPY_AND_ASSIGN(Handle); + }; + + private: + friend class base::RefCountedThreadSafe<ProfileImplIOData>; + + struct LazyParams { + LazyParams(); + ~LazyParams(); + + // All of these parameters are intended to be read on the IO thread. + FilePath cookie_path; + FilePath cache_path; + int cache_max_size; + FilePath media_cache_path; + int media_cache_max_size; + FilePath extensions_cookie_path; + IOThread* io_thread; + + ProfileParams profile_params; + }; + + ProfileImplIOData(); + virtual ~ProfileImplIOData(); + + // Lazily initializes ProfileImplIOData. + virtual void LazyInitializeInternal() const; + virtual scoped_refptr<ChromeURLRequestContext> + AcquireMainRequestContext() const; + virtual scoped_refptr<ChromeURLRequestContext> + AcquireMediaRequestContext() const; + virtual scoped_refptr<ChromeURLRequestContext> + AcquireExtensionsRequestContext() const; + + // Lazy initialization params. + mutable scoped_ptr<LazyParams> lazy_params_; + + mutable scoped_refptr<RequestContext> main_request_context_; + mutable scoped_refptr<RequestContext> media_request_context_; + mutable scoped_refptr<RequestContext> extensions_request_context_; + + mutable scoped_ptr<net::DnsCertProvenanceChecker> dns_cert_checker_; + mutable scoped_ptr<net::HttpTransactionFactory> main_http_factory_; + mutable scoped_ptr<net::HttpTransactionFactory> media_http_factory_; + + DISALLOW_COPY_AND_ASSIGN(ProfileImplIOData); +}; + +#endif // CHROME_BROWSER_PROFILES_PROFILE_IMPL_IO_DATA_H_ diff --git a/chrome/browser/profiles/profile_io_data.cc b/chrome/browser/profiles/profile_io_data.cc index a2f6c5f..4926d68 100644 --- a/chrome/browser/profiles/profile_io_data.cc +++ b/chrome/browser/profiles/profile_io_data.cc @@ -7,107 +7,182 @@ #include "base/basictypes.h" #include "base/command_line.h" #include "base/logging.h" -#include "build/build_config.h" +#include "base/string_number_conversions.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/browser_thread.h" -#include "chrome/browser/net/chrome_net_log.h" -#include "chrome/browser/net/chrome_url_request_context.h" +#include "chrome/browser/io_thread.h" +#include "chrome/browser/net/chrome_cookie_notification_details.h" +#include "chrome/browser/net/pref_proxy_config_service.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/prefs/pref_service.h" +#include "chrome/browser/extensions/user_script_master.h" +#include "chrome/common/chrome_switches.h" +#include "chrome/common/notification_service.h" +#include "chrome/common/pref_names.h" +#include "net/http/http_util.h" +#include "net/proxy/proxy_config_service_fixed.h" +#include "net/proxy/proxy_script_fetcher_impl.h" +#include "net/proxy/proxy_service.h" -ProfileIOData::Handle::Handle() : io_data_(new ProfileIOData) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); -} +#if defined(OS_CHROMEOS) +#include "chrome/browser/chromeos/cros/cros_library.h" +#include "chrome/browser/chromeos/cros/libcros_service_library.h" +#include "chrome/browser/chromeos/proxy_config_service.h" +#endif // defined(OS_CHROMEOS) -ProfileIOData::Handle::~Handle() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - if (main_request_context_getter_) - main_request_context_getter_->CleanupOnUIThread(); - if (media_request_context_getter_) - media_request_context_getter_->CleanupOnUIThread(); - if (extensions_request_context_getter_) - extensions_request_context_getter_->CleanupOnUIThread(); -} +namespace { -void ProfileIOData::Handle::Init(const FilePath& cookie_path, - const FilePath& cache_path, - int cache_max_size, - const FilePath& media_cache_path, - int media_cache_max_size, - const FilePath& extensions_cookie_path, - Profile* profile) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - DCHECK(!io_data_->lazy_params_.get()); - LazyParams* lazy_params = new LazyParams; - lazy_params->cookie_path = cookie_path; - lazy_params->cache_path = cache_path; - lazy_params->cache_max_size = cache_max_size; - lazy_params->media_cache_path = media_cache_path; - lazy_params->media_cache_max_size = media_cache_max_size; - lazy_params->extensions_cookie_path = extensions_cookie_path; - lazy_params->profile = profile; - lazy_params->io_thread = g_browser_process->io_thread(); - io_data_->lazy_params_.reset(lazy_params); -} +// ---------------------------------------------------------------------------- +// CookieMonster::Delegate implementation +// ---------------------------------------------------------------------------- +class ChromeCookieMonsterDelegate : public net::CookieMonster::Delegate { + public: + explicit ChromeCookieMonsterDelegate(Profile* profile) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + profile_getter_ = new ProfileGetter(profile); + } -scoped_refptr<ChromeURLRequestContextGetter> -ProfileIOData::Handle::GetMainRequestContextGetter() const { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - if (!main_request_context_getter_) { - main_request_context_getter_ = - ChromeURLRequestContextGetter::CreateOriginal( - io_data_->lazy_params_->profile, io_data_); + // net::CookieMonster::Delegate implementation. + virtual void OnCookieChanged( + const net::CookieMonster::CanonicalCookie& cookie, + bool removed) { + BrowserThread::PostTask( + BrowserThread::UI, FROM_HERE, + NewRunnableMethod(this, + &ChromeCookieMonsterDelegate::OnCookieChangedAsyncHelper, + cookie, + removed)); } - return main_request_context_getter_; -} -scoped_refptr<ChromeURLRequestContextGetter> -ProfileIOData::Handle::GetMediaRequestContextGetter() const { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - if (!media_request_context_getter_) { - media_request_context_getter_ = - ChromeURLRequestContextGetter::CreateOriginalForMedia( - io_data_->lazy_params_->profile, io_data_); + private: + // This class allows us to safely access the Profile pointer. The Delegate + // itself cannot observe the PROFILE_DESTROYED notification, since it cannot + // guarantee to be deleted on the UI thread and therefore unregister from + // the notifications. All methods of ProfileGetter must be invoked on the UI + // thread. + class ProfileGetter + : public base::RefCountedThreadSafe<ProfileGetter, + BrowserThread::DeleteOnUIThread>, + public NotificationObserver { + public: + explicit ProfileGetter(Profile* profile) : profile_(profile) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + registrar_.Add(this, + NotificationType::PROFILE_DESTROYED, + Source<Profile>(profile_)); + } + + // NotificationObserver implementation. + void Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + if (NotificationType::PROFILE_DESTROYED == type) { + Profile* profile = Source<Profile>(source).ptr(); + if (profile_ == profile) + profile_ = NULL; + } + } + + Profile* get() { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + return profile_; + } + + private: + friend class ::BrowserThread; + friend class DeleteTask<ProfileGetter>; + + virtual ~ProfileGetter() {} + + NotificationRegistrar registrar_; + + Profile* profile_; + }; + + virtual ~ChromeCookieMonsterDelegate() {} + + void OnCookieChangedAsyncHelper( + const net::CookieMonster::CanonicalCookie& cookie, + bool removed) { + if (profile_getter_->get()) { + ChromeCookieDetails cookie_details(&cookie, removed); + NotificationService::current()->Notify( + NotificationType::COOKIE_CHANGED, + Source<Profile>(profile_getter_->get()), + Details<ChromeCookieDetails>(&cookie_details)); + } } - return media_request_context_getter_; -} -scoped_refptr<ChromeURLRequestContextGetter> -ProfileIOData::Handle::GetExtensionsRequestContextGetter() const { + scoped_refptr<ProfileGetter> profile_getter_; +}; + +} // namespace + +void ProfileIOData::InitializeProfileParams(Profile* profile, + ProfileParams* params) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - if (!extensions_request_context_getter_) { - extensions_request_context_getter_ = - ChromeURLRequestContextGetter::CreateOriginalForExtensions( - io_data_->lazy_params_->profile, io_data_); - } - return extensions_request_context_getter_; -} + PrefService* pref_service = profile->GetPrefs(); + params->is_off_the_record = profile->IsOffTheRecord(); + params->clear_local_state_on_exit = + pref_service->GetBoolean(prefs::kClearSiteDataOnExit); -ProfileIOData::LazyParams::LazyParams() - : cache_max_size(0), - media_cache_max_size(0), - io_thread(NULL), - profile(NULL) { -} + params->appcache_service = profile->GetAppCacheService(); -ProfileIOData::LazyParams::~LazyParams() {} + // Set up Accept-Language and Accept-Charset header values + params->accept_language = net::HttpUtil::GenerateAcceptLanguageHeader( + pref_service->GetString(prefs::kAcceptLanguages)); + std::string default_charset = pref_service->GetString(prefs::kDefaultCharset); + params->accept_charset = + net::HttpUtil::GenerateAcceptCharsetHeader(default_charset); -class ProfileIOData::RequestContext : public ChromeURLRequestContext { - public: - RequestContext(); - ~RequestContext(); + // At this point, we don't know the charset of the referring page + // where a url request originates from. This is used to get a suggested + // filename from Content-Disposition header made of raw 8bit characters. + // Down the road, it can be overriden if it becomes known (for instance, + // when download request is made through the context menu in a web page). + // At the moment, it'll remain 'undeterministic' when a user + // types a URL in the omnibar or click on a download link in a page. + // For the latter, we need a change on the webkit-side. + // We initialize it to the default charset here and a user will + // have an *arguably* better default charset for interpreting a raw 8bit + // C-D header field. It means the native OS codepage fallback in + // net_util::GetSuggestedFilename is unlikely to be taken. + params->referrer_charset = default_charset; + + params->host_content_settings_map = profile->GetHostContentSettingsMap(); + params->host_zoom_map = profile->GetHostZoomMap(); + params->transport_security_state = profile->GetTransportSecurityState(); - void set_profile_io_data(const ProfileIOData* profile_io_data) { - profile_io_data_ = profile_io_data; + if (profile->GetUserScriptMaster()) { + params->user_script_dir_path = + profile->GetUserScriptMaster()->user_script_dir(); } - private: - scoped_refptr<const ProfileIOData> profile_io_data_; -}; + params->ssl_config_service = profile->GetSSLConfigService(); + params->cookie_monster_delegate = new ChromeCookieMonsterDelegate(profile); + params->database_tracker = profile->GetDatabaseTracker(); + params->appcache_service = profile->GetAppCacheService(); + params->blob_storage_context = profile->GetBlobStorageContext(); + params->file_system_context = profile->GetFileSystemContext(); + params->extension_info_map = profile->GetExtensionInfoMap(); + params->extension_io_event_router = profile->GetExtensionIOEventRouter(); + params->prerender_manager = profile->GetPrerenderManager(); + + params->proxy_config_service.reset(CreateProxyConfigService(profile)); +} ProfileIOData::RequestContext::RequestContext() {} ProfileIOData::RequestContext::~RequestContext() {} -ProfileIOData::ProfileIOData() : initialized_(false) { +ProfileIOData::ProfileParams::ProfileParams() + : is_off_the_record(false), + clear_local_state_on_exit(false) {} +ProfileIOData::ProfileParams::~ProfileParams() {} + +ProfileIOData::ProfileIOData(bool is_off_the_record) + : initialized_(false) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); } @@ -125,78 +200,144 @@ ProfileIOData::~ProfileIOData() { scoped_refptr<ChromeURLRequestContext> ProfileIOData::GetMainRequestContext() const { LazyInitialize(); - DCHECK(main_request_context_); - scoped_refptr<ChromeURLRequestContext> context = main_request_context_; - main_request_context_->set_profile_io_data(this); - main_request_context_ = NULL; + scoped_refptr<ChromeURLRequestContext> context = + AcquireMainRequestContext(); + DCHECK(context); return context; } scoped_refptr<ChromeURLRequestContext> ProfileIOData::GetMediaRequestContext() const { LazyInitialize(); - DCHECK(media_request_context_); - scoped_refptr<ChromeURLRequestContext> context = media_request_context_; - media_request_context_->set_profile_io_data(this); - media_request_context_ = NULL; + scoped_refptr<ChromeURLRequestContext> context = + AcquireMediaRequestContext(); + DCHECK(context); return context; } scoped_refptr<ChromeURLRequestContext> ProfileIOData::GetExtensionsRequestContext() const { LazyInitialize(); - DCHECK(extensions_request_context_); - scoped_refptr<ChromeURLRequestContext> context = extensions_request_context_; - extensions_request_context_->set_profile_io_data(this); - extensions_request_context_ = NULL; + scoped_refptr<ChromeURLRequestContext> context = + AcquireExtensionsRequestContext(); + DCHECK(context); return context; } -const ProfileIOData::LazyParams& ProfileIOData::lazy_params() const { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); - DCHECK(lazy_params_.get()); - return *lazy_params_; -} - void ProfileIOData::LazyInitialize() const { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); if (initialized_) return; + LazyInitializeInternal(); + initialized_ = true; +} - main_request_context_ = new RequestContext; - media_request_context_ = new RequestContext; - extensions_request_context_ = new RequestContext; - - // Initialize context members. - IOThread::Globals* io_thread_globals = lazy_params_->io_thread->globals(); - - main_request_context_->set_net_log(lazy_params_->io_thread->net_log()); - media_request_context_->set_net_log(lazy_params_->io_thread->net_log()); - - main_request_context_->set_host_resolver( - io_thread_globals->host_resolver.get()); - main_request_context_->set_cert_verifier( - io_thread_globals->cert_verifier.get()); - main_request_context_->set_dnsrr_resolver( - io_thread_globals->dnsrr_resolver.get()); - main_request_context_->set_network_delegate( - &io_thread_globals->network_delegate); - - main_request_context_->set_http_auth_handler_factory( - io_thread_globals->http_auth_handler_factory.get()); - media_request_context_->set_http_auth_handler_factory( - io_thread_globals->http_auth_handler_factory.get()); - // TODO(cbentzel): How should extensions handle HTTP Authentication? - extensions_request_context_->set_http_auth_handler_factory( - io_thread_globals->http_auth_handler_factory.get()); - - // TODO(willchan): Initialize more of the contexts! - - // TODO(willchan): Enable this when LazyInitialize() is able to fully - // initialize all the ChromeURLRequestContexts. -#if 0 - params_.reset(); -#endif +// static +void ProfileIOData::ApplyProfileParamsToContext( + const ProfileParams& profile_params, + ChromeURLRequestContext* context) { + context->set_is_off_the_record(profile_params.is_off_the_record); + context->set_accept_language(profile_params.accept_language); + context->set_accept_charset(profile_params.accept_charset); + context->set_referrer_charset(profile_params.referrer_charset); + context->set_user_script_dir_path(profile_params.user_script_dir_path); + context->set_host_content_settings_map( + profile_params.host_content_settings_map); + context->set_host_zoom_map(profile_params.host_zoom_map); + context->set_transport_security_state( + profile_params.transport_security_state); + context->set_ssl_config_service(profile_params.ssl_config_service); + context->set_database_tracker(profile_params.database_tracker); + context->set_appcache_service(profile_params.appcache_service); + context->set_blob_storage_context(profile_params.blob_storage_context); + context->set_file_system_context(profile_params.file_system_context); + context->set_extension_info_map(profile_params.extension_info_map); + context->set_extension_io_event_router( + profile_params.extension_io_event_router); + context->set_prerender_manager(profile_params.prerender_manager); +} - initialized_ = true; +// static +net::ProxyConfigService* ProfileIOData::CreateProxyConfigService( + Profile* profile) { + // The linux gconf-based proxy settings getter relies on being initialized + // from the UI thread. + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + + // Create a baseline service that provides proxy configuration in case nothing + // is configured through prefs (Note: prefs include command line and + // configuration policy). + net::ProxyConfigService* base_service = NULL; + + // TODO(port): the IO and FILE message loops are only used by Linux. Can + // that code be moved to chrome/browser instead of being in net, so that it + // can use BrowserThread instead of raw MessageLoop pointers? See bug 25354. +#if defined(OS_CHROMEOS) + base_service = new chromeos::ProxyConfigService( + profile->GetChromeOSProxyConfigServiceImpl()); +#else + base_service = net::ProxyService::CreateSystemProxyConfigService( + g_browser_process->io_thread()->message_loop(), + g_browser_process->file_thread()->message_loop()); +#endif // defined(OS_CHROMEOS) + + return new PrefProxyConfigService(profile->GetProxyConfigTracker(), + base_service); +} + +// static +net::ProxyService* ProfileIOData::CreateProxyService( + net::NetLog* net_log, + net::URLRequestContext* context, + net::ProxyConfigService* proxy_config_service, + const CommandLine& command_line) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + + bool use_v8 = !command_line.HasSwitch(switches::kWinHttpProxyResolver); + if (use_v8 && command_line.HasSwitch(switches::kSingleProcess)) { + // See the note about V8 multithreading in net/proxy/proxy_resolver_v8.h + // to understand why we have this limitation. + LOG(ERROR) << "Cannot use V8 Proxy resolver in single process mode."; + use_v8 = false; // Fallback to non-v8 implementation. + } + + size_t num_pac_threads = 0u; // Use default number of threads. + + // Check the command line for an override on the number of proxy resolver + // threads to use. + if (command_line.HasSwitch(switches::kNumPacThreads)) { + std::string s = command_line.GetSwitchValueASCII(switches::kNumPacThreads); + + // Parse the switch (it should be a positive integer formatted as decimal). + int n; + if (base::StringToInt(s, &n) && n > 0) { + num_pac_threads = static_cast<size_t>(n); + } else { + LOG(ERROR) << "Invalid switch for number of PAC threads: " << s; + } + } + + net::ProxyService* proxy_service; + if (use_v8) { + proxy_service = net::ProxyService::CreateUsingV8ProxyResolver( + proxy_config_service, + num_pac_threads, + new net::ProxyScriptFetcherImpl(context), + context->host_resolver(), + net_log); + } else { + proxy_service = net::ProxyService::CreateUsingSystemProxyResolver( + proxy_config_service, + num_pac_threads, + net_log); + } + +#if defined(OS_CHROMEOS) + if (chromeos::CrosLibrary::Get()->EnsureLoaded()) { + chromeos::CrosLibrary::Get()->GetLibCrosServiceLibrary()-> + RegisterNetworkProxyHandler(proxy_service); + } +#endif // defined(OS_CHROMEOS) + + return proxy_service; } diff --git a/chrome/browser/profiles/profile_io_data.h b/chrome/browser/profiles/profile_io_data.h index 2d7f888..c598b91 100644 --- a/chrome/browser/profiles/profile_io_data.h +++ b/chrome/browser/profiles/profile_io_data.h @@ -10,85 +10,53 @@ #include "base/file_path.h" #include "base/ref_counted.h" #include "base/scoped_ptr.h" +#include "chrome/browser/net/chrome_url_request_context.h" +#include "net/base/cookie_monster.h" +class CommandLine; +class ChromeAppCacheService; +class ChromeBlobStorageContext; class ChromeURLRequestContext; class ChromeURLRequestContextGetter; +class ExtensionInfoMap; +class ExtensionIOEventRouter; +namespace fileapi { +class FileSystemContext; +} +class HostContentSettingsMap; +class HostZoomMap; class IOThread; +namespace net { +class DnsCertProvenanceChecker; +class NetLog; +class ProxyConfigService; +class ProxyService; +class SSLConfigService; +class TransportSecurityState; +} // namespace net +namespace prerender { +class PrerenderManager; +}; // namespace prerender class Profile; - -// ProfileImpl owns a ProfileIOData::Handle, which holds a reference to the -// ProfileIOData. ProfileIOData is intended to own all the objects owned by -// ProfileImpl which live on the IO thread, such as, but not limited to, network -// objects like CookieMonster, HttpTransactionFactory, etc. ProfileIOData is -// owned by the ProfileImpl and ProfileIOData's ChromeURLRequestContexts. When -// all of them go away, then ProfileIOData will be deleted. Note that the -// ProfileIOData will typically outlive the Profile it is "owned" by, so it's -// important for ProfileIOData not to hold any references to the Profile beyond -// what's used by LazyParams (which should be deleted after lazy -// initialization). +namespace webkit_database { +class DatabaseTracker; +} // webkit_database + +// Conceptually speaking, the ProfileIOData represents data that lives on the IO +// thread that is owned by a Profile, such as, but not limited to, network +// objects like CookieMonster, HttpTransactionFactory, etc. The Profile +// implementation will maintain a reference to the ProfileIOData. The +// ProfileIOData will originally own a reference to the ChromeURLRequestContexts +// that reference its members. When an accessor for a ChromeURLRequestContext is +// invoked, then ProfileIOData will release its reference to the +// ChromeURLRequestContext and the ChromeURLRequestContext will acquire a +// reference to the ProfileIOData, so they exchange ownership. This is done +// because it's possible for a context's accessor never to be invoked, so this +// ownership reversal prevents shutdown leaks. ProfileIOData will lazily +// initialize its members on the first invocation of a ChromeURLRequestContext +// accessor. class ProfileIOData : public base::RefCountedThreadSafe<ProfileIOData> { public: - class Handle { - public: - Handle(); - ~Handle(); - - // Init() must be called before ~Handle(). It records all the necessary - // parameters needed to construct a ChromeURLRequestContextGetter. - void Init(const FilePath& cookie_path, - const FilePath& cache_path, - int cache_max_size, - const FilePath& media_cache_path, - int media_cache_max_size, - const FilePath& extensions_cookie_path, - Profile* profile); - - bool HasMainRequestContext() const { - return main_request_context_getter_ != NULL; - } - scoped_refptr<ChromeURLRequestContextGetter> - GetMainRequestContextGetter() const; - scoped_refptr<ChromeURLRequestContextGetter> - GetMediaRequestContextGetter() const; - scoped_refptr<ChromeURLRequestContextGetter> - GetExtensionsRequestContextGetter() const; - - private: - // Ordering is important here. Do not reorder unless you know what you're - // doing. |io_data_| must be released before the getters to ensure - // that ProfileIOData is deleted on the IO thread. - mutable scoped_refptr<ChromeURLRequestContextGetter> - main_request_context_getter_; - mutable scoped_refptr<ChromeURLRequestContextGetter> - media_request_context_getter_; - mutable scoped_refptr<ChromeURLRequestContextGetter> - extensions_request_context_getter_; - const scoped_refptr<ProfileIOData> io_data_; - - DISALLOW_COPY_AND_ASSIGN(Handle); - }; - - // TODO(willchan): Move this to the private section when - // ChromeURLRequestContextFactory subclasses don't need it anymore. - struct LazyParams { - LazyParams(); - ~LazyParams(); - - // All of these parameters are intended to be read on the IO thread. - FilePath cookie_path; - FilePath cache_path; - int cache_max_size; - FilePath media_cache_path; - int media_cache_max_size; - FilePath extensions_cookie_path; - IOThread* io_thread; - - // TODO(willchan): Kill this, since the IO thread shouldn't be reading from - // the Profile. Instead, replace this with the parameters we want to copy - // from the UI thread to the IO thread. - Profile* profile; - }; - // These should only be called at most once each. Ownership is reversed they // get called, from ProfileIOData owning ChromeURLRequestContext to vice // versa. @@ -96,30 +64,93 @@ class ProfileIOData : public base::RefCountedThreadSafe<ProfileIOData> { scoped_refptr<ChromeURLRequestContext> GetMediaRequestContext() const; scoped_refptr<ChromeURLRequestContext> GetExtensionsRequestContext() const; - // TODO(willchan): Delete this when ChromeURLRequestContextFactory subclasses - // don't need it anymore. - const LazyParams& lazy_params() const; - - private: + protected: friend class base::RefCountedThreadSafe<ProfileIOData>; - class RequestContext; + class RequestContext : public ChromeURLRequestContext { + public: + RequestContext(); + ~RequestContext(); + + // Setter is used to transfer ownership of the ProfileIOData to the context. + void set_profile_io_data(const ProfileIOData* profile_io_data) { + profile_io_data_ = profile_io_data; + } - ProfileIOData(); - ~ProfileIOData(); + private: + scoped_refptr<const ProfileIOData> profile_io_data_; + }; - // Lazily initializes ProfileIOData. + // Created on the UI thread, read on the IO thread during ProfileIOData lazy + // initialization. + struct ProfileParams { + ProfileParams(); + ~ProfileParams(); + + bool is_off_the_record; + bool clear_local_state_on_exit; + std::string accept_language; + std::string accept_charset; + std::string referrer_charset; + FilePath user_script_dir_path; + scoped_refptr<HostContentSettingsMap> host_content_settings_map; + scoped_refptr<HostZoomMap> host_zoom_map; + scoped_refptr<net::TransportSecurityState> transport_security_state; + scoped_refptr<net::SSLConfigService> ssl_config_service; + scoped_refptr<net::CookieMonster::Delegate> cookie_monster_delegate; + scoped_refptr<webkit_database::DatabaseTracker> database_tracker; + scoped_refptr<ChromeAppCacheService> appcache_service; + scoped_refptr<ChromeBlobStorageContext> blob_storage_context; + scoped_refptr<fileapi::FileSystemContext> file_system_context; + scoped_refptr<ExtensionInfoMap> extension_info_map; + scoped_refptr<ExtensionIOEventRouter> extension_io_event_router; + scoped_refptr<prerender::PrerenderManager> prerender_manager; + // 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; + }; + + explicit ProfileIOData(bool is_off_the_record); + virtual ~ProfileIOData(); + + // Static helper functions to assist in common operations executed by + // subtypes. + + static void InitializeProfileParams(Profile* profile, ProfileParams* params); + static void ApplyProfileParamsToContext(const ProfileParams& profile_params, + ChromeURLRequestContext* context); + static net::ProxyConfigService* CreateProxyConfigService(Profile* profile); + static net::ProxyService* CreateProxyService( + net::NetLog* net_log, + net::URLRequestContext* context, + net::ProxyConfigService* proxy_config_service, + const CommandLine& command_line); + + // Lazy initializes the ProfileIOData object the first time a request context + // is requested. The lazy logic is implemented here. The actual initialization + // is done in LazyInitializeInternal(), implemented by subtypes. Static helper + // functions have been provided to assist in common operations. void LazyInitialize() const; - // Lazy initialization params. - // TODO(willchan): Delete after Initialize() finishes initializing all the - // contexts. - scoped_ptr<const LazyParams> lazy_params_; + // -------------------------------------------- + // Virtual interface for subtypes to implement: + // -------------------------------------------- + + // Does that actual initialization of the ProfileIOData subtype. Subtypes + // should use the static helper functions above to implement this. + virtual void LazyInitializeInternal() const = 0; + + // These functions are used to transfer ownership of the lazily initialized + // context from ProfileIOData to the URLRequestContextGetter. + virtual scoped_refptr<ChromeURLRequestContext> + AcquireMainRequestContext() const = 0; + virtual scoped_refptr<ChromeURLRequestContext> + AcquireMediaRequestContext() const = 0; + virtual scoped_refptr<ChromeURLRequestContext> + AcquireExtensionsRequestContext() const = 0; mutable bool initialized_; - mutable scoped_refptr<RequestContext> main_request_context_; - mutable scoped_refptr<RequestContext> media_request_context_; - mutable scoped_refptr<RequestContext> extensions_request_context_; DISALLOW_COPY_AND_ASSIGN(ProfileIOData); }; |