diff options
author | eroman@chromium.org <eroman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-10-23 06:33:31 +0000 |
---|---|---|
committer | eroman@chromium.org <eroman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-10-23 06:33:31 +0000 |
commit | be180c8044f145310f9eb13fd2cab5fd20e88220 (patch) | |
tree | 707ac9f3f95f5191664dbdac2ff3f34ab08ad8e7 /chrome/browser/net | |
parent | 4cb1d3be9986c105608991f3dde12c6346335060 (diff) | |
download | chromium_src-be180c8044f145310f9eb13fd2cab5fd20e88220.zip chromium_src-be180c8044f145310f9eb13fd2cab5fd20e88220.tar.gz chromium_src-be180c8044f145310f9eb13fd2cab5fd20e88220.tar.bz2 |
Move initialization of ChromeURLRequestContexts to the IO thread.
Before, these URLRequestContexts were lazily created from the UI thread. Unfortunately that model made it easy for consumers on the UI thread to poke at stuff which was being used from the IO thread, and introduce races.
So instead of providing a URLRequestContext*, the Profile now vends a URLRequestContextGetter*.
The consequence of this is:
* Consumers on the UI thread can no longer get access to a URLRequestContext.
* Consumers on the IO thread need to call URLRequestContextGetter::GetURLRequestContext() to get at the context. This uses the same style lazy-creation of URLRequestContexts, albeit from the IO thread.
OK, so now the smelly part:
There were a couple of consumers of URLRequestContext on the UI thread that can't easily be moved to the IO thread -- these are the consumers of the cookie store. Before they could happily mess with the cookie store from the UI thread, and this was fine since CookieStore is threadsafe. However under the new model, they have no way to get at the URLRequestContext from the UI thread, hence can't get a pointer to the cookie store.
To support that use-cases, I bastardized the API some by adding a URLRequestContextGetter::GetCookieStore() method that lets UI thread consumers get a pointer to the cookie store, since we know this particular cross-thread usage is safe.
BUG=http://crbug.com/22294
Review URL: http://codereview.chromium.org/258008
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@29880 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/net')
-rw-r--r-- | chrome/browser/net/chrome_url_request_context.cc | 596 | ||||
-rw-r--r-- | chrome/browser/net/chrome_url_request_context.h | 267 | ||||
-rw-r--r-- | chrome/browser/net/resolve_proxy_msg_helper.cc | 8 | ||||
-rw-r--r-- | chrome/browser/net/sdch_dictionary_fetcher.cc | 2 | ||||
-rw-r--r-- | chrome/browser/net/url_fetcher.cc | 14 | ||||
-rw-r--r-- | chrome/browser/net/url_fetcher.h | 4 | ||||
-rw-r--r-- | chrome/browser/net/url_fetcher_unittest.cc | 37 | ||||
-rw-r--r-- | chrome/browser/net/url_request_context_getter.cc | 10 | ||||
-rw-r--r-- | chrome/browser/net/url_request_context_getter.h | 30 |
9 files changed, 785 insertions, 183 deletions
diff --git a/chrome/browser/net/chrome_url_request_context.cc b/chrome/browser/net/chrome_url_request_context.cc index 368e95e..33b6f61 100644 --- a/chrome/browser/net/chrome_url_request_context.cc +++ b/chrome/browser/net/chrome_url_request_context.cc @@ -24,10 +24,31 @@ #include "net/http/http_cache.h" #include "net/http/http_network_layer.h" #include "net/http/http_util.h" +#include "net/proxy/proxy_config_service_fixed.h" #include "net/proxy/proxy_service.h" #include "net/url_request/url_request.h" #include "webkit/glue/webkit_glue.h" +#if defined(OS_LINUX) +#include "net/ocsp/nss_ocsp.h" +#endif + +// TODO(eroman): Fix the definition ordering to match-up with the declaration +// ordering (this was done to help keep the diffs simple during +// refactor). + +// TODO(eroman): The ChromeURLRequestContext's Blacklist* is shared with the +// Profile... This is a problem since the Profile dies before +// the IO thread, so we may end up accessing a deleted variable. + +static void CheckCurrentlyOnIOThread() { + DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO)); +} + +static void CheckCurrentlyOnMainThread() { + DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); +} + net::ProxyConfig* CreateProxyConfig(const CommandLine& command_line) { // Scan for all "enable" type proxy switches. static const char* proxy_switches[] = { @@ -86,10 +107,33 @@ net::ProxyConfig* CreateProxyConfig(const CommandLine& command_line) { return proxy_config; } +static net::ProxyConfigService* CreateProxyConfigService( + const CommandLine& command_line) { + // The linux gconf-based proxy settings getter relies on being initialized + // from the UI thread. + CheckCurrentlyOnMainThread(); + + scoped_ptr<net::ProxyConfig> proxy_config_from_cmd_line( + CreateProxyConfig(command_line)); + + if (!proxy_config_from_cmd_line.get()) { + // Use system settings. + return net::ProxyService::CreateSystemProxyConfigService( + g_browser_process->io_thread()->message_loop(), + g_browser_process->file_thread()->message_loop()); + } + + // Otherwise use the fixed settings from the command line. + return new net::ProxyConfigServiceFixed(*proxy_config_from_cmd_line.get()); +} + // Create a proxy service according to the options on command line. -static net::ProxyService* CreateProxyService(URLRequestContext* context, - const CommandLine& command_line) { - scoped_ptr<net::ProxyConfig> proxy_config(CreateProxyConfig(command_line)); +static net::ProxyService* CreateProxyService( + URLRequestContext* context, + net::ProxyConfigService* proxy_config_service, + const CommandLine& command_line, + MessageLoop* io_loop) { + CheckCurrentlyOnIOThread(); bool use_v8 = !command_line.HasSwitch(switches::kWinHttpProxyResolver); if (use_v8 && command_line.HasSwitch(switches::kSingleProcess)) { @@ -100,38 +144,87 @@ static net::ProxyService* CreateProxyService(URLRequestContext* context, } return net::ProxyService::Create( - proxy_config.get(), + proxy_config_service, use_v8, context, - g_browser_process->io_thread()->message_loop(), - g_browser_process->file_thread()->message_loop()); + io_loop); } +// Lazily create a ChromeURLRequestContext using our factory. +URLRequestContext* ChromeURLRequestContextGetter::GetURLRequestContext() { + CheckCurrentlyOnIOThread(); + + if (!url_request_context_) { + DCHECK(factory_.get()); + url_request_context_ = factory_->Create(); + factory_.reset(); + } + + return url_request_context_; +} + +// Factory that creates the main ChromeURLRequestContext. +class FactoryForOriginal : public ChromeURLRequestContextFactory { + public: + FactoryForOriginal(Profile* profile, + const FilePath& cookie_store_path, + const FilePath& disk_cache_path, + int cache_size) + : ChromeURLRequestContextFactory(profile), + cookie_store_path_(cookie_store_path), + disk_cache_path_(disk_cache_path), + cache_size_(cache_size), + // 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. + proxy_config_service_( + CreateProxyConfigService( + *CommandLine::ForCurrentProcess())) { + } + + virtual ChromeURLRequestContext* Create(); + + private: + FilePath cookie_store_path_; + FilePath disk_cache_path_; + int cache_size_; + + scoped_ptr<net::ProxyConfigService> proxy_config_service_; +}; + // static -ChromeURLRequestContext* ChromeURLRequestContext::CreateOriginal( +ChromeURLRequestContextGetter* ChromeURLRequestContextGetter::CreateOriginal( Profile* profile, const FilePath& cookie_store_path, - const FilePath& disk_cache_path, int cache_size, - ChromeAppCacheService* appcache_service) { + const FilePath& disk_cache_path, int cache_size) { DCHECK(!profile->IsOffTheRecord()); - ChromeURLRequestContext* context = new ChromeURLRequestContext( - profile, appcache_service); + return new ChromeURLRequestContextGetter( + profile, + new FactoryForOriginal(profile, + cookie_store_path, + disk_cache_path, + cache_size)); +} - // The appcache service uses the profile's original context for UpdateJobs. - DCHECK(!appcache_service->request_context()); - appcache_service->set_request_context(context); +ChromeURLRequestContext* FactoryForOriginal::Create() { + ChromeURLRequestContext* context = new ChromeURLRequestContext; + ApplyProfileParametersToContext(context); // Global host resolver for the context. - context->host_resolver_ = chrome_browser_net::GetGlobalHostResolver(); + context->set_host_resolver(chrome_browser_net::GetGlobalHostResolver()); const CommandLine& command_line = *CommandLine::ForCurrentProcess(); - context->proxy_service_ = CreateProxyService(context, command_line); + context->set_proxy_service( + CreateProxyService(context, + proxy_config_service_.release(), + command_line, + MessageLoop::current() /*io_loop*/)); net::HttpCache* cache = - new net::HttpCache(context->host_resolver_, - context->proxy_service_, - context->ssl_config_service_, - disk_cache_path, cache_size); + new net::HttpCache(context->host_resolver(), + context->proxy_service(), + context->ssl_config_service(), + disk_cache_path_, cache_size_); if (command_line.HasSwitch(switches::kDisableByteRangeSupport)) cache->set_enable_range_support(false); @@ -142,80 +235,130 @@ ChromeURLRequestContext* ChromeURLRequestContext::CreateOriginal( if (record_mode || playback_mode) { // Don't use existing cookies and use an in-memory store. - context->cookie_store_ = new net::CookieMonster(); + context->set_cookie_store(new net::CookieMonster()); cache->set_mode( record_mode ? net::HttpCache::RECORD : net::HttpCache::PLAYBACK); } - context->http_transaction_factory_ = cache; + context->set_http_transaction_factory(cache); // The kWininetFtp switch is Windows specific because we have two FTP // implementations on Windows. #if defined(OS_WIN) if (!command_line.HasSwitch(switches::kWininetFtp)) - context->ftp_transaction_factory_ = - new net::FtpNetworkLayer(context->host_resolver_); + context->set_ftp_transaction_factory( + new net::FtpNetworkLayer(context->host_resolver())); #else - context->ftp_transaction_factory_ = - new net::FtpNetworkLayer(context->host_resolver_); + context->set_ftp_transaction_factory( + new net::FtpNetworkLayer(context->host_resolver())); #endif // setup cookie store - if (!context->cookie_store_) { - DCHECK(!cookie_store_path.empty()); + if (!context->cookie_store()) { + DCHECK(!cookie_store_path_.empty()); scoped_refptr<SQLitePersistentCookieStore> cookie_db = new SQLitePersistentCookieStore( - cookie_store_path, - g_browser_process->db_thread()->message_loop()); - context->cookie_store_ = new net::CookieMonster(cookie_db.get()); + cookie_store_path_, + db_loop_); + context->set_cookie_store(new net::CookieMonster(cookie_db.get())); } + // Create a new AppCacheService (issues fetches through the + // main URLRequestContext that we just created). + context->set_appcache_service( + new ChromeAppCacheService(profile_dir_path_, false)); + context->appcache_service()->set_request_context(context); + +#if defined(OS_LINUX) + // TODO(ukai): find a better way to set the URLRequestContext for OCSP. + net::SetURLRequestContextForOCSP(context); +#endif + return context; } // static -ChromeURLRequestContext* ChromeURLRequestContext::CreateOriginalForMedia( - Profile* profile, const FilePath& disk_cache_path, int cache_size, - ChromeAppCacheService* appcache_service) { +ChromeURLRequestContextGetter* +ChromeURLRequestContextGetter::CreateOriginalForMedia( + Profile* profile, const FilePath& disk_cache_path, int cache_size) { DCHECK(!profile->IsOffTheRecord()); return CreateRequestContextForMedia(profile, disk_cache_path, cache_size, - false, appcache_service); + false); } +// Factory that creates the ChromeURLRequestContext for extensions. +class FactoryForExtensions : public ChromeURLRequestContextFactory { + public: + FactoryForExtensions(Profile* profile, const FilePath& cookie_store_path) + : ChromeURLRequestContextFactory(profile), + cookie_store_path_(cookie_store_path) { + } + + virtual ChromeURLRequestContext* Create(); + + private: + FilePath cookie_store_path_; +}; + // static -ChromeURLRequestContext* ChromeURLRequestContext::CreateOriginalForExtensions( +ChromeURLRequestContextGetter* +ChromeURLRequestContextGetter::CreateOriginalForExtensions( Profile* profile, const FilePath& cookie_store_path) { DCHECK(!profile->IsOffTheRecord()); - ChromeURLRequestContext* context = new ChromeURLRequestContext( - profile, NULL); + return new ChromeURLRequestContextGetter( + profile, + new FactoryForExtensions(profile, cookie_store_path)); +} + +ChromeURLRequestContext* FactoryForExtensions::Create() { + ChromeURLRequestContext* context = new ChromeURLRequestContext; + ApplyProfileParametersToContext(context); // All we care about for extensions is the cookie store. - DCHECK(!cookie_store_path.empty()); + DCHECK(!cookie_store_path_.empty()); scoped_refptr<SQLitePersistentCookieStore> cookie_db = - new SQLitePersistentCookieStore( - cookie_store_path, - g_browser_process->db_thread()->message_loop()); + new SQLitePersistentCookieStore(cookie_store_path_, db_loop_); net::CookieMonster* cookie_monster = new net::CookieMonster(cookie_db.get()); // Enable cookies for extension URLs only. const char* schemes[] = {chrome::kExtensionScheme}; cookie_monster->SetCookieableSchemes(schemes, 1); - context->cookie_store_ = cookie_monster; + context->set_cookie_store(cookie_monster); return context; } +// Factory that creates the ChromeURLRequestContext for incognito profile. +class FactoryForOffTheRecord : public ChromeURLRequestContextFactory { + public: + FactoryForOffTheRecord(Profile* profile) + : ChromeURLRequestContextFactory(profile), + original_context_getter_( + static_cast<ChromeURLRequestContextGetter*>( + profile->GetOriginalProfile()->GetRequestContext())) { + } + + virtual ChromeURLRequestContext* Create(); + + private: + scoped_refptr<ChromeURLRequestContextGetter> original_context_getter_; +}; + // static -ChromeURLRequestContext* ChromeURLRequestContext::CreateOffTheRecord( - Profile* profile, ChromeAppCacheService* appcache_service) { +ChromeURLRequestContextGetter* ChromeURLRequestContextGetter::CreateOffTheRecord( + Profile* profile) { DCHECK(profile->IsOffTheRecord()); - ChromeURLRequestContext* context = new ChromeURLRequestContext( - profile, appcache_service); + return new ChromeURLRequestContextGetter( + profile, new FactoryForOffTheRecord(profile)); +} + +ChromeURLRequestContext* FactoryForOffTheRecord::Create() { + ChromeURLRequestContext* context = new ChromeURLRequestContext; + ApplyProfileParametersToContext(context); - // The appcache service uses the profile's original context for UpdateJobs. - DCHECK(!appcache_service->request_context()); - appcache_service->set_request_context(context); + ChromeURLRequestContext* original_context = + original_context_getter_->GetIOContext(); // Share the same proxy service and host resolver as the original profile. // TODO(eroman): although ProxyService is reference counted, this sharing @@ -223,16 +366,14 @@ ChromeURLRequestContext* ChromeURLRequestContext::CreateOffTheRecord( // ProxyService holds a (non referencing) pointer to the URLRequestContext // it uses to download PAC scripts, which in this case is the original // profile... - context->host_resolver_ = - profile->GetOriginalProfile()->GetRequestContext()->host_resolver(); - context->proxy_service_ = - profile->GetOriginalProfile()->GetRequestContext()->proxy_service(); + context->set_host_resolver(original_context->host_resolver()); + context->set_proxy_service(original_context->proxy_service()); net::HttpCache* cache = - new net::HttpCache(context->host_resolver_, context->proxy_service_, - context->ssl_config_service_, 0); - context->cookie_store_ = new net::CookieMonster; - context->http_transaction_factory_ = cache; + new net::HttpCache(context->host_resolver(), context->proxy_service(), + context->ssl_config_service(), 0); + context->set_cookie_store(new net::CookieMonster); + context->set_http_transaction_factory(cache); if (CommandLine::ForCurrentProcess()->HasSwitch( switches::kDisableByteRangeSupport)) @@ -242,69 +383,129 @@ ChromeURLRequestContext* ChromeURLRequestContext::CreateOffTheRecord( // implementations on Windows. #if defined(OS_WIN) if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kWininetFtp)) - context->ftp_transaction_factory_ = - new net::FtpNetworkLayer(context->host_resolver_); + context->set_ftp_transaction_factory( + new net::FtpNetworkLayer(context->host_resolver())); #else - context->ftp_transaction_factory_ = - new net::FtpNetworkLayer(context->host_resolver_); + context->set_ftp_transaction_factory( + new net::FtpNetworkLayer(context->host_resolver())); #endif + // Create a separate AppCacheService for OTR mode. + context->set_appcache_service( + new ChromeAppCacheService(profile_dir_path_, true)); + context->appcache_service()->set_request_context(context); + return context; } +// Factory that creates the ChromeURLRequestContext for extensions in incognito +// mode. +class FactoryForOffTheRecordExtensions + : public ChromeURLRequestContextFactory { + public: + FactoryForOffTheRecordExtensions(Profile* profile) + : ChromeURLRequestContextFactory(profile) {} + + virtual ChromeURLRequestContext* Create(); +}; + // static -ChromeURLRequestContext* -ChromeURLRequestContext::CreateOffTheRecordForExtensions(Profile* profile) { +ChromeURLRequestContextGetter* +ChromeURLRequestContextGetter::CreateOffTheRecordForExtensions(Profile* profile) { DCHECK(profile->IsOffTheRecord()); - ChromeURLRequestContext* context = - new ChromeURLRequestContext(profile, NULL); + return new ChromeURLRequestContextGetter( + profile, + new FactoryForOffTheRecordExtensions(profile)); +} + +ChromeURLRequestContext* FactoryForOffTheRecordExtensions::Create() { + ChromeURLRequestContext* context = new ChromeURLRequestContext; + ApplyProfileParametersToContext(context); + net::CookieMonster* cookie_monster = new net::CookieMonster; // Enable cookies for extension URLs only. const char* schemes[] = {chrome::kExtensionScheme}; cookie_monster->SetCookieableSchemes(schemes, 1); - context->cookie_store_ = cookie_monster; + context->set_cookie_store(cookie_monster); return context; } +// Factory that creates the ChromeURLRequestContext for media. +class FactoryForMedia : public ChromeURLRequestContextFactory { + public: + FactoryForMedia(Profile* profile, + const FilePath& disk_cache_path, + int cache_size, + bool off_the_record) + : ChromeURLRequestContextFactory(profile), + main_context_getter_( + static_cast<ChromeURLRequestContextGetter*>( + profile->GetRequestContext())) { + is_media_ = true; + is_off_the_record_ = off_the_record; + } + + virtual ChromeURLRequestContext* Create(); + + private: + scoped_refptr<ChromeURLRequestContextGetter> main_context_getter_; + + FilePath disk_cache_path_; + int cache_size_; +}; + // static -ChromeURLRequestContext* ChromeURLRequestContext::CreateRequestContextForMedia( +ChromeURLRequestContextGetter* +ChromeURLRequestContextGetter::CreateRequestContextForMedia( Profile* profile, const FilePath& disk_cache_path, int cache_size, - bool off_the_record, ChromeAppCacheService* appcache_service) { - URLRequestContext* original_context = - profile->GetOriginalProfile()->GetRequestContext(); - ChromeURLRequestContext* context = - new ChromeURLRequestContext(profile, appcache_service); - context->is_media_ = true; + bool off_the_record) { + return new ChromeURLRequestContextGetter( + profile, + new FactoryForMedia(profile, + disk_cache_path, + cache_size, + off_the_record)); +} + +ChromeURLRequestContext* FactoryForMedia::Create() { + ChromeURLRequestContext* context = new ChromeURLRequestContext; + ApplyProfileParametersToContext(context); + + ChromeURLRequestContext* main_context = + main_context_getter_->GetIOContext(); // Share the same proxy service of the common profile. - context->proxy_service_ = original_context->proxy_service(); + context->set_proxy_service(main_context->proxy_service()); // Also share the cookie store of the common profile. - context->cookie_store_ = original_context->cookie_store(); + context->set_cookie_store(main_context->cookie_store()); // Create a media cache with default size. // TODO(hclam): make the maximum size of media cache configurable. - net::HttpCache* original_cache = - original_context->http_transaction_factory()->GetCache(); + net::HttpCache* main_cache = + main_context->http_transaction_factory()->GetCache(); net::HttpCache* cache; - if (original_cache) { - // Try to reuse HttpNetworkSession in the original context, assuming that + if (main_cache) { + // Try to reuse HttpNetworkSession in the main context, assuming that // HttpTransactionFactory (network_layer()) of HttpCache is implemented // by HttpNetworkLayer so we can reuse HttpNetworkSession within it. This // assumption will be invalid if the original HttpCache is constructed with // HttpCache(HttpTransactionFactory*, disk_cache::Backend*) constructor. - net::HttpNetworkLayer* original_network_layer = - static_cast<net::HttpNetworkLayer*>(original_cache->network_layer()); - cache = new net::HttpCache(original_network_layer->GetSession(), - disk_cache_path, cache_size); + net::HttpNetworkLayer* main_network_layer = + static_cast<net::HttpNetworkLayer*>(main_cache->network_layer()); + cache = new net::HttpCache(main_network_layer->GetSession(), + disk_cache_path_, cache_size_); + // TODO(eroman): Since this is poaching the session from the main + // context, it should hold a reference to that context preventing the + // session from getting deleted. } else { // If original HttpCache doesn't exist, simply construct one with a whole // new set of network stack. - cache = new net::HttpCache(original_context->host_resolver(), - original_context->proxy_service(), - original_context->ssl_config_service(), - disk_cache_path, cache_size); + cache = new net::HttpCache(main_context->host_resolver(), + main_context->proxy_service(), + main_context->ssl_config_service(), + disk_cache_path_, cache_size_); } if (CommandLine::ForCurrentProcess()->HasSwitch( @@ -312,21 +513,42 @@ ChromeURLRequestContext* ChromeURLRequestContext::CreateRequestContextForMedia( cache->set_enable_range_support(false); cache->set_type(net::MEDIA_CACHE); - context->http_transaction_factory_ = cache; + context->set_http_transaction_factory(cache); + + // Use the same appcache service as the profile's main context. + context->set_appcache_service(main_context->appcache_service()); + return context; } -ChromeURLRequestContext::ChromeURLRequestContext( - Profile* profile, ChromeAppCacheService* appcache_service) - : appcache_service_(appcache_service), - prefs_(profile->GetPrefs()), - is_media_(false), +ChromeURLRequestContextGetter::ChromeURLRequestContextGetter( + Profile* profile, + ChromeURLRequestContextFactory* factory) + : prefs_(NULL), + factory_(factory), + url_request_context_(NULL) { + DCHECK(factory); + + // If a base profile was specified, listen for changes to the preferences. + if (profile) + RegisterPrefsObserver(profile); +} + +// Extract values from |profile| and copy them into +// ChromeURLRequestContextFactory. We will use them later when constructing the +// ChromeURLRequestContext on the IO thread (see +// ApplyProfileParametersToContext() which reverses this). +ChromeURLRequestContextFactory::ChromeURLRequestContextFactory(Profile* profile) + : is_media_(false), is_off_the_record_(profile->IsOffTheRecord()) { + CheckCurrentlyOnMainThread(); + PrefService* prefs = profile->GetPrefs(); + // Set up Accept-Language and Accept-Charset header values accept_language_ = net::HttpUtil::GenerateAcceptLanguageHeader( - WideToASCII(prefs_->GetString(prefs::kAcceptLanguages))); + WideToASCII(prefs->GetString(prefs::kAcceptLanguages))); std::string default_charset = - WideToASCII(prefs_->GetString(prefs::kDefaultCharset)); + WideToASCII(prefs->GetString(prefs::kDefaultCharset)); accept_charset_ = net::HttpUtil::GenerateAcceptCharsetHeader(default_charset); @@ -344,11 +566,13 @@ ChromeURLRequestContext::ChromeURLRequestContext( // net_util::GetSuggestedFilename is unlikely to be taken. referrer_charset_ = default_charset; - cookie_policy_.set_type(net::CookiePolicy::FromInt( - prefs_->GetInteger(prefs::kCookieBehavior))); + cookie_policy_type_ = net::CookiePolicy::FromInt( + prefs->GetInteger(prefs::kCookieBehavior)); + // TODO(eroman): this doesn't look safe; sharing between IO and UI threads! blacklist_ = profile->GetBlacklist(); + // TODO(eroman): this doesn't look safe; sharing between IO and UI threads! strict_transport_security_state_ = profile->GetStrictTransportSecurityState(); if (profile->GetExtensionsService()) { @@ -363,15 +587,51 @@ ChromeURLRequestContext::ChromeURLRequestContext( if (profile->GetUserScriptMaster()) user_script_dir_path_ = profile->GetUserScriptMaster()->user_script_dir(); + // TODO(eroman): this doesn't look safe; sharing between IO and UI threads! + ssl_config_service_ = profile->GetSSLConfigService(); + + profile_dir_path_ = profile->GetPath(); + + // Get references to the database and file threads. + db_loop_ = g_browser_process->db_thread()->message_loop(); +} + +ChromeURLRequestContextFactory::~ChromeURLRequestContextFactory() { + CheckCurrentlyOnIOThread(); +} + +void ChromeURLRequestContextFactory::ApplyProfileParametersToContext( + ChromeURLRequestContext* context) { + // Apply all the parameters. NOTE: keep this in sync with + // ChromeURLRequestContextFactory(Profile*). + context->set_is_media(is_media_); + context->set_is_off_the_record(is_off_the_record_); + context->set_accept_language(accept_language_); + context->set_accept_charset(accept_charset_); + context->set_referrer_charset(referrer_charset_); + context->set_cookie_policy_type(cookie_policy_type_); + context->set_extension_paths(extension_paths_); + context->set_user_script_dir_path(user_script_dir_path_); + context->set_blacklist(blacklist_); + context->set_strict_transport_security_state( + strict_transport_security_state_); + context->set_ssl_config_service(ssl_config_service_); +} + +void ChromeURLRequestContextGetter::RegisterPrefsObserver(Profile* profile) { + CheckCurrentlyOnMainThread(); + + prefs_ = profile->GetPrefs(); + prefs_->AddPrefObserver(prefs::kAcceptLanguages, this); prefs_->AddPrefObserver(prefs::kCookieBehavior, this); prefs_->AddPrefObserver(prefs::kDefaultCharset, this); - - ssl_config_service_ = profile->GetSSLConfigService(); } ChromeURLRequestContext::ChromeURLRequestContext( ChromeURLRequestContext* other) { + CheckCurrentlyOnIOThread(); + // Set URLRequestContext members host_resolver_ = other->host_resolver_; proxy_service_ = other->proxy_service_; @@ -389,16 +649,17 @@ ChromeURLRequestContext::ChromeURLRequestContext( appcache_service_ = other->appcache_service_; extension_paths_ = other->extension_paths_; user_script_dir_path_ = other->user_script_dir_path_; - prefs_ = other->prefs_; blacklist_ = other->blacklist_; is_media_ = other->is_media_; is_off_the_record_ = other->is_off_the_record_; } // NotificationObserver implementation. -void ChromeURLRequestContext::Observe(NotificationType type, - const NotificationSource& source, - const NotificationDetails& details) { +void ChromeURLRequestContextGetter::Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details) { + CheckCurrentlyOnMainThread(); + if (NotificationType::PREF_CHANGED == type) { std::wstring* pref_name_in = Details<std::wstring>(details).ptr(); PrefService* prefs = Source<PrefService>(source).ptr(); @@ -407,39 +668,91 @@ void ChromeURLRequestContext::Observe(NotificationType type, std::string accept_language = WideToASCII(prefs->GetString(prefs::kAcceptLanguages)); g_browser_process->io_thread()->message_loop()->PostTask(FROM_HERE, - NewRunnableMethod(this, - &ChromeURLRequestContext::OnAcceptLanguageChange, - accept_language)); + NewRunnableMethod( + this, + &ChromeURLRequestContextGetter::OnAcceptLanguageChange, + accept_language)); } else if (*pref_name_in == prefs::kCookieBehavior) { net::CookiePolicy::Type policy_type = net::CookiePolicy::FromInt( prefs_->GetInteger(prefs::kCookieBehavior)); g_browser_process->io_thread()->message_loop()->PostTask(FROM_HERE, - NewRunnableMethod(this, - &ChromeURLRequestContext::OnCookiePolicyChange, - policy_type)); + NewRunnableMethod( + this, + &ChromeURLRequestContextGetter::OnCookiePolicyChange, + policy_type)); } else if (*pref_name_in == prefs::kDefaultCharset) { std::string default_charset = WideToASCII(prefs->GetString(prefs::kDefaultCharset)); g_browser_process->io_thread()->message_loop()->PostTask(FROM_HERE, - NewRunnableMethod(this, - &ChromeURLRequestContext::OnDefaultCharsetChange, - default_charset)); + NewRunnableMethod( + this, + &ChromeURLRequestContextGetter::OnDefaultCharsetChange, + default_charset)); } } else { NOTREACHED(); } } -void ChromeURLRequestContext::CleanupOnUIThread() { - // Unregister for pref notifications. - prefs_->RemovePrefObserver(prefs::kAcceptLanguages, this); - prefs_->RemovePrefObserver(prefs::kCookieBehavior, this); - prefs_->RemovePrefObserver(prefs::kDefaultCharset, this); - prefs_ = NULL; +void ChromeURLRequestContextGetter::OnAcceptLanguageChange( + const std::string& accept_language) { + GetIOContext()->OnAcceptLanguageChange(accept_language); +} + +void ChromeURLRequestContextGetter::OnCookiePolicyChange( + net::CookiePolicy::Type type) { + GetIOContext()->OnCookiePolicyChange(type); +} +void ChromeURLRequestContextGetter::OnDefaultCharsetChange( + const std::string& default_charset) { + GetIOContext()->OnDefaultCharsetChange(default_charset); +} + +void ChromeURLRequestContextGetter::OnNewExtensions(const std::string& id, + const FilePath& path) { + GetIOContext()->OnNewExtensions(id, path); +} + +void ChromeURLRequestContextGetter::OnUnloadedExtension( + const std::string& id) { + GetIOContext()->OnUnloadedExtension(id); +} + +void ChromeURLRequestContextGetter::CleanupOnUIThread() { + CheckCurrentlyOnMainThread(); + + if (prefs_) { + // Unregister for pref notifications. + prefs_->RemovePrefObserver(prefs::kAcceptLanguages, this); + prefs_->RemovePrefObserver(prefs::kCookieBehavior, this); + prefs_->RemovePrefObserver(prefs::kDefaultCharset, this); + prefs_ = NULL; + } + + // TODO(eroman): Doesn't look like this member is even used... + // can probably be deleted. registrar_.RemoveAll(); } +ChromeURLRequestContextGetter::~ChromeURLRequestContextGetter() { + CheckCurrentlyOnIOThread(); + + DCHECK(!prefs_) << "Probably didn't call CleanupOnUIThread"; + + // Either we already transformed the factory into a URLRequestContext, or + // we still have a pending factory. + DCHECK((factory_.get() && !url_request_context_.get()) || + (!factory_.get() && url_request_context_.get())); + + // The scoped_refptr / scoped_ptr destructors take care of releasing + // |factory_| and |url_request_context_| now. +} + +ChromeURLRequestContext::ChromeURLRequestContext() { + CheckCurrentlyOnIOThread(); +} + FilePath ChromeURLRequestContext::GetPathForExtension(const std::string& id) { ExtensionPaths::iterator iter = extension_paths_.find(id); if (iter != extension_paths_.end()) { @@ -496,23 +809,20 @@ bool ChromeURLRequestContext::AllowSendingCookies(const URLRequest* request) void ChromeURLRequestContext::OnAcceptLanguageChange( const std::string& accept_language) { - DCHECK(MessageLoop::current() == - ChromeThread::GetMessageLoop(ChromeThread::IO)); + CheckCurrentlyOnIOThread(); accept_language_ = net::HttpUtil::GenerateAcceptLanguageHeader(accept_language); } void ChromeURLRequestContext::OnCookiePolicyChange( net::CookiePolicy::Type type) { - DCHECK(MessageLoop::current() == - ChromeThread::GetMessageLoop(ChromeThread::IO)); + CheckCurrentlyOnIOThread(); cookie_policy_.set_type(type); } void ChromeURLRequestContext::OnDefaultCharsetChange( const std::string& default_charset) { - DCHECK(MessageLoop::current() == - ChromeThread::GetMessageLoop(ChromeThread::IO)); + CheckCurrentlyOnIOThread(); referrer_charset_ = default_charset; accept_charset_ = net::HttpUtil::GenerateAcceptCharsetHeader(default_charset); @@ -525,6 +835,7 @@ void ChromeURLRequestContext::OnNewExtensions(const std::string& id, } void ChromeURLRequestContext::OnUnloadedExtension(const std::string& id) { + CheckCurrentlyOnIOThread(); if (is_off_the_record_) return; ExtensionPaths::iterator iter = extension_paths_.find(id); @@ -533,8 +844,7 @@ void ChromeURLRequestContext::OnUnloadedExtension(const std::string& id) { } ChromeURLRequestContext::~ChromeURLRequestContext() { - DCHECK(NULL == prefs_); - + CheckCurrentlyOnIOThread(); if (appcache_service_.get() && appcache_service_->request_context() == this) appcache_service_->set_request_context(NULL); @@ -546,3 +856,35 @@ ChromeURLRequestContext::~ChromeURLRequestContext() { delete ftp_transaction_factory_; delete http_transaction_factory_; } + +net::CookieStore* ChromeURLRequestContextGetter::GetCookieStore() { + // If we are running on the IO thread this is real easy. + if (ChromeThread::CurrentlyOn(ChromeThread::IO)) + return GetURLRequestContext()->cookie_store(); + + // If we aren't running on the IO thread, we cannot call + // GetURLRequestContext(). Instead we will post a task to the IO loop + // and wait for it to complete. + + base::WaitableEvent completion(false, false); + net::CookieStore* result = NULL; + + g_browser_process->io_thread()->message_loop()->PostTask( + FROM_HERE, + NewRunnableMethod(this, + &ChromeURLRequestContextGetter::GetCookieStoreAsyncHelper, + &completion, + &result)); + + completion.Wait(); + DCHECK(result); + return result; +} + +void ChromeURLRequestContextGetter::GetCookieStoreAsyncHelper( + base::WaitableEvent* completion, + net::CookieStore** result) { + // Note that CookieStore is refcounted, yet we do not add a reference. + *result = GetURLRequestContext()->cookie_store(); + completion->Signal(); +} diff --git a/chrome/browser/net/chrome_url_request_context.h b/chrome/browser/net/chrome_url_request_context.h index 892593b..8bbfabe 100644 --- a/chrome/browser/net/chrome_url_request_context.h +++ b/chrome/browser/net/chrome_url_request_context.h @@ -2,7 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#ifndef CHROME_BROWSER_NET_CHROME_URL_REQUEST_CONTEXT_H_ +#define CHROME_BROWSER_NET_CHROME_URL_REQUEST_CONTEXT_H_ + #include "base/file_path.h" +#include "chrome/browser/net/url_request_context_getter.h" #include "chrome/common/appcache/chrome_appcache_service.h" #include "chrome/common/notification_registrar.h" #include "chrome/common/pref_service.h" @@ -16,50 +20,135 @@ namespace net { class ProxyConfig; } -// A URLRequestContext subclass used by the browser. This can be used to store -// extra information about requests, beyond what is supported by the base -// URLRequestContext class. +class ChromeURLRequestContext; +class ChromeURLRequestContextFactory; + +// TODO(eroman): Cleanup the declaration order in this file -- it is all +// wonky to try and minimize awkward deltas. + +// A URLRequestContextGetter subclass used by the browser. This returns a +// subclass of URLRequestContext which can be used to store extra information +// about requests. // -// All methods are expected to be called on the IO thread except the -// constructor and factories (CreateOriginal, CreateOffTheRecord), which are -// expected to be called on the UI thread. -class ChromeURLRequestContext : public URLRequestContext, - public NotificationObserver { +// Most methods are expected to be called on the UI thread, except for +// the destructor and GetURLRequestContext(). +class ChromeURLRequestContextGetter : public URLRequestContextGetter, + public NotificationObserver { public: - typedef std::map<std::string, FilePath> ExtensionPaths; + // Constructs a ChromeURLRequestContextGetter that will use |factory| to + // create the ChromeURLRequestContext. If |profile| is non-NULL, then the + // ChromeURLRequestContextGetter will additionally watch the preferences for + // changes to charset/language and CleanupOnUIThread() will need to be + // called to unregister. + ChromeURLRequestContextGetter(Profile* profile, + ChromeURLRequestContextFactory* factory); + + // Must be called on the IO thread. + virtual ~ChromeURLRequestContextGetter(); + + // Note that GetURLRequestContext() can only be called from the IO + // thread (it will assert otherwise). GetCookieStore() however can + // be called from any thread. + // + // URLRequestContextGetter implementation. + virtual URLRequestContext* GetURLRequestContext(); + virtual net::CookieStore* GetCookieStore(); + + // Convenience overload of GetURLRequestContext() that returns a + // ChromeURLRequestContext* rather than a URLRequestContext*. + ChromeURLRequestContext* GetIOContext() { + return reinterpret_cast<ChromeURLRequestContext*>(GetURLRequestContext()); + } // Create an instance for use with an 'original' (non-OTR) profile. This is // expected to get called on the UI thread. - static ChromeURLRequestContext* CreateOriginal( + static ChromeURLRequestContextGetter* CreateOriginal( Profile* profile, const FilePath& cookie_store_path, - const FilePath& disk_cache_path, int cache_size, - ChromeAppCacheService* appcache_service); + const FilePath& disk_cache_path, int cache_size); // Create an instance for an original profile for media. This is expected to // get called on UI thread. This method takes a profile and reuses the // 'original' URLRequestContext for common files. - static ChromeURLRequestContext* CreateOriginalForMedia(Profile *profile, - const FilePath& disk_cache_path, int cache_size, - ChromeAppCacheService* appcache_service); + static ChromeURLRequestContextGetter* CreateOriginalForMedia( + Profile* profile, const FilePath& disk_cache_path, int cache_size); // Create an instance for an original profile for extensions. This is expected // to get called on UI thread. - static ChromeURLRequestContext* CreateOriginalForExtensions(Profile *profile, - const FilePath& cookie_store_path); + static ChromeURLRequestContextGetter* CreateOriginalForExtensions( + Profile* profile, const FilePath& cookie_store_path); // Create an instance for use with an OTR profile. This is expected to get // called on the UI thread. - static ChromeURLRequestContext* CreateOffTheRecord(Profile* profile, - ChromeAppCacheService* appcache_service); + static ChromeURLRequestContextGetter* CreateOffTheRecord(Profile* profile); // Create an instance of request context for OTR profile for extensions. - static ChromeURLRequestContext* CreateOffTheRecordForExtensions( + static ChromeURLRequestContextGetter* CreateOffTheRecordForExtensions( Profile* profile); // Clean up UI thread resources. This is expected to get called on the UI // thread before the instance is deleted on the IO thread. void CleanupOnUIThread(); + // These methods simply forward to the corresponding method on + // ChromeURLRequestContext. + void OnNewExtensions(const std::string& id, const FilePath& path); + void OnUnloadedExtension(const std::string& id); + + // NotificationObserver implementation. + virtual void Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details); + + private: + // Registers an observer on |profile|'s preferences which will be used + // to update the context when the default language and charset change. + void RegisterPrefsObserver(Profile* profile); + + // Creates a request context for media resources from a regular request + // context. This helper method is called from CreateOriginalForMedia and + // CreateOffTheRecordForMedia. + static ChromeURLRequestContextGetter* CreateRequestContextForMedia( + Profile* profile, const FilePath& disk_cache_path, int cache_size, + bool off_the_record); + + // These methods simply forward to the corresponding method on + // ChromeURLRequestContext. + void OnAcceptLanguageChange(const std::string& accept_language); + void OnCookiePolicyChange(net::CookiePolicy::Type type); + void OnDefaultCharsetChange(const std::string& default_charset); + + // Saves the cookie store to |result| and signals |completion|. + void GetCookieStoreAsyncHelper(base::WaitableEvent* completion, + net::CookieStore** result); + + // Access only from the UI thread. + PrefService* prefs_; + NotificationRegistrar registrar_; + + // Deferred logic for creating a ChromeURLRequestContext. + // Access only from the IO thread. + scoped_ptr<ChromeURLRequestContextFactory> factory_; + + // NULL if not yet initialized. Otherwise, it is the URLRequestContext + // instance that was lazilly created by GetURLRequestContext. + // Access only from the IO thread. + scoped_refptr<URLRequestContext> url_request_context_; + + DISALLOW_COPY_AND_ASSIGN(ChromeURLRequestContextGetter); +}; + +// Subclass of URLRequestContext which can be used to store extra information +// for requests. +// +// All methods of this class must be called from the IO thread, +// including the constructor and destructor. +class ChromeURLRequestContext : public URLRequestContext { + public: + typedef std::map<std::string, FilePath> ExtensionPaths; + + ChromeURLRequestContext(); + virtual ~ChromeURLRequestContext(); + // Gets the path to the directory for the specified extension. FilePath GetPathForExtension(const std::string& id); @@ -74,6 +163,16 @@ class ChromeURLRequestContext : public URLRequestContext, return appcache_service_.get(); } + bool is_off_the_record() const { + return is_off_the_record_; + } + bool is_media() const { + return is_media_; + } + const ExtensionPaths& extension_paths() const { + return extension_paths_; + } + virtual const std::string& GetUserAgent(const GURL& url) const; virtual bool InterceptCookie(const URLRequest* request, std::string* cookie); @@ -90,23 +189,66 @@ class ChromeURLRequestContext : public URLRequestContext, void OnUnloadedExtension(const std::string& id); protected: - // Private constructors, use the static factory methods instead. This is - // expected to be called on the UI thread. - ChromeURLRequestContext( - Profile* profile, ChromeAppCacheService* appcache_service); + // Copies the dependencies from |other| into |this|. If you use this + // constructor, then you should hold a reference to |other|, as we + // depend on |other| being alive. ChromeURLRequestContext(ChromeURLRequestContext* other); - // Create a request context for media resources from a regular request - // context. This helper method is called from CreateOriginalForMedia and - // CreateOffTheRecordForMedia. - static ChromeURLRequestContext* CreateRequestContextForMedia(Profile* profile, - const FilePath& disk_cache_path, int cache_size, bool off_the_record, - ChromeAppCacheService* appache_service); + public: + // Setters to simplify initializing from factory objects. - // NotificationObserver implementation. - virtual void Observe(NotificationType type, - const NotificationSource& source, - const NotificationDetails& details); + void set_accept_language(const std::string& accept_language) { + accept_language_ = accept_language; + } + void set_accept_charset(const std::string& accept_charset) { + accept_charset_ = accept_charset; + } + void set_referrer_charset(const std::string& referrer_charset) { + referrer_charset_ = referrer_charset; + } + void set_cookie_policy_type(net::CookiePolicy::Type type) { + cookie_policy_.set_type(type); + } + void set_strict_transport_security_state( + net::StrictTransportSecurityState* state) { + strict_transport_security_state_ = state; + } + void set_ssl_config_service(net::SSLConfigService* service) { + ssl_config_service_ = service; + } + void set_host_resolver(net::HostResolver* resolver) { + host_resolver_ = resolver; + } + void set_http_transaction_factory(net::HttpTransactionFactory* factory) { + http_transaction_factory_ = factory; + } + void set_ftp_transaction_factory(net::FtpTransactionFactory* factory) { + ftp_transaction_factory_ = factory; + } + void set_cookie_store(net::CookieStore* cookie_store) { + cookie_store_ = cookie_store; + } + void set_proxy_service(net::ProxyService* service) { + proxy_service_ = service; + } + void set_user_script_dir_path(const FilePath& path) { + user_script_dir_path_ = path; + } + void set_is_off_the_record(bool is_off_the_record) { + is_off_the_record_ = is_off_the_record; + } + void set_is_media(bool is_media) { + is_media_ = is_media; + } + void set_extension_paths(const ExtensionPaths& paths) { + extension_paths_ = paths; + } + void set_blacklist(const Blacklist* blacklist) { + blacklist_ = blacklist; + } + void set_appcache_service(ChromeAppCacheService* service) { + appcache_service_ = service; + } // Callback for when the accept language changes. void OnAcceptLanguageChange(const std::string& accept_language); @@ -117,11 +259,7 @@ class ChromeURLRequestContext : public URLRequestContext, // Callback for when the default charset changes. void OnDefaultCharsetChange(const std::string& default_charset); - // Destructor. - virtual ~ChromeURLRequestContext(); - - NotificationRegistrar registrar_; - + protected: // Maps extension IDs to paths on disk. This is initialized in the // construtor and updated when extensions changed. ExtensionPaths extension_paths_; @@ -131,12 +269,61 @@ class ChromeURLRequestContext : public URLRequestContext, scoped_refptr<ChromeAppCacheService> appcache_service_; - PrefService* prefs_; const Blacklist* blacklist_; bool is_media_; bool is_off_the_record_; + + private: + DISALLOW_COPY_AND_ASSIGN(ChromeURLRequestContext); +}; + +// Base class for a ChromeURLRequestContext factory. This includes +// the shared functionality like extracting the default language/charset +// from a profile. +// +// Except for the constructor, all methods of this class must be called from +// the IO thread. +class ChromeURLRequestContextFactory { + public: + // Extract properties of interested from |profile|, for setting later into + // a ChromeURLRequestContext using ApplyProfileParametersToContext(). + ChromeURLRequestContextFactory(Profile* profile); + + virtual ~ChromeURLRequestContextFactory(); + + // Called to create a new instance (will only be called once). + virtual ChromeURLRequestContext* Create() = 0; + + protected: + // Assigns this factory's properties to |context|. + void ApplyProfileParametersToContext(ChromeURLRequestContext* context); + + // Values extracted from the Profile. + // + // NOTE: If you add any parameters here, keep it in sync with + // ApplyProfileParametersToContext(). + bool is_media_; + bool is_off_the_record_; + std::string accept_language_; + std::string accept_charset_; + std::string referrer_charset_; + net::CookiePolicy::Type cookie_policy_type_; + ChromeURLRequestContext::ExtensionPaths extension_paths_; + FilePath user_script_dir_path_; + Blacklist* blacklist_; + net::StrictTransportSecurityState* strict_transport_security_state_; + scoped_refptr<net::SSLConfigService> ssl_config_service_; + + FilePath profile_dir_path_; + + // Values extracted from the browser process. + MessageLoop* db_loop_; + + DISALLOW_COPY_AND_ASSIGN(ChromeURLRequestContextFactory); }; // Creates a proxy configuration using the overrides specified on the command // line. Returns NULL if the system defaults should be used instead. net::ProxyConfig* CreateProxyConfig(const CommandLine& command_line); + +#endif // CHROME_BROWSER_NET_CHROME_URL_REQUEST_CONTEXT_H_ diff --git a/chrome/browser/net/resolve_proxy_msg_helper.cc b/chrome/browser/net/resolve_proxy_msg_helper.cc index 90924d1..9859670 100644 --- a/chrome/browser/net/resolve_proxy_msg_helper.cc +++ b/chrome/browser/net/resolve_proxy_msg_helper.cc @@ -6,6 +6,7 @@ #include "base/compiler_specific.h" #include "chrome/browser/profile.h" +#include "chrome/browser/net/url_request_context_getter.h" #include "net/base/net_errors.h" #include "net/url_request/url_request_context.h" @@ -80,12 +81,13 @@ bool ResolveProxyMsgHelper::GetProxyService( } // If there is no default request context (say during shut down). - URLRequestContext* context = Profile::GetDefaultRequestContext(); - if (!context) + URLRequestContextGetter* context_getter = + Profile::GetDefaultRequestContext(); + if (!context_getter) return false; // Otherwise use the browser's global proxy service. - *out = context->proxy_service(); + *out = context_getter->GetURLRequestContext()->proxy_service(); return true; } diff --git a/chrome/browser/net/sdch_dictionary_fetcher.cc b/chrome/browser/net/sdch_dictionary_fetcher.cc index 08ed763..ed24b8b 100644 --- a/chrome/browser/net/sdch_dictionary_fetcher.cc +++ b/chrome/browser/net/sdch_dictionary_fetcher.cc @@ -39,7 +39,7 @@ void SdchDictionaryFetcher::StartFetching() { DCHECK(task_is_pending_); task_is_pending_ = false; - URLRequestContext* context = Profile::GetDefaultRequestContext(); + URLRequestContextGetter* context = Profile::GetDefaultRequestContext(); if (!context) { // Shutdown in progress. // Simulate handling of all dictionary requests by clearing queue. diff --git a/chrome/browser/net/url_fetcher.cc b/chrome/browser/net/url_fetcher.cc index 5052bb3..ca73756 100644 --- a/chrome/browser/net/url_fetcher.cc +++ b/chrome/browser/net/url_fetcher.cc @@ -9,6 +9,7 @@ #include "base/thread.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/chrome_thread.h" +#include "chrome/browser/net/url_request_context_getter.h" #include "googleurl/src/gurl.h" #include "net/base/load_flags.h" #include "net/base/io_buffer.h" @@ -71,7 +72,7 @@ class URLFetcher::Core std::string data_; // Results of the request scoped_refptr<net::IOBuffer> buffer_; // Read buffer - scoped_refptr<URLRequestContext> request_context_; + scoped_refptr<URLRequestContextGetter> request_context_getter_; // Cookie/cache info for the request ResponseCookies cookies_; // Response cookies std::string extra_request_headers_;// Extra headers for the request, if any @@ -138,7 +139,7 @@ URLFetcher::Core::Core(URLFetcher* fetcher, void URLFetcher::Core::Start() { DCHECK(delegate_loop_); DCHECK(io_loop_); - DCHECK(request_context_) << "We need an URLRequestContext!"; + DCHECK(request_context_getter_) << "We need an URLRequestContextGetter!"; io_loop_->PostDelayedTask(FROM_HERE, NewRunnableMethod( this, &Core::StartURLRequest), protect_entry_->UpdateBackoff(URLFetcherProtectEntry::SEND)); @@ -203,7 +204,7 @@ void URLFetcher::Core::StartURLRequest() { flags = flags | net::LOAD_DISABLE_INTERCEPT; } request_->set_load_flags(flags); - request_->set_context(request_context_.get()); + request_->set_context(request_context_getter_->GetURLRequestContext()); switch (request_type_) { case GET: @@ -247,7 +248,7 @@ void URLFetcher::Core::CancelURLRequest() { // references to URLFetcher::Core at this point so it may take a while to // delete the object, but we cannot delay the destruction of the request // context. - request_context_ = NULL; + request_context_getter_ = NULL; } void URLFetcher::Core::OnCompletedURLRequest(const URLRequestStatus& status) { @@ -301,8 +302,9 @@ void URLFetcher::set_extra_request_headers( core_->extra_request_headers_ = extra_request_headers; } -void URLFetcher::set_request_context(URLRequestContext* request_context) { - core_->request_context_ = request_context; +void URLFetcher::set_request_context( + URLRequestContextGetter* request_context_getter) { + core_->request_context_getter_ = request_context_getter; } net::HttpResponseHeaders* URLFetcher::response_headers() const { diff --git a/chrome/browser/net/url_fetcher.h b/chrome/browser/net/url_fetcher.h index b7aa137..d62536c 100644 --- a/chrome/browser/net/url_fetcher.h +++ b/chrome/browser/net/url_fetcher.h @@ -18,7 +18,7 @@ class GURL; typedef std::vector<std::string> ResponseCookies; class URLFetcher; -class URLRequestContext; +class URLRequestContextGetter; class URLRequestStatus; namespace net { @@ -143,7 +143,7 @@ class URLFetcher { // Set the URLRequestContext on the request. Must be called before the // request is started. - void set_request_context(URLRequestContext* request_context); + void set_request_context(URLRequestContextGetter* request_context_getter); // Retrieve the response headers from the request. Must only be called after // the OnURLFetchComplete callback has run. diff --git a/chrome/browser/net/url_fetcher_unittest.cc b/chrome/browser/net/url_fetcher_unittest.cc index 91deec0..f8537d9 100644 --- a/chrome/browser/net/url_fetcher_unittest.cc +++ b/chrome/browser/net/url_fetcher_unittest.cc @@ -7,6 +7,7 @@ #include "base/timer.h" #include "chrome/browser/net/url_fetcher.h" #include "chrome/browser/net/url_fetcher_protect.h" +#include "chrome/browser/net/url_request_context_getter.h" #include "chrome/common/chrome_plugin_lib.h" #include "net/http/http_response_headers.h" #include "net/socket/ssl_test_util.h" @@ -20,6 +21,17 @@ namespace { const wchar_t kDocRoot[] = L"chrome/test/data"; +class TestURLRequestContextGetter : public URLRequestContextGetter { + public: + virtual URLRequestContext* GetURLRequestContext() { + if (!context_) + context_ = new TestURLRequestContext(); + return context_; + } + private: + scoped_refptr<URLRequestContext> context_; +}; + class URLFetcherTest : public testing::Test, public URLFetcher::Delegate { public: URLFetcherTest() : fetcher_(NULL) { } @@ -147,6 +159,23 @@ class CancelTestURLRequestContext : public TestURLRequestContext { bool* destructor_called_; }; +class CancelTestURLRequestContextGetter : public URLRequestContextGetter { + public: + CancelTestURLRequestContextGetter(bool* destructor_called) + : destructor_called_(destructor_called) { + } + + virtual URLRequestContext* GetURLRequestContext() { + if (!context_) + context_ = new CancelTestURLRequestContext(destructor_called_); + return context_; + } + + private: + scoped_refptr<URLRequestContext> context_; + bool* destructor_called_; +}; + // Wrapper that lets us call CreateFetcher() on a thread of our choice. We // could make URLFetcherTest refcounted and use PostTask(FROM_HERE.. ) to call // CreateFetcher() directly, but the ownership of the URLFetcherTest is a bit @@ -167,7 +196,7 @@ class FetcherWrapperTask : public Task { void URLFetcherTest::CreateFetcher(const GURL& url) { fetcher_ = new URLFetcher(url, URLFetcher::GET, this); - fetcher_->set_request_context(new TestURLRequestContext()); + fetcher_->set_request_context(new TestURLRequestContextGetter()); fetcher_->set_io_loop(&io_loop_); fetcher_->Start(); } @@ -193,7 +222,7 @@ void URLFetcherTest::OnURLFetchComplete(const URLFetcher* source, void URLFetcherPostTest::CreateFetcher(const GURL& url) { fetcher_ = new URLFetcher(url, URLFetcher::POST, this); - fetcher_->set_request_context(new TestURLRequestContext()); + fetcher_->set_request_context(new TestURLRequestContextGetter()); fetcher_->set_io_loop(&io_loop_); fetcher_->set_upload_data("application/x-www-form-urlencoded", "bobsyeruncle"); @@ -228,7 +257,7 @@ void URLFetcherHeadersTest::OnURLFetchComplete( void URLFetcherProtectTest::CreateFetcher(const GURL& url) { fetcher_ = new URLFetcher(url, URLFetcher::GET, this); - fetcher_->set_request_context(new TestURLRequestContext()); + fetcher_->set_request_context(new TestURLRequestContextGetter()); fetcher_->set_io_loop(&io_loop_); start_time_ = Time::Now(); fetcher_->Start(); @@ -300,7 +329,7 @@ void URLFetcherBadHTTPSTest::OnURLFetchComplete( void URLFetcherCancelTest::CreateFetcher(const GURL& url) { fetcher_ = new URLFetcher(url, URLFetcher::GET, this); fetcher_->set_request_context( - new CancelTestURLRequestContext(&context_released_)); + new CancelTestURLRequestContextGetter(&context_released_)); fetcher_->set_io_loop(&io_loop_); fetcher_->Start(); // Make sure we give the IO thread a chance to run. diff --git a/chrome/browser/net/url_request_context_getter.cc b/chrome/browser/net/url_request_context_getter.cc new file mode 100644 index 0000000..23f9226 --- /dev/null +++ b/chrome/browser/net/url_request_context_getter.cc @@ -0,0 +1,10 @@ +// Copyright (c) 2009 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/net/url_request_context_getter.h" +#include "net/url_request/url_request_context.h" + +net::CookieStore* URLRequestContextGetter::GetCookieStore() { + return GetURLRequestContext()->cookie_store(); +} diff --git a/chrome/browser/net/url_request_context_getter.h b/chrome/browser/net/url_request_context_getter.h new file mode 100644 index 0000000..b5c8070 --- /dev/null +++ b/chrome/browser/net/url_request_context_getter.h @@ -0,0 +1,30 @@ +// Copyright (c) 2009 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_NET_URL_REQUEST_CONTEXT_GETTER_H_ +#define CHROME_BROWSER_NET_URL_REQUEST_CONTEXT_GETTER_H_ + +#include "base/ref_counted.h" + +namespace net { +class CookieStore; +} + +class URLRequestContext; + +// Interface for retrieving an URLRequestContext. +class URLRequestContextGetter + : public base::RefCountedThreadSafe<URLRequestContextGetter> { + public: + virtual ~URLRequestContextGetter() {} + + virtual URLRequestContext* GetURLRequestContext() = 0; + + // Defaults to GetURLRequestContext()->cookie_store(), but + // implementations can override it. + virtual net::CookieStore* GetCookieStore(); +}; + +#endif // CHROME_BROWSER_NET_URL_REQUEST_CONTEXT_GETTER_H_ + |