summaryrefslogtreecommitdiffstats
path: root/chrome/browser/profiles
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/browser/profiles')
-rw-r--r--chrome/browser/profiles/off_the_record_profile_io_data.cc188
-rw-r--r--chrome/browser/profiles/off_the_record_profile_io_data.h110
-rw-r--r--chrome/browser/profiles/profile.cc52
-rw-r--r--chrome/browser/profiles/profile_impl.cc49
-rw-r--r--chrome/browser/profiles/profile_impl.h6
-rw-r--r--chrome/browser/profiles/profile_impl_io_data.cc282
-rw-r--r--chrome/browser/profiles/profile_impl_io_data.h114
-rw-r--r--chrome/browser/profiles/profile_io_data.cc405
-rw-r--r--chrome/browser/profiles/profile_io_data.h207
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);
};