| Index: chrome/browser/profile.cc
|
| diff --git a/chrome/browser/profile.cc b/chrome/browser/profile.cc
|
| index d8f2f6439f39634af1a99cfe1f150b4771a6a09a..9014424da2815ce3caddc12377a696cf7a78f040 100644
|
| --- a/chrome/browser/profile.cc
|
| +++ b/chrome/browser/profile.cc
|
| @@ -21,6 +21,7 @@
|
| #include "chrome/browser/greasemonkey_master.h"
|
| #include "chrome/browser/history/history.h"
|
| #include "chrome/browser/navigation_controller.h"
|
| +#include "chrome/browser/net/chrome_url_request_context.h"
|
| #include "chrome/browser/profile_manager.h"
|
| #include "chrome/browser/render_process_host.h"
|
| #include "chrome/browser/sessions/session_service.h"
|
| @@ -76,272 +77,6 @@ URLRequestContext* Profile::GetDefaultRequestContext() {
|
| }
|
|
|
|
|
| -// Sets up proxy info if it was specified, otherwise returns NULL. The
|
| -// returned pointer MUST be deleted by the caller if non-NULL.
|
| -static net::ProxyInfo* CreateProxyInfo(const CommandLine& command_line) {
|
| - net::ProxyInfo* proxy_info = NULL;
|
| -
|
| - if (command_line.HasSwitch(switches::kProxyServer)) {
|
| - proxy_info = new net::ProxyInfo();
|
| - const std::wstring& proxy_server =
|
| - command_line.GetSwitchValue(switches::kProxyServer);
|
| - proxy_info->UseNamedProxy(WideToASCII(proxy_server));
|
| - }
|
| -
|
| - return proxy_info;
|
| -}
|
| -
|
| -// Releases the URLRequestContext and sends out a notification about it.
|
| -// Note: runs on IO thread.
|
| -static void ReleaseURLRequestContext(URLRequestContext* context) {
|
| - NotificationService::current()->Notify(NOTIFY_URL_REQUEST_CONTEXT_RELEASED,
|
| - Source<URLRequestContext>(context),
|
| - NotificationService::NoDetails());
|
| - context->Release();
|
| -}
|
| -
|
| -// A context for URLRequests issued relative to this profile.
|
| -class ProfileImpl::RequestContext : public URLRequestContext,
|
| - public NotificationObserver {
|
| - public:
|
| - // |cookie_store_path| is the local disk path at which the cookie store
|
| - // is persisted.
|
| - RequestContext(const std::wstring& cookie_store_path,
|
| - const std::wstring& disk_cache_path,
|
| - PrefService* prefs)
|
| - : prefs_(prefs) {
|
| - cookie_store_ = NULL;
|
| -
|
| - // setup user agent
|
| - user_agent_ = webkit_glue::GetUserAgent();
|
| - // set up Accept-Language and Accept-Charset header values
|
| - // TODO(jungshik) : This may slow down http requests. Perhaps,
|
| - // we have to come up with a better way to set up these values.
|
| - accept_language_ = WideToASCII(prefs_->GetString(prefs::kAcceptLanguages));
|
| - accept_charset_ = WideToASCII(prefs_->GetString(prefs::kDefaultCharset));
|
| - accept_charset_ += ",*,utf-8";
|
| -
|
| - CommandLine command_line;
|
| -
|
| - scoped_ptr<net::ProxyInfo> proxy_info(CreateProxyInfo(command_line));
|
| - proxy_service_ = net::ProxyService::Create(proxy_info.get());
|
| -
|
| - net::HttpCache* cache =
|
| - new net::HttpCache(proxy_service_, disk_cache_path, 0);
|
| -
|
| - bool record_mode = chrome::kRecordModeEnabled &&
|
| - CommandLine().HasSwitch(switches::kRecordMode);
|
| - bool playback_mode = CommandLine().HasSwitch(switches::kPlaybackMode);
|
| -
|
| - if (record_mode || playback_mode) {
|
| - // Don't use existing cookies and use an in-memory store.
|
| - cookie_store_ = new net::CookieMonster();
|
| - cache->set_mode(
|
| - record_mode ? net::HttpCache::RECORD : net::HttpCache::PLAYBACK);
|
| - }
|
| - http_transaction_factory_ = cache;
|
| -
|
| - // setup cookie store
|
| - if (!cookie_store_) {
|
| - DCHECK(!cookie_store_path.empty());
|
| - cookie_db_.reset(new SQLitePersistentCookieStore(
|
| - cookie_store_path, g_browser_process->db_thread()->message_loop()));
|
| - cookie_store_ = new net::CookieMonster(cookie_db_.get());
|
| - }
|
| -
|
| - cookie_policy_.SetType(net::CookiePolicy::FromInt(
|
| - prefs_->GetInteger(prefs::kCookieBehavior)));
|
| -
|
| - // The first request context to be created is the one for the default
|
| - // profile - at least until we support multiple profiles.
|
| - if (!default_request_context_)
|
| - default_request_context_ = this;
|
| - NotificationService::current()->Notify(
|
| - NOTIFY_DEFAULT_REQUEST_CONTEXT_AVAILABLE,
|
| - NotificationService::AllSources(), NotificationService::NoDetails());
|
| -
|
| - // Register for notifications about prefs.
|
| - prefs_->AddPrefObserver(prefs::kAcceptLanguages, this);
|
| - prefs_->AddPrefObserver(prefs::kCookieBehavior, this);
|
| - }
|
| -
|
| - // NotificationObserver implementation.
|
| - virtual void Observe(NotificationType type,
|
| - const NotificationSource& source,
|
| - const NotificationDetails& details) {
|
| - if (NOTIFY_PREF_CHANGED == type) {
|
| - std::wstring* pref_name_in = Details<std::wstring>(details).ptr();
|
| - PrefService* prefs = Source<PrefService>(source).ptr();
|
| - DCHECK(pref_name_in && prefs);
|
| - if (*pref_name_in == prefs::kAcceptLanguages) {
|
| - std::string accept_language =
|
| - WideToASCII(prefs->GetString(prefs::kAcceptLanguages));
|
| - g_browser_process->io_thread()->message_loop()->PostTask(FROM_HERE,
|
| - NewRunnableMethod(this,
|
| - &RequestContext::OnAcceptLanguageChange,
|
| - accept_language));
|
| - } else if (*pref_name_in == prefs::kCookieBehavior) {
|
| - net::CookiePolicy::Type type = net::CookiePolicy::FromInt(
|
| - prefs_->GetInteger(prefs::kCookieBehavior));
|
| - g_browser_process->io_thread()->message_loop()->PostTask(FROM_HERE,
|
| - NewRunnableMethod(this,
|
| - &RequestContext::OnCookiePolicyChange,
|
| - type));
|
| - }
|
| - }
|
| - }
|
| -
|
| - // Since ProfileImpl::RequestContext will be destroyed on IO thread, but all
|
| - // PrefService observers are needed to clear in before destroying ProfileImpl.
|
| - // So we use to CleanupBeforeDestroy to do this thing. This function need to
|
| - // be called on destructor of ProfileImpl.
|
| - void CleanupBeforeDestroy() {
|
| - // Unregister for pref notifications.
|
| - prefs_->RemovePrefObserver(prefs::kAcceptLanguages, this);
|
| - prefs_->RemovePrefObserver(prefs::kCookieBehavior, this);
|
| - prefs_ = NULL;
|
| - }
|
| -
|
| - void OnAcceptLanguageChange(std::string accept_language) {
|
| - DCHECK(MessageLoop::current() ==
|
| - ChromeThread::GetMessageLoop(ChromeThread::IO));
|
| - accept_language_ = accept_language;
|
| - }
|
| -
|
| - void OnCookiePolicyChange(net::CookiePolicy::Type type) {
|
| - DCHECK(MessageLoop::current() ==
|
| - ChromeThread::GetMessageLoop(ChromeThread::IO));
|
| - cookie_policy_.SetType(type);
|
| - }
|
| -
|
| - virtual ~RequestContext() {
|
| - DCHECK(NULL == prefs_);
|
| - delete cookie_store_;
|
| - delete http_transaction_factory_;
|
| - delete proxy_service_;
|
| -
|
| - if (default_request_context_ == this)
|
| - default_request_context_ = NULL;
|
| - }
|
| -
|
| - private:
|
| - scoped_ptr<SQLitePersistentCookieStore> cookie_db_;
|
| - PrefService* prefs_;
|
| -};
|
| -
|
| -////////////////////////////////////////////////////////////////////////////////
|
| -//
|
| -// An URLRequestContext proxy for OffTheRecord. This request context is
|
| -// really a proxy to the original profile's request context but set
|
| -// is_off_the_record_ to true.
|
| -//
|
| -// TODO(ACW). Do we need to share the FtpAuthCache with the real request context
|
| -// see bug 974328
|
| -//
|
| -// TODO(jackson): http://b/issue?id=1197350 Remove duplicated code from above.
|
| -//
|
| -////////////////////////////////////////////////////////////////////////////////
|
| -class OffTheRecordRequestContext : public URLRequestContext,
|
| - public NotificationObserver {
|
| - public:
|
| - explicit OffTheRecordRequestContext(Profile* profile) {
|
| - DCHECK(!profile->IsOffTheRecord());
|
| - prefs_ = profile->GetPrefs();
|
| - DCHECK(prefs_);
|
| -
|
| - // The OffTheRecordRequestContext is owned by the OffTheRecordProfileImpl
|
| - // which is itself owned by the original profile. We reference the original
|
| - // context to make sure it doesn't go away when we delete the object graph.
|
| - original_context_ = profile->GetRequestContext();
|
| -
|
| - // Share the same proxy service as the original profile. This proxy
|
| - // service's lifespan is dependent on the lifespan of the original profile,
|
| - // which we reference (see above).
|
| - proxy_service_ = original_context_->proxy_service();
|
| -
|
| - http_transaction_factory_ = new net::HttpCache(proxy_service_, 0);
|
| - cookie_store_ = new net::CookieMonster;
|
| - cookie_policy_.SetType(net::CookiePolicy::FromInt(
|
| - prefs_->GetInteger(prefs::kCookieBehavior)));
|
| - user_agent_ = original_context_->user_agent();
|
| - accept_language_ = original_context_->accept_language();
|
| - accept_charset_ = original_context_->accept_charset();
|
| - is_off_the_record_ = true;
|
| -
|
| - // Register for notifications about prefs.
|
| - prefs_->AddPrefObserver(prefs::kAcceptLanguages, this);
|
| - prefs_->AddPrefObserver(prefs::kCookieBehavior, this);
|
| - }
|
| -
|
| - // Since OffTheRecordProfileImpl maybe be destroyed after destroying
|
| - // PrefService, but all PrefService observers are needed to clear in
|
| - // before destroying PrefService. So we use to CleanupBeforeDestroy
|
| - // to do this thing. This function need to be called on destructor
|
| - // of ProfileImpl.
|
| - void CleanupBeforeDestroy() {
|
| - // Unregister for pref notifications.
|
| - prefs_->RemovePrefObserver(prefs::kAcceptLanguages, this);
|
| - prefs_->RemovePrefObserver(prefs::kCookieBehavior, this);
|
| - prefs_ = NULL;
|
| - }
|
| -
|
| - // NotificationObserver implementation.
|
| - virtual void Observe(NotificationType type,
|
| - const NotificationSource& source,
|
| - const NotificationDetails& details) {
|
| - if (NOTIFY_PREF_CHANGED == type) {
|
| - std::wstring* pref_name_in = Details<std::wstring>(details).ptr();
|
| - PrefService* prefs = Source<PrefService>(source).ptr();
|
| - DCHECK(pref_name_in && prefs);
|
| - if (*pref_name_in == prefs::kAcceptLanguages) {
|
| - std::string accept_language =
|
| - WideToASCII(prefs->GetString(prefs::kAcceptLanguages));
|
| - g_browser_process->io_thread()->message_loop()->PostTask(FROM_HERE,
|
| - NewRunnableMethod(
|
| - this,
|
| - &OffTheRecordRequestContext::OnAcceptLanguageChange,
|
| - accept_language));
|
| - } else if (*pref_name_in == prefs::kCookieBehavior) {
|
| - net::CookiePolicy::Type type = net::CookiePolicy::FromInt(
|
| - prefs_->GetInteger(prefs::kCookieBehavior));
|
| - g_browser_process->io_thread()->message_loop()->PostTask(FROM_HERE,
|
| - NewRunnableMethod(this,
|
| - &OffTheRecordRequestContext::OnCookiePolicyChange,
|
| - type));
|
| - }
|
| - }
|
| - }
|
| -
|
| - void OnAcceptLanguageChange(std::string accept_language) {
|
| - DCHECK(MessageLoop::current() ==
|
| - ChromeThread::GetMessageLoop(ChromeThread::IO));
|
| - accept_language_ = accept_language;
|
| - }
|
| -
|
| - void OnCookiePolicyChange(net::CookiePolicy::Type type) {
|
| - DCHECK(MessageLoop::current() ==
|
| - ChromeThread::GetMessageLoop(ChromeThread::IO));
|
| - cookie_policy_.SetType(type);
|
| - }
|
| -
|
| - virtual ~OffTheRecordRequestContext() {
|
| - DCHECK(NULL == prefs_);
|
| - delete cookie_store_;
|
| - delete http_transaction_factory_;
|
| - // NOTE: do not delete |proxy_service_| as is owned by the original profile.
|
| -
|
| - // The OffTheRecordRequestContext simply act as a proxy to the real context.
|
| - // There is nothing else to delete.
|
| - }
|
| -
|
| - private:
|
| - // The original (non off the record) URLRequestContext.
|
| - scoped_refptr<URLRequestContext> original_context_;
|
| - PrefService* prefs_;
|
| -
|
| - DISALLOW_EVIL_CONSTRUCTORS(OffTheRecordRequestContext);
|
| -};
|
| -
|
| ////////////////////////////////////////////////////////////////////////////////
|
| //
|
| // OffTheRecordProfileImpl is a profile subclass that wraps an existing profile
|
| @@ -354,7 +89,7 @@ class OffTheRecordProfileImpl : public Profile,
|
| explicit OffTheRecordProfileImpl(Profile* real_profile)
|
| : profile_(real_profile),
|
| start_time_(Time::Now()) {
|
| - request_context_ = new OffTheRecordRequestContext(real_profile);
|
| + request_context_ = ChromeURLRequestContext::CreateOffTheRecord(this);
|
| request_context_->AddRef();
|
| // Register for browser close notifications so we can detect when the last
|
| // off-the-record window is closed, in which case we can clean our states
|
| @@ -365,10 +100,12 @@ class OffTheRecordProfileImpl : public Profile,
|
|
|
| virtual ~OffTheRecordProfileImpl() {
|
| if (request_context_) {
|
| - request_context_->CleanupBeforeDestroy();
|
| + request_context_->CleanupOnUIThread();
|
| +
|
| // Clean up request context on IO thread.
|
| g_browser_process->io_thread()->message_loop()->PostTask(FROM_HERE,
|
| - NewRunnableFunction(&ReleaseURLRequestContext, request_context_));
|
| + NewRunnableMethod(request_context_,
|
| + &base::RefCountedThreadSafe<URLRequestContext>::Release));
|
| request_context_ = NULL;
|
| }
|
| NotificationService::current()->RemoveObserver(
|
| @@ -545,8 +282,8 @@ class OffTheRecordProfileImpl : public Profile,
|
| // The real underlying profile.
|
| Profile* profile_;
|
|
|
| - // A proxy to the real request context.
|
| - OffTheRecordRequestContext* request_context_;
|
| + // The context to use for requests made from this OTR session.
|
| + ChromeURLRequestContext* request_context_;
|
|
|
| // The download manager that only stores downloaded items in memory.
|
| scoped_refptr<DownloadManager> download_manager_;
|
| @@ -628,10 +365,15 @@ ProfileImpl::~ProfileImpl() {
|
| }
|
|
|
| if (request_context_) {
|
| - request_context_->CleanupBeforeDestroy();
|
| + request_context_->CleanupOnUIThread();
|
| +
|
| + if (default_request_context_ == request_context_)
|
| + default_request_context_ = NULL;
|
| +
|
| // Clean up request context on IO thread.
|
| - io_thread->message_loop()->PostTask(FROM_HERE,
|
| - NewRunnableFunction(&ReleaseURLRequestContext, request_context_));
|
| + g_browser_process->io_thread()->message_loop()->PostTask(FROM_HERE,
|
| + NewRunnableMethod(request_context_,
|
| + &base::RefCountedThreadSafe<URLRequestContext>::Release));
|
| request_context_ = NULL;
|
| }
|
|
|
| @@ -753,10 +495,20 @@ URLRequestContext* ProfileImpl::GetRequestContext() {
|
| file_util::AppendToPath(&cookie_path, chrome::kCookieFilename);
|
| std::wstring cache_path = GetPath();
|
| file_util::AppendToPath(&cache_path, chrome::kCacheDirname);
|
| - request_context_ =
|
| - new ProfileImpl::RequestContext(cookie_path, cache_path, GetPrefs());
|
| + request_context_ = ChromeURLRequestContext::CreateOriginal(
|
| + this, cookie_path, cache_path);
|
| request_context_->AddRef();
|
|
|
| + // The first request context is always a normal (non-OTR) request context.
|
| + // Even when Chromium is started in OTR mode, a normal profile is always
|
| + // created first.
|
| + if (!default_request_context_) {
|
| + default_request_context_ = request_context_;
|
| + NotificationService::current()->Notify(
|
| + NOTIFY_DEFAULT_REQUEST_CONTEXT_AVAILABLE,
|
| + NotificationService::AllSources(), NotificationService::NoDetails());
|
| + }
|
| +
|
| DCHECK(request_context_->cookie_store());
|
| }
|
|
|
|
|