diff options
Diffstat (limited to 'chrome/browser')
43 files changed, 1229 insertions, 499 deletions
diff --git a/chrome/browser/automation/automation_profile_impl.cc b/chrome/browser/automation/automation_profile_impl.cc index 8d6118b..d1f0750 100644 --- a/chrome/browser/automation/automation_profile_impl.cc +++ b/chrome/browser/automation/automation_profile_impl.cc @@ -6,20 +6,24 @@ #include "chrome/browser/net/chrome_url_request_context.h" #include "chrome/test/automation/automation_messages.h" +namespace { + // A special Request context for automation. Substitute a few things // like cookie store, proxy settings etc to handle them differently // for automation. class AutomationURLRequestContext : public ChromeURLRequestContext { public: - AutomationURLRequestContext(URLRequestContext* original_context, + AutomationURLRequestContext(ChromeURLRequestContext* original_context, net::CookieStore* automation_cookie_store) - // All URLRequestContexts in chrome extend from ChromeURLRequestContext - : ChromeURLRequestContext(static_cast<ChromeURLRequestContext*>( - original_context)) { + : ChromeURLRequestContext(original_context), + // We must hold a reference to |original_context|, since many + // of the dependencies that ChromeURLRequestContext(original_context) + // copied are scoped to |original_context|. + original_context_(original_context) { cookie_store_ = automation_cookie_store; } - ~AutomationURLRequestContext() { + virtual ~AutomationURLRequestContext() { // Clear out members before calling base class dtor since we don't // own any of them. @@ -32,11 +36,11 @@ class AutomationURLRequestContext : public ChromeURLRequestContext { strict_transport_security_state_ = NULL; // Clear ChromeURLRequestContext members. - prefs_ = NULL; blacklist_ = NULL; } private: + scoped_refptr<ChromeURLRequestContext> original_context_; DISALLOW_COPY_AND_ASSIGN(AutomationURLRequestContext); }; @@ -56,6 +60,8 @@ class AutomationCookieStore : public net::CookieStore { virtual bool SetCookie(const GURL& url, const std::string& cookie_line) { bool cookie_set = original_cookie_store_->SetCookie(url, cookie_line); if (cookie_set) { + // TODO(eroman): Should NOT be accessing the profile from here, as this + // is running on the IO thread. automation_client_->Send(new AutomationMsg_SetCookieAsync(0, profile_->tab_handle(), url, cookie_line)); } @@ -107,18 +113,63 @@ class AutomationCookieStore : public net::CookieStore { DISALLOW_COPY_AND_ASSIGN(AutomationCookieStore); }; +class Factory : public ChromeURLRequestContextFactory { + public: + Factory(ChromeURLRequestContextGetter* original_context_getter, + AutomationProfileImpl* profile, + IPC::Message::Sender* automation_client) + : ChromeURLRequestContextFactory(profile), + original_context_getter_(original_context_getter), + profile_(profile), + automation_client_(automation_client) { + } + + virtual ChromeURLRequestContext* Create() { + ChromeURLRequestContext* original_context = + original_context_getter_->GetIOContext(); + + // Create an automation cookie store. + scoped_refptr<net::CookieStore> automation_cookie_store = + new AutomationCookieStore(profile_, + original_context->cookie_store(), + automation_client_); + + return new AutomationURLRequestContext(original_context, + automation_cookie_store); + } + + private: + scoped_refptr<ChromeURLRequestContextGetter> original_context_getter_; + AutomationProfileImpl* profile_; + IPC::Message::Sender* automation_client_; +}; + +// TODO(eroman): This duplicates CleanupRequestContext() from profile.cc. +void CleanupRequestContext(ChromeURLRequestContextGetter* context) { + context->CleanupOnUIThread(); + + // Clean up request context on IO thread. + g_browser_process->io_thread()->message_loop()->ReleaseSoon(FROM_HERE, + context); +} + +} // namespace + +AutomationProfileImpl::~AutomationProfileImpl() { + CleanupRequestContext(alternate_request_context_); +} + void AutomationProfileImpl::Initialize(Profile* original_profile, IPC::Message::Sender* automation_client) { DCHECK(original_profile); original_profile_ = original_profile; - URLRequestContext* original_context = original_profile_->GetRequestContext(); - scoped_refptr<net::CookieStore> original_cookie_store = - original_context->cookie_store(); - alternate_cookie_store_ = new AutomationCookieStore(this, - original_cookie_store, - automation_client); - alternate_reqeust_context_ = new AutomationURLRequestContext( - original_context, alternate_cookie_store_.get()); + ChromeURLRequestContextGetter* original_context = + static_cast<ChromeURLRequestContextGetter*>( + original_profile_->GetRequestContext()); + alternate_request_context_ = new ChromeURLRequestContextGetter( + NULL, // Don't register an observer on PrefService. + new Factory(original_context, this, automation_client)); + alternate_request_context_->AddRef(); // Balananced in the destructor. } diff --git a/chrome/browser/automation/automation_profile_impl.h b/chrome/browser/automation/automation_profile_impl.h index e4d9ac6..c893aa1 100644 --- a/chrome/browser/automation/automation_profile_impl.h +++ b/chrome/browser/automation/automation_profile_impl.h @@ -5,6 +5,7 @@ #ifndef CHROME_BROWSER_AUTOMATION_AUTOMATION_PROFILE_IMPL_H_ #define CHROME_BROWSER_AUTOMATION_AUTOMATION_PROFILE_IMPL_H_ +#include "chrome/browser/net/chrome_url_request_context.h" #include "chrome/browser/profile.h" #include "net/url_request/url_request_context.h" @@ -19,6 +20,8 @@ class AutomationProfileImpl : public Profile { tab_handle_(0) { } + virtual ~AutomationProfileImpl(); + void Initialize(Profile* original_profile, IPC::Message::Sender* automation_client); @@ -48,9 +51,6 @@ class AutomationProfileImpl : public Profile { virtual Profile* GetOriginalProfile() { return original_profile_->GetOriginalProfile(); } - virtual ChromeAppCacheService* GetAppCacheService() { - return original_profile_->GetAppCacheService(); - } virtual VisitedLinkMaster* GetVisitedLinkMaster() { return original_profile_->GetVisitedLinkMaster(); } @@ -126,13 +126,13 @@ class AutomationProfileImpl : public Profile { virtual ThumbnailStore* GetThumbnailStore() { return original_profile_->GetThumbnailStore(); } - virtual URLRequestContext* GetRequestContext() { - return alternate_reqeust_context_; + virtual URLRequestContextGetter* GetRequestContext() { + return alternate_request_context_; } - virtual URLRequestContext* GetRequestContextForMedia() { + virtual URLRequestContextGetter* GetRequestContextForMedia() { return original_profile_->GetRequestContextForMedia(); } - virtual URLRequestContext* GetRequestContextForExtensions() { + virtual URLRequestContextGetter* GetRequestContextForExtensions() { return original_profile_->GetRequestContextForExtensions(); } virtual net::SSLConfigService* GetSSLConfigService() { @@ -214,8 +214,7 @@ class AutomationProfileImpl : public Profile { protected: Profile* original_profile_; - scoped_refptr<net::CookieStore> alternate_cookie_store_; - scoped_refptr<URLRequestContext> alternate_reqeust_context_; + ChromeURLRequestContextGetter* alternate_request_context_; int tab_handle_; private: diff --git a/chrome/browser/automation/automation_provider.cc b/chrome/browser/automation/automation_provider.cc index 2194fe6e..891b6b7 100644 --- a/chrome/browser/automation/automation_provider.cc +++ b/chrome/browser/automation/automation_provider.cc @@ -40,6 +40,7 @@ #include "chrome/browser/find_notification_details.h" #include "chrome/browser/location_bar.h" #include "chrome/browser/login_prompt.h" +#include "chrome/browser/net/url_request_context_getter.h" #include "chrome/browser/net/url_request_mock_util.h" #include "chrome/browser/profile_manager.h" #include "chrome/browser/renderer_host/render_process_host.h" @@ -975,8 +976,12 @@ void AutomationProvider::GetCookies(const GURL& url, int handle, *value_size = -1; if (url.is_valid() && tab_tracker_->ContainsHandle(handle)) { NavigationController* tab = tab_tracker_->GetResource(handle); - *value = - tab->profile()->GetRequestContext()->cookie_store()->GetCookies(url); + + // Since we are running on the UI thread don't call GetURLRequestContext(). + net::CookieStore* cookie_store = + tab->profile()->GetRequestContext()->GetCookieStore(); + + *value = cookie_store->GetCookies(url); *value_size = static_cast<int>(value->size()); } } @@ -989,8 +994,12 @@ void AutomationProvider::SetCookie(const GURL& url, if (url.is_valid() && tab_tracker_->ContainsHandle(handle)) { NavigationController* tab = tab_tracker_->GetResource(handle); - URLRequestContext* context = tab->profile()->GetRequestContext(); - if (context->cookie_store()->SetCookie(url, value)) + + // Since we are running on the UI thread don't call GetURLRequestContext(). + scoped_refptr<net::CookieStore> cookie_store = + tab->profile()->GetRequestContext()->GetCookieStore(); + + if (cookie_store->SetCookie(url, value)) *response_value = 1; } } @@ -1181,9 +1190,9 @@ void AutomationProvider::ReceivedInspectElementResponse(int num_resources) { class SetProxyConfigTask : public Task { public: - explicit SetProxyConfigTask(net::ProxyService* proxy_service, - const std::string& new_proxy_config) - : proxy_service_(proxy_service), proxy_config_(new_proxy_config) {} + SetProxyConfigTask(URLRequestContextGetter* request_context_getter, + const std::string& new_proxy_config) + : request_context_getter_(request_context_getter), proxy_config_(new_proxy_config) {} virtual void Run() { // First, deserialize the JSON string. If this fails, log and bail. JSONStringValueSerializer deserializer(proxy_config_); @@ -1201,10 +1210,12 @@ class SetProxyConfigTask : public Task { net::ProxyConfig pc; PopulateProxyConfig(*dict.get(), &pc); - DCHECK(proxy_service_); + net::ProxyService* proxy_service = + request_context_getter_->GetURLRequestContext()->proxy_service(); + DCHECK(proxy_service); scoped_ptr<net::ProxyConfigService> proxy_config_service( new net::ProxyConfigServiceFixed(pc)); - proxy_service_->ResetConfigService(proxy_config_service.release()); + proxy_service->ResetConfigService(proxy_config_service.release()); } void PopulateProxyConfig(const DictionaryValue& dict, net::ProxyConfig* pc) { @@ -1233,29 +1244,26 @@ class SetProxyConfigTask : public Task { } private: - net::ProxyService* proxy_service_; + scoped_refptr<URLRequestContextGetter> request_context_getter_; std::string proxy_config_; }; void AutomationProvider::SetProxyConfig(const std::string& new_proxy_config) { - URLRequestContext* context = Profile::GetDefaultRequestContext(); - if (!context) { + URLRequestContextGetter* context_getter = Profile::GetDefaultRequestContext(); + if (!context_getter) { FilePath user_data_dir; PathService::Get(chrome::DIR_USER_DATA, &user_data_dir); ProfileManager* profile_manager = g_browser_process->profile_manager(); DCHECK(profile_manager); Profile* profile = profile_manager->GetDefaultProfile(user_data_dir); DCHECK(profile); - context = profile->GetRequestContext(); + context_getter = profile->GetRequestContext(); } - DCHECK(context); - // Every URLRequestContext should have a proxy service. - net::ProxyService* proxy_service = context->proxy_service(); - DCHECK(proxy_service); + DCHECK(context_getter); g_browser_process->io_thread()->message_loop()->PostTask(FROM_HERE, - new SetProxyConfigTask(proxy_service, new_proxy_config)); + new SetProxyConfigTask(context_getter, new_proxy_config)); } void AutomationProvider::GetDownloadDirectory( diff --git a/chrome/browser/browsing_data_remover.cc b/chrome/browser/browsing_data_remover.cc index e6e2071..c23d5b6 100644 --- a/chrome/browser/browsing_data_remover.cc +++ b/chrome/browser/browsing_data_remover.cc @@ -10,6 +10,7 @@ #include "chrome/browser/history/history.h" #include "chrome/browser/profile.h" #include "chrome/browser/metrics/user_metrics.h" +#include "chrome/browser/net/url_request_context_getter.h" #include "chrome/browser/password_manager/password_store.h" #include "chrome/browser/search_engines/template_url_model.h" #include "chrome/browser/sessions/session_service.h" @@ -106,8 +107,9 @@ void BrowsingDataRemover::Remove(int remove_mask) { if (remove_mask & REMOVE_COOKIES) { UserMetrics::RecordAction(L"ClearBrowsingData_Cookies", profile_); + // Since we are running on the UI thread don't call GetURLRequestContext(). net::CookieMonster* cookie_monster = - profile_->GetRequestContext()->cookie_store()->GetCookieMonster(); + profile_->GetRequestContext()->GetCookieStore()->GetCookieMonster(); if (cookie_monster) cookie_monster->DeleteAllCreatedBetween(delete_begin_, delete_end_, true); } @@ -138,6 +140,7 @@ void BrowsingDataRemover::Remove(int remove_mask) { thread->message_loop()->PostTask(FROM_HERE, NewRunnableMethod( this, &BrowsingDataRemover::ClearCacheOnIOThread, + profile_->GetRequestContext(), delete_begin_, delete_end_, MessageLoop::current())); @@ -218,16 +221,18 @@ void BrowsingDataRemover::ClearedCache() { NotifyAndDeleteIfDone(); } -void BrowsingDataRemover::ClearCacheOnIOThread(base::Time delete_begin, - base::Time delete_end, - MessageLoop* ui_loop) { +void BrowsingDataRemover::ClearCacheOnIOThread( + URLRequestContextGetter* context_getter, + base::Time delete_begin, + base::Time delete_end, + MessageLoop* ui_loop) { // This function should be called on the IO thread. DCHECK(MessageLoop::current() == ChromeThread::GetMessageLoop(ChromeThread::IO)); // Get a pointer to the cache. net::HttpTransactionFactory* factory = - profile_->GetRequestContext()->http_transaction_factory(); + context_getter->GetURLRequestContext()->http_transaction_factory(); disk_cache::Backend* cache = factory->GetCache()->disk_cache(); // |cache| can be null since it is lazily initialized, in this case we do @@ -240,7 +245,8 @@ void BrowsingDataRemover::ClearCacheOnIOThread(base::Time delete_begin, } // Get a pointer to the media cache. - factory = profile_->GetRequestContextForMedia()->http_transaction_factory(); + factory = profile_->GetRequestContextForMedia()->GetURLRequestContext()-> + http_transaction_factory(); cache = factory->GetCache()->disk_cache(); // |cache| can be null since it is lazily initialized, in this case we do diff --git a/chrome/browser/browsing_data_remover.h b/chrome/browser/browsing_data_remover.h index 1e5054c..27527b8 100644 --- a/chrome/browser/browsing_data_remover.h +++ b/chrome/browser/browsing_data_remover.h @@ -12,6 +12,7 @@ class MessageLoop; class Profile; +class URLRequestContextGetter; // BrowsingDataRemover is responsible for removing data related to browsing: // visits in url database, downloads, cookies ... @@ -86,7 +87,8 @@ class BrowsingDataRemover : public NotificationObserver { void ClearedCache(); // Invoked on the IO thread to delete from the cache. - void ClearCacheOnIOThread(base::Time delete_begin, + void ClearCacheOnIOThread(URLRequestContextGetter* context_getter, + base::Time delete_begin, base::Time delete_end, MessageLoop* ui_loop); diff --git a/chrome/browser/chrome_plugin_host.cc b/chrome/browser/chrome_plugin_host.cc index 026eaa1..5f13109 100644 --- a/chrome/browser/chrome_plugin_host.cc +++ b/chrome/browser/chrome_plugin_host.cc @@ -21,6 +21,7 @@ #include "chrome/browser/chrome_thread.h" #include "chrome/browser/dom_ui/html_dialog_ui.h" #include "chrome/browser/gears_integration.h" +#include "chrome/browser/net/url_request_context_getter.h" #include "chrome/browser/plugin_process_host.h" #include "chrome/browser/plugin_service.h" #include "chrome/browser/profile.h" @@ -157,7 +158,7 @@ class PluginRequestHandler : public PluginHelper, public URLRequest::Delegate { ToURLRequestContext(cprequest_->context); // TODO(mpcomplete): remove fallback case when Gears support is prevalent. if (!context) - context = Profile::GetDefaultRequestContext(); + context = Profile::GetDefaultRequestContext()->GetURLRequestContext(); GURL gurl(cprequest_->url); request_.reset(new URLRequest(gurl, this)); @@ -389,7 +390,7 @@ CPError STDCALL CPB_GetCookies(CPID id, CPBrowsingContext bcontext, ToURLRequestContext(bcontext); // TODO(mpcomplete): remove fallback case when Gears support is prevalent. if (!context) { - context = Profile::GetDefaultRequestContext(); + context = Profile::GetDefaultRequestContext()->GetURLRequestContext(); if (!context) return CPERR_FAILURE; } diff --git a/chrome/browser/cookies_table_model.cc b/chrome/browser/cookies_table_model.cc index 3f85819..3cc140f 100644 --- a/chrome/browser/cookies_table_model.cc +++ b/chrome/browser/cookies_table_model.cc @@ -8,6 +8,7 @@ #include "app/table_model_observer.h" #include "app/resource_bundle.h" #include "base/string_util.h" +#include "chrome/browser/net/chrome_url_request_context.h" #include "chrome/browser/profile.h" #include "grit/generated_resources.h" #include "grit/theme_resources.h" @@ -38,9 +39,9 @@ void CookiesTableModel::RemoveCookies(int start_index, int remove_count) { NOTREACHED(); return; } - + // Since we are running on the UI thread don't call GetURLRequestContext(). net::CookieMonster* monster = - profile_->GetRequestContext()->cookie_store()->GetCookieMonster(); + profile_->GetRequestContext()->GetCookieStore()->GetCookieMonster(); // We need to update the searched results list, the full cookie list, // and the view. We walk through the search results list (which is what @@ -158,8 +159,11 @@ static bool ContainsFilterText( void CookiesTableModel::LoadCookies() { // mmargh mmargh mmargh! + + // Since we are running on the UI thread don't call GetURLRequestContext(). net::CookieMonster* cookie_monster = - profile_->GetRequestContext()->cookie_store()->GetCookieMonster(); + profile_->GetRequestContext()->GetCookieStore()->GetCookieMonster(); + all_cookies_ = cookie_monster->GetAllCookies(); DoFilter(); } diff --git a/chrome/browser/dom_ui/new_tab_page_sync_handler.cc b/chrome/browser/dom_ui/new_tab_page_sync_handler.cc index 7a24310..b4db8b3 100644 --- a/chrome/browser/dom_ui/new_tab_page_sync_handler.cc +++ b/chrome/browser/dom_ui/new_tab_page_sync_handler.cc @@ -10,6 +10,7 @@ #include "base/json_writer.h" #include "base/string_util.h" #include "base/values.h" +#include "chrome/browser/net/chrome_url_request_context.h" #include "chrome/browser/profile.h" #include "chrome/browser/renderer_host/render_view_host.h" #include "chrome/browser/tab_contents/tab_contents.h" @@ -51,8 +52,9 @@ static const GoogleCookieFilter kGAIACookieFilters[] = { bool IsGoogleGAIACookieInstalled() { for (size_t i = 0; i < arraysize(kGAIACookieFilters); ++i) { - URLRequestContext* context = Profile::GetDefaultRequestContext(); - net::CookieStore* store = context->cookie_store(); + // Since we are running on the UI thread don't call GetURLRequestContext(). + net::CookieStore* store = + Profile::GetDefaultRequestContext()->GetCookieStore(); GURL url(kGAIACookieFilters[i].url); net::CookieOptions options; options.set_include_httponly(); // The SID cookie might be httponly. diff --git a/chrome/browser/download/download_file.cc b/chrome/browser/download/download_file.cc index b340d00..6bb0866 100644 --- a/chrome/browser/download/download_file.cc +++ b/chrome/browser/download/download_file.cc @@ -13,6 +13,7 @@ #include "build/build_config.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/download/download_manager.h" +#include "chrome/browser/net/chrome_url_request_context.h" #include "chrome/browser/profile.h" #include "chrome/browser/renderer_host/resource_dispatcher_host.h" #include "chrome/browser/tab_contents/tab_util.h" @@ -423,11 +424,13 @@ void DownloadFileManager::OnDownloadFinished(int id, RemoveDownloadFromUIProgress(id); } -void DownloadFileManager::DownloadUrl(const GURL& url, - const GURL& referrer, - int render_process_host_id, - int render_view_id, - URLRequestContext* request_context) { +void DownloadFileManager::DownloadUrl( + const GURL& url, + const GURL& referrer, + const std::string& referrer_charset, + int render_process_host_id, + int render_view_id, + URLRequestContextGetter* request_context_getter) { DCHECK(MessageLoop::current() == ui_loop_); base::Thread* thread = g_browser_process->io_thread(); if (thread) { @@ -436,9 +439,10 @@ void DownloadFileManager::DownloadUrl(const GURL& url, &DownloadFileManager::OnDownloadUrl, url, referrer, + referrer_charset, render_process_host_id, render_view_id, - request_context)); + request_context_getter)); } } @@ -517,17 +521,23 @@ void DownloadFileManager::RemoveDownloadManager(DownloadManager* manager) { // Notifications from the UI thread and run on the IO thread // Initiate a request for URL to be downloaded. -void DownloadFileManager::OnDownloadUrl(const GURL& url, - const GURL& referrer, - int render_process_host_id, - int render_view_id, - URLRequestContext* request_context) { +void DownloadFileManager::OnDownloadUrl( + const GURL& url, + const GURL& referrer, + const std::string& referrer_charset, + int render_process_host_id, + int render_view_id, + URLRequestContextGetter* request_context_getter) { DCHECK(MessageLoop::current() == io_loop_); + + URLRequestContext* context = request_context_getter->GetURLRequestContext(); + context->set_referrer_charset(referrer_charset); + resource_dispatcher_host_->BeginDownload(url, referrer, render_process_host_id, render_view_id, - request_context); + context); } // Actions from the UI thread and run on the download thread diff --git a/chrome/browser/download/download_file.h b/chrome/browser/download/download_file.h index 66d3e7c..2e24a17 100644 --- a/chrome/browser/download/download_file.h +++ b/chrome/browser/download/download_file.h @@ -42,6 +42,7 @@ #define CHROME_BROWSER_DOWNLOAD_DOWNLOAD_FILE_H_ #include <map> +#include <string> #include <vector> #include "app/gfx/native_widget_types.h" @@ -61,7 +62,7 @@ struct DownloadCreateInfo; class DownloadManager; class MessageLoop; class ResourceDispatcherHost; -class URLRequestContext; +class URLRequestContextGetter; // DownloadBuffer -------------------------------------------------------------- @@ -193,16 +194,18 @@ class DownloadFileManager // ResourceDispatcherHost on the IO thread. void DownloadUrl(const GURL& url, const GURL& referrer, + const std::string& referrer_charset, int render_process_host_id, int render_view_id, - URLRequestContext* request_context); + URLRequestContextGetter* request_context_getter); // Run on the IO thread to initiate the download of a URL. void OnDownloadUrl(const GURL& url, const GURL& referrer, + const std::string& referrer_charset, int render_process_host_id, int render_view_id, - URLRequestContext* request_context); + URLRequestContextGetter* request_context_getter); // Called on the UI thread to remove a download item or manager. void RemoveDownloadManager(DownloadManager* manager); diff --git a/chrome/browser/download/download_manager.cc b/chrome/browser/download/download_manager.cc index fb68114..f412e33 100644 --- a/chrome/browser/download/download_manager.cc +++ b/chrome/browser/download/download_manager.cc @@ -23,6 +23,7 @@ #include "chrome/browser/extensions/crx_installer.h" #include "chrome/browser/extensions/extension_install_ui.h" #include "chrome/browser/extensions/extensions_service.h" +#include "chrome/browser/net/chrome_url_request_context.h" #include "chrome/browser/profile.h" #include "chrome/browser/renderer_host/render_process_host.h" #include "chrome/browser/renderer_host/render_view_host.h" @@ -475,7 +476,7 @@ bool DownloadManager::Init(Profile* profile) { shutdown_needed_ = true; profile_ = profile; - request_context_ = profile_->GetRequestContext(); + request_context_getter_ = profile_->GetRequestContext(); // 'incognito mode' will have access to past downloads, but we won't store // information about new downloads while in that mode. @@ -1119,12 +1120,12 @@ void DownloadManager::DownloadUrl(const GURL& url, const std::string& referrer_charset, TabContents* tab_contents) { DCHECK(tab_contents); - request_context_->set_referrer_charset(referrer_charset); file_manager_->DownloadUrl(url, referrer, + referrer_charset, tab_contents->process()->id(), tab_contents->render_view_host()->routing_id(), - request_context_.get()); + request_context_getter_); } void DownloadManager::GenerateExtension( diff --git a/chrome/browser/download/download_manager.h b/chrome/browser/download/download_manager.h index f2fea6e..b2d6b3c 100644 --- a/chrome/browser/download/download_manager.h +++ b/chrome/browser/download/download_manager.h @@ -63,7 +63,7 @@ class MessageLoop; class PrefService; class Profile; class ResourceDispatcherHost; -class URLRequestContext; +class URLRequestContextGetter; class TabContents; namespace base { @@ -585,7 +585,7 @@ class DownloadManager : public base::RefCountedThreadSafe<DownloadManager>, // The current active profile. Profile* profile_; - scoped_refptr<URLRequestContext> request_context_; + scoped_refptr<URLRequestContextGetter> request_context_getter_; // Used for history service request management. CancelableRequestConsumerTSimple<Observer*> cancelable_consumer_; diff --git a/chrome/browser/download/save_file_manager.cc b/chrome/browser/download/save_file_manager.cc index 063c6b1..3289799 100644 --- a/chrome/browser/download/save_file_manager.cc +++ b/chrome/browser/download/save_file_manager.cc @@ -15,6 +15,7 @@ #include "chrome/browser/browser_process.h" #include "chrome/browser/download/save_file.h" #include "chrome/browser/download/save_package.h" +#include "chrome/browser/net/url_request_context_getter.h" #include "chrome/browser/renderer_host/resource_dispatcher_host.h" #include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/browser/tab_contents/tab_util.h" @@ -153,7 +154,7 @@ void SaveFileManager::SaveURL(const GURL& url, int render_view_id, SaveFileCreateInfo::SaveFileSource save_source, const FilePath& file_full_path, - URLRequestContext* request_context, + URLRequestContextGetter* request_context_getter, SavePackage* save_package) { DCHECK_EQ(MessageLoop::current(), ui_loop_); if (!io_loop_) { @@ -173,7 +174,7 @@ void SaveFileManager::SaveURL(const GURL& url, referrer, render_process_host_id, render_view_id, - request_context)); + request_context_getter)); } else { // We manually start the save job. SaveFileCreateInfo* info = new SaveFileCreateInfo(file_full_path, @@ -393,17 +394,19 @@ void SaveFileManager::OnCancelSaveRequest(int render_process_id, // Notifications sent from the UI thread and run on the IO thread. -void SaveFileManager::OnSaveURL(const GURL& url, - const GURL& referrer, - int render_process_host_id, - int render_view_id, - URLRequestContext* request_context) { +void SaveFileManager::OnSaveURL( + const GURL& url, + const GURL& referrer, + int render_process_host_id, + int render_view_id, + URLRequestContextGetter* request_context_getter) { DCHECK_EQ(MessageLoop::current(), io_loop_); + URLRequestContext* context = request_context_getter->GetURLRequestContext(); resource_dispatcher_host_->BeginSaveFile(url, referrer, render_process_host_id, render_view_id, - request_context); + context); } void SaveFileManager::OnRequireSaveJobFromOtherSource( diff --git a/chrome/browser/download/save_file_manager.h b/chrome/browser/download/save_file_manager.h index f85fee7..5f3d564 100644 --- a/chrome/browser/download/save_file_manager.h +++ b/chrome/browser/download/save_file_manager.h @@ -75,7 +75,7 @@ class SavePackage; class MessageLoop; class ResourceDispatcherHost; class Task; -class URLRequestContext; +class URLRequestContextGetter; class SaveFileManager : public base::RefCountedThreadSafe<SaveFileManager> { @@ -99,7 +99,7 @@ class SaveFileManager int render_view_id, SaveFileCreateInfo::SaveFileSource save_source, const FilePath& file_full_path, - URLRequestContext* request_context, + URLRequestContextGetter* request_context_getter, SavePackage* save_package); // Notifications sent from the IO thread and run on the file thread: @@ -218,7 +218,7 @@ class SaveFileManager const GURL& referrer, int render_process_host_id, int render_view_id, - URLRequestContext* request_context); + URLRequestContextGetter* request_context_getter); // Handler for a notification sent to the IO thread for generating save id. void OnRequireSaveJobFromOtherSource(SaveFileCreateInfo* info); // Call ResourceDispatcherHost's CancelRequest method to execute cancel diff --git a/chrome/browser/download/save_package.cc b/chrome/browser/download/save_package.cc index 97487c0..20cb15b 100644 --- a/chrome/browser/download/save_package.cc +++ b/chrome/browser/download/save_package.cc @@ -20,6 +20,7 @@ #include "chrome/browser/download/save_file.h" #include "chrome/browser/download/save_file_manager.h" #include "chrome/browser/download/save_item.h" +#include "chrome/browser/net/url_request_context_getter.h" #include "chrome/browser/profile.h" #include "chrome/browser/renderer_host/render_process_host.h" #include "chrome/browser/renderer_host/render_view_host.h" @@ -295,7 +296,7 @@ bool SavePackage::Init() { return false; } - request_context_ = profile->GetRequestContext(); + request_context_getter_ = profile->GetRequestContext(); // Create the fake DownloadItem and display the view. download_ = new DownloadItem(1, saved_main_file_path_, 0, page_url_, GURL(), @@ -764,7 +765,7 @@ void SavePackage::SaveNextFile(bool process_all_remaining_items) { tab_contents_->render_view_host()->routing_id(), save_item->save_source(), save_item->full_path(), - request_context_.get(), + request_context_getter_.get(), this); } while (process_all_remaining_items && waiting_item_queue_.size()); } diff --git a/chrome/browser/download/save_package.h b/chrome/browser/download/save_package.h index 4e84c25..a20f027 100644 --- a/chrome/browser/download/save_package.h +++ b/chrome/browser/download/save_package.h @@ -28,7 +28,7 @@ class MessageLoop; class PrefService; class Profile; class TabContents; -class URLRequestContext; +class URLRequestContextGetter; class TabContents; namespace base { @@ -265,7 +265,7 @@ class SavePackage : public base::RefCountedThreadSafe<SavePackage>, // The request context which provides application-specific context for // URLRequest instances. - scoped_refptr<URLRequestContext> request_context_; + scoped_refptr<URLRequestContextGetter> request_context_getter_; // Non-owning pointer for handling file writing on the file thread. SaveFileManager* file_manager_; diff --git a/chrome/browser/extensions/extensions_service.cc b/chrome/browser/extensions/extensions_service.cc index 71d3a08..5b87bd1 100644 --- a/chrome/browser/extensions/extensions_service.cc +++ b/chrome/browser/extensions/extensions_service.cc @@ -326,12 +326,13 @@ void ExtensionsService::NotifyExtensionLoaded(Extension* extension) { // for the extension may try to load an extension URL with an extension id // that the request context doesn't yet know about. if (profile_ && !profile_->IsOffTheRecord()) { - ChromeURLRequestContext* context = static_cast<ChromeURLRequestContext*>( - profile_->GetRequestContext()); - if (context) { + ChromeURLRequestContextGetter* context_getter = + static_cast<ChromeURLRequestContextGetter*>( + profile_->GetRequestContext()); + if (context_getter) { g_browser_process->io_thread()->message_loop()->PostTask(FROM_HERE, - NewRunnableMethod(context, - &ChromeURLRequestContext::OnNewExtensions, + NewRunnableMethod(context_getter, + &ChromeURLRequestContextGetter::OnNewExtensions, extension->id(), extension->path())); } @@ -352,13 +353,15 @@ void ExtensionsService::NotifyExtensionUnloaded(Extension* extension) { Details<Extension>(extension)); if (profile_ && !profile_->IsOffTheRecord()) { - ChromeURLRequestContext* context = static_cast<ChromeURLRequestContext*>( - profile_->GetRequestContext()); - if (context) { + ChromeURLRequestContextGetter* context_getter = + static_cast<ChromeURLRequestContextGetter*>( + profile_->GetRequestContext()); + if (context_getter) { g_browser_process->io_thread()->message_loop()->PostTask(FROM_HERE, - NewRunnableMethod(context, - &ChromeURLRequestContext::OnUnloadedExtension, - extension->id())); + NewRunnableMethod( + context_getter, + &ChromeURLRequestContextGetter::OnUnloadedExtension, + extension->id())); } } } diff --git a/chrome/browser/gtk/options/cookies_view_unittest.cc b/chrome/browser/gtk/options/cookies_view_unittest.cc index ce0db2d..6f7240f 100644 --- a/chrome/browser/gtk/options/cookies_view_unittest.cc +++ b/chrome/browser/gtk/options/cookies_view_unittest.cc @@ -11,6 +11,7 @@ #include "base/string_util.h" #include "chrome/browser/cookies_table_model.h" +#include "chrome/browser/net/url_request_context_getter.h" #include "chrome/test/testing_profile.h" #include "net/url_request/url_request_context.h" #include "testing/gtest/include/gtest/gtest.h" @@ -24,17 +25,32 @@ class TestURLRequestContext : public URLRequestContext { } }; +class TestURLRequestContextGetter : public URLRequestContextGetter { + public: + virtual URLRequestContext* GetURLRequestContext() { + if (!context_) + context_ = new TestURLRequestContext(); + return context_; + } + private: + scoped_refptr<URLRequestContext> context_; +}; + class CookieTestingProfile : public TestingProfile { public: - virtual URLRequestContext* GetRequestContext() { - if (!url_request_context_.get()) - url_request_context_ = new TestURLRequestContext; - return url_request_context_.get(); + virtual URLRequestContextGetter* GetRequestContext() { + if (!url_request_context_getter_.get()) + url_request_context_getter_ = new TestURLRequestContextGetter; + return url_request_context_getter_.get(); } virtual ~CookieTestingProfile() {} + net::CookieMonster* GetCookieMonster() { + return GetRequestContext()->GetCookieStore()->GetCookieMonster(); + } + private: - scoped_refptr<TestURLRequestContext> url_request_context_; + scoped_refptr<URLRequestContextGetter> url_request_context_getter_; }; } // namespace @@ -112,8 +128,7 @@ TEST_F(CookiesViewTest, Empty) { } TEST_F(CookiesViewTest, RemoveAll) { - net::CookieMonster* monster = - profile_->GetRequestContext()->cookie_store()->GetCookieMonster(); + net::CookieMonster* monster = profile_->GetCookieMonster(); monster->SetCookie(GURL("http://foo"), "A=1"); monster->SetCookie(GURL("http://foo2"), "B=1"); CookiesView cookies_view(profile_.get()); @@ -146,8 +161,7 @@ TEST_F(CookiesViewTest, RemoveAll) { // OnSelectionChanged callback could get called while the gtk list view and the // CookiesTableModel were inconsistent. Test that it doesn't crash. TEST_F(CookiesViewTest, RemoveAllWithAllSelected) { - net::CookieMonster* monster = - profile_->GetRequestContext()->cookie_store()->GetCookieMonster(); + net::CookieMonster* monster = profile_->GetCookieMonster(); monster->SetCookie(GURL("http://foo"), "A=1"); monster->SetCookie(GURL("http://foo2"), "B=1"); CookiesView cookies_view(profile_.get()); @@ -175,8 +189,7 @@ TEST_F(CookiesViewTest, RemoveAllWithAllSelected) { } TEST_F(CookiesViewTest, Remove) { - net::CookieMonster* monster = - profile_->GetRequestContext()->cookie_store()->GetCookieMonster(); + net::CookieMonster* monster = profile_->GetCookieMonster(); monster->SetCookie(GURL("http://foo1"), "A=1"); monster->SetCookie(GURL("http://foo2"), "B=1"); monster->SetCookie(GURL("http://foo3"), "C=1"); @@ -242,8 +255,7 @@ TEST_F(CookiesViewTest, Remove) { } TEST_F(CookiesViewTest, RemoveMultiple) { - net::CookieMonster* monster = - profile_->GetRequestContext()->cookie_store()->GetCookieMonster(); + net::CookieMonster* monster = profile_->GetCookieMonster(); monster->SetCookie(GURL("http://foo0"), "C=1"); monster->SetCookie(GURL("http://foo1"), "D=1"); monster->SetCookie(GURL("http://foo2"), "B=1"); @@ -279,8 +291,7 @@ TEST_F(CookiesViewTest, RemoveMultiple) { } TEST_F(CookiesViewTest, RemoveDefaultSelection) { - net::CookieMonster* monster = - profile_->GetRequestContext()->cookie_store()->GetCookieMonster(); + net::CookieMonster* monster = profile_->GetCookieMonster(); monster->SetCookie(GURL("http://foo1"), "A=1"); monster->SetCookie(GURL("http://foo2"), "B=1"); monster->SetCookie(GURL("http://foo3"), "C=1"); @@ -309,8 +320,7 @@ TEST_F(CookiesViewTest, RemoveDefaultSelection) { } TEST_F(CookiesViewTest, Filter) { - net::CookieMonster* monster = - profile_->GetRequestContext()->cookie_store()->GetCookieMonster(); + net::CookieMonster* monster = profile_->GetCookieMonster(); monster->SetCookie(GURL("http://foo1"), "A=1"); monster->SetCookie(GURL("http://bar1"), "B=1"); monster->SetCookie(GURL("http://foo2"), "C=1"); @@ -344,8 +354,7 @@ TEST_F(CookiesViewTest, Filter) { } TEST_F(CookiesViewTest, FilterRemoveAll) { - net::CookieMonster* monster = - profile_->GetRequestContext()->cookie_store()->GetCookieMonster(); + net::CookieMonster* monster = profile_->GetCookieMonster(); monster->SetCookie(GURL("http://foo1"), "A=1"); monster->SetCookie(GURL("http://bar1"), "B=1"); monster->SetCookie(GURL("http://foo2"), "C=1"); @@ -370,8 +379,7 @@ TEST_F(CookiesViewTest, FilterRemoveAll) { } TEST_F(CookiesViewTest, FilterRemove) { - net::CookieMonster* monster = - profile_->GetRequestContext()->cookie_store()->GetCookieMonster(); + net::CookieMonster* monster = profile_->GetCookieMonster(); monster->SetCookie(GURL("http://foo1"), "A=1"); monster->SetCookie(GURL("http://bar1"), "B=1"); monster->SetCookie(GURL("http://foo2"), "C=1"); @@ -406,8 +414,7 @@ TEST_F(CookiesViewTest, FilterRemove) { } TEST_F(CookiesViewTest, Sort) { - net::CookieMonster* monster = - profile_->GetRequestContext()->cookie_store()->GetCookieMonster(); + net::CookieMonster* monster = profile_->GetCookieMonster(); monster->SetCookie(GURL("http://foo1"), "X=1"); monster->SetCookie(GURL("http://bar1"), "Z=1"); monster->SetCookie(GURL("http://foo2"), "C=1"); @@ -442,8 +449,7 @@ TEST_F(CookiesViewTest, Sort) { } TEST_F(CookiesViewTest, SortRemove) { - net::CookieMonster* monster = - profile_->GetRequestContext()->cookie_store()->GetCookieMonster(); + net::CookieMonster* monster = profile_->GetCookieMonster(); monster->SetCookie(GURL("http://foo1"), "B=1"); monster->SetCookie(GURL("http://bar1"), "Z=1"); monster->SetCookie(GURL("http://foo2"), "C=1"); @@ -471,8 +477,7 @@ TEST_F(CookiesViewTest, SortRemove) { } TEST_F(CookiesViewTest, SortFilterRemove) { - net::CookieMonster* monster = - profile_->GetRequestContext()->cookie_store()->GetCookieMonster(); + net::CookieMonster* monster = profile_->GetCookieMonster(); monster->SetCookie(GURL("http://foo1"), "B=1"); monster->SetCookie(GURL("http://bar1"), "Z=1"); monster->SetCookie(GURL("http://foo2"), "C=1"); @@ -506,8 +511,7 @@ TEST_F(CookiesViewTest, SortFilterRemove) { } TEST_F(CookiesViewTest, SortRemoveMultiple) { - net::CookieMonster* monster = - profile_->GetRequestContext()->cookie_store()->GetCookieMonster(); + net::CookieMonster* monster = profile_->GetCookieMonster(); monster->SetCookie(GURL("http://foo0"), "C=1"); monster->SetCookie(GURL("http://foo1"), "D=1"); monster->SetCookie(GURL("http://foo2"), "B=1"); @@ -546,8 +550,7 @@ TEST_F(CookiesViewTest, SortRemoveMultiple) { } TEST_F(CookiesViewTest, SortRemoveDefaultSelection) { - net::CookieMonster* monster = - profile_->GetRequestContext()->cookie_store()->GetCookieMonster(); + net::CookieMonster* monster = profile_->GetCookieMonster(); monster->SetCookie(GURL("http://foo1"), "Z=1"); monster->SetCookie(GURL("http://bar1"), "X=1"); monster->SetCookie(GURL("http://foo2"), "W=1"); diff --git a/chrome/browser/importer/toolbar_importer.cc b/chrome/browser/importer/toolbar_importer.cc index 669abab..47a1cfd 100644 --- a/chrome/browser/importer/toolbar_importer.cc +++ b/chrome/browser/importer/toolbar_importer.cc @@ -11,6 +11,7 @@ #include "base/rand_util.h" #include "chrome/browser/first_run.h" #include "chrome/browser/importer/importer_bridge.h" +#include "chrome/browser/net/url_request_context_getter.h" #include "chrome/common/libxml_utils.h" #include "grit/generated_resources.h" #include "net/base/cookie_monster.h" @@ -25,8 +26,8 @@ static const wchar_t kSplitStringToken = L';'; static const char* kGoogleDomainSecureCookieId = "SID="; bool toolbar_importer_utils::IsGoogleGAIACookieInstalled() { - URLRequestContext* context = Profile::GetDefaultRequestContext(); - net::CookieStore* store = context->cookie_store(); + net::CookieStore* store = + Profile::GetDefaultRequestContext()->GetCookieStore(); GURL url(kGoogleDomainUrl); net::CookieOptions options; options.set_include_httponly(); // The SID cookie might be httponly. 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_ + diff --git a/chrome/browser/plugin_process_host.cc b/chrome/browser/plugin_process_host.cc index 35dcda3..fe4583a 100644 --- a/chrome/browser/plugin_process_host.cc +++ b/chrome/browser/plugin_process_host.cc @@ -34,6 +34,7 @@ #include "chrome/browser/child_process_security_policy.h" #include "chrome/browser/chrome_plugin_browsing_context.h" #include "chrome/browser/chrome_thread.h" +#include "chrome/browser/net/url_request_context_getter.h" #include "chrome/browser/net/url_request_tracking.h" #include "chrome/browser/plugin_service.h" #include "chrome/browser/profile.h" @@ -149,7 +150,8 @@ void PluginDownloadUrlHelper::InitiateDownload() { download_file_request_ = new URLRequest(GURL(download_url_), this); chrome_browser_net::SetOriginProcessUniqueIDForRequest( download_source_child_unique_id_, download_file_request_); - download_file_request_->set_context(Profile::GetDefaultRequestContext()); + download_file_request_->set_context( + Profile::GetDefaultRequestContext()->GetURLRequestContext()); download_file_request_->Start(); } @@ -563,7 +565,7 @@ void PluginProcessHost::OnGetCookies(uint32 request_context, ToURLRequestContext(request_context); // TODO(mpcomplete): remove fallback case when Gears support is prevalent. if (!context) - context = Profile::GetDefaultRequestContext(); + context = Profile::GetDefaultRequestContext()->GetURLRequestContext(); // Note: We don't have a first_party_for_cookies check because plugins bypass // third-party cookie blocking. diff --git a/chrome/browser/profile.cc b/chrome/browser/profile.cc index 8e3e43e..2f6b153 100644 --- a/chrome/browser/profile.cc +++ b/chrome/browser/profile.cc @@ -124,9 +124,9 @@ bool HasACacheSubdir(const FilePath &dir) { // A pointer to the request context for the default profile. See comments on // Profile::GetDefaultRequestContext. -URLRequestContext* Profile::default_request_context_; +URLRequestContextGetter* Profile::default_request_context_; -static void CleanupRequestContext(ChromeURLRequestContext* context) { +static void CleanupRequestContext(ChromeURLRequestContextGetter* context) { if (context) { context->CleanupOnUIThread(); @@ -136,17 +136,6 @@ static void CleanupRequestContext(ChromeURLRequestContext* context) { } } -static void CleanupAppCacheService(ChromeAppCacheService* appcache_service) { - if (appcache_service) { - // The I/O thread may be NULL during testing. - base::Thread* io_thread = g_browser_process->io_thread(); - if (io_thread) - io_thread->message_loop()->ReleaseSoon(FROM_HERE, appcache_service); - else - appcache_service->Release(); - } -} - // static const ProfileId Profile::InvalidProfileId = static_cast<ProfileId>(0); @@ -179,7 +168,7 @@ Profile* Profile::CreateProfile(const FilePath& path) { } // static -URLRequestContext* Profile::GetDefaultRequestContext() { +URLRequestContextGetter* Profile::GetDefaultRequestContext() { return default_request_context_; } @@ -209,13 +198,7 @@ class OffTheRecordProfileImpl : public Profile, : profile_(real_profile), extensions_request_context_(NULL), start_time_(Time::Now()) { - // Created here but lazily inititialized later, finally released on - // on the io thread, see CleanupAppCacheService. - appcache_service_ = new ChromeAppCacheService(); - appcache_service_->AddRef(); - - request_context_ = ChromeURLRequestContext::CreateOffTheRecord( - this, appcache_service_); + request_context_ = ChromeURLRequestContextGetter::CreateOffTheRecord(this); request_context_->AddRef(); // Register for browser close notifications so we can detect when the last @@ -228,7 +211,6 @@ class OffTheRecordProfileImpl : public Profile, virtual ~OffTheRecordProfileImpl() { CleanupRequestContext(request_context_); CleanupRequestContext(extensions_request_context_); - CleanupAppCacheService(appcache_service_); } virtual ProfileId GetRuntimeId() { @@ -254,13 +236,6 @@ class OffTheRecordProfileImpl : public Profile, return profile_; } - virtual ChromeAppCacheService* GetAppCacheService() { - DCHECK(request_context_); // should be created in ctor - if (!appcache_service_->is_initialized()) - appcache_service_->InitializeOnUIThread(GetPath(), true); - return appcache_service_; - } - virtual VisitedLinkMaster* GetVisitedLinkMaster() { // We don't provide access to the VisitedLinkMaster when we're OffTheRecord // because we don't want to leak the sites that the user has visited before. @@ -393,22 +368,20 @@ class OffTheRecordProfileImpl : public Profile, return GetOriginalProfile()->GetThemeProvider(); } - virtual URLRequestContext* GetRequestContext() { + virtual URLRequestContextGetter* GetRequestContext() { return request_context_; } - virtual URLRequestContext* GetRequestContextForMedia() { + virtual URLRequestContextGetter* GetRequestContextForMedia() { // In OTR mode, media request context is the same as the original one. return request_context_; } - URLRequestContext* GetRequestContextForExtensions() { + URLRequestContextGetter* GetRequestContextForExtensions() { if (!extensions_request_context_) { extensions_request_context_ = - ChromeURLRequestContext::CreateOffTheRecordForExtensions(this); + ChromeURLRequestContextGetter::CreateOffTheRecordForExtensions(this); extensions_request_context_->AddRef(); - - DCHECK(extensions_request_context_->cookie_store()); } return extensions_request_context_; @@ -547,12 +520,9 @@ class OffTheRecordProfileImpl : public Profile, Profile* profile_; // The context to use for requests made from this OTR session. - ChromeURLRequestContext* request_context_; + ChromeURLRequestContextGetter* request_context_; - ChromeURLRequestContext* extensions_request_context_; - - // Use a seperate appcache service for OTR. - ChromeAppCacheService* appcache_service_; + ChromeURLRequestContextGetter* extensions_request_context_; // The download manager that only stores downloaded items in memory. scoped_refptr<DownloadManager> download_manager_; @@ -603,11 +573,6 @@ ProfileImpl::ProfileImpl(const FilePath& path) extension_devtools_manager_ = new ExtensionDevToolsManager(this); } - // Created here but lazily inititialized later, finally released on - // on the io thread, see CleanupAppCacheService. - appcache_service_ = new ChromeAppCacheService(); - appcache_service_->AddRef(); - extension_process_manager_.reset(new ExtensionProcessManager(this)); extension_message_service_ = new ExtensionMessageService(this); @@ -788,7 +753,6 @@ ProfileImpl::~ProfileImpl() { CleanupRequestContext(request_context_); CleanupRequestContext(media_request_context_); CleanupRequestContext(extensions_request_context_); - CleanupAppCacheService(appcache_service_); // When the request contexts are gone, the blacklist wont be needed anymore. delete blacklist_; @@ -843,14 +807,6 @@ Profile* ProfileImpl::GetOriginalProfile() { return this; } -ChromeAppCacheService* ProfileImpl::GetAppCacheService() { - if (!appcache_service_->is_initialized()) { - EnsureRequestContextCreated(); - appcache_service_->InitializeOnUIThread(GetPath(), false); - } - return appcache_service_; -} - VisitedLinkMaster* ProfileImpl::GetVisitedLinkMaster() { if (!visited_link_master_.get()) { scoped_ptr<VisitedLinkMaster> visited_links( @@ -939,7 +895,7 @@ FilePath ProfileImpl::GetPrefFilePath() { return pref_file_path; } -URLRequestContext* ProfileImpl::GetRequestContext() { +URLRequestContextGetter* ProfileImpl::GetRequestContext() { if (!request_context_) { FilePath cookie_path = GetPath(); cookie_path = cookie_path.Append(chrome::kCookieFilename); @@ -948,8 +904,8 @@ URLRequestContext* ProfileImpl::GetRequestContext() { GetCacheParameters(kNormalContext, &cache_path, &max_size); cache_path = GetCachePath(cache_path); - request_context_ = ChromeURLRequestContext::CreateOriginal( - this, cookie_path, cache_path, max_size, appcache_service_); + request_context_ = ChromeURLRequestContextGetter::CreateOriginal( + this, cookie_path, cache_path, max_size); request_context_->AddRef(); // The first request context is always a normal (non-OTR) request context. @@ -957,33 +913,28 @@ URLRequestContext* ProfileImpl::GetRequestContext() { // created first. if (!default_request_context_) { default_request_context_ = request_context_; + // TODO(eroman): this isn't terribly useful anymore now that the + // URLRequestContext is constructed by the IO thread... NotificationService::current()->Notify( NotificationType::DEFAULT_REQUEST_CONTEXT_AVAILABLE, NotificationService::AllSources(), NotificationService::NoDetails()); -#if defined(OS_LINUX) - // TODO(ukai): find a better way to set the URLRequestContext for OCSP. - net::SetURLRequestContextForOCSP(default_request_context_); -#endif } - - DCHECK(request_context_->cookie_store()); } return request_context_; } -URLRequestContext* ProfileImpl::GetRequestContextForMedia() { +URLRequestContextGetter* ProfileImpl::GetRequestContextForMedia() { if (!media_request_context_) { FilePath cache_path = base_cache_path_; int max_size; GetCacheParameters(kMediaContext, &cache_path, &max_size); cache_path = GetMediaCachePath(cache_path); - media_request_context_ = ChromeURLRequestContext::CreateOriginalForMedia( - this, cache_path, max_size, appcache_service_); + media_request_context_ = + ChromeURLRequestContextGetter::CreateOriginalForMedia( + this, cache_path, max_size); media_request_context_->AddRef(); - - DCHECK(media_request_context_->cookie_store()); } return media_request_context_; @@ -998,16 +949,15 @@ FaviconService* ProfileImpl::GetFaviconService(ServiceAccessType sat) { return favicon_service_.get(); } -URLRequestContext* ProfileImpl::GetRequestContextForExtensions() { +URLRequestContextGetter* ProfileImpl::GetRequestContextForExtensions() { if (!extensions_request_context_) { FilePath cookie_path = GetPath(); cookie_path = cookie_path.Append(chrome::kExtensionsCookieFilename); extensions_request_context_ = - ChromeURLRequestContext::CreateOriginalForExtensions(this, cookie_path); + ChromeURLRequestContextGetter::CreateOriginalForExtensions( + this, cookie_path); extensions_request_context_->AddRef(); - - DCHECK(extensions_request_context_->cookie_store()); } return extensions_request_context_; diff --git a/chrome/browser/profile.h b/chrome/browser/profile.h index a9ac35a..d190989 100644 --- a/chrome/browser/profile.h +++ b/chrome/browser/profile.h @@ -25,11 +25,11 @@ namespace net { class StrictTransportSecurityState; class SSLConfigService; } + class Blacklist; class BookmarkModel; class BrowserThemeProvider; -class ChromeAppCacheService; -class ChromeURLRequestContext; +class ChromeURLRequestContextGetter; class DesktopNotificationService; class DownloadManager; class Extension; @@ -54,7 +54,7 @@ class TemplateURLFetcher; class TemplateURLModel; class ThemeProvider; class ThumbnailStore; -class URLRequestContext; +class URLRequestContextGetter; class UserScriptMaster; class VisitedLinkMaster; class VisitedLinkEventListener; @@ -110,7 +110,7 @@ class Profile { // // The returned object is ref'd by the profile. Callers who AddRef() it (to // keep it alive longer than the profile) must Release() it on the I/O thread. - static URLRequestContext* GetDefaultRequestContext(); + static URLRequestContextGetter* GetDefaultRequestContext(); // Returns a unique Id that can be used to identify this profile at runtime. // This Id is not persistent and will not survive a restart of the browser. @@ -134,11 +134,6 @@ class Profile { // profile is not off the record. virtual Profile* GetOriginalProfile() = 0; - // Retrieves a pointer to the AppCacheService for this profile. - // Chrome request contexts associated with this profile also have - // a reference to this instance. - virtual ChromeAppCacheService* GetAppCacheService() = 0; - // Retrieves a pointer to the VisitedLinkMaster associated with this // profile. The VisitedLinkMaster is lazily created the first time // that this method is called. @@ -261,15 +256,15 @@ class Profile { // // The returned object is ref'd by the profile. Callers who AddRef() it (to // keep it alive longer than the profile) must Release() it on the I/O thread. - virtual URLRequestContext* GetRequestContext() = 0; + virtual URLRequestContextGetter* GetRequestContext() = 0; // Returns the request context for media resources asociated with this // profile. - virtual URLRequestContext* GetRequestContextForMedia() = 0; + virtual URLRequestContextGetter* GetRequestContextForMedia() = 0; // Returns the request context used for extension-related requests. This // is only used for a separate cookie store currently. - virtual URLRequestContext* GetRequestContextForExtensions() = 0; + virtual URLRequestContextGetter* GetRequestContextForExtensions() = 0; // Returns the SSLConfigService for this profile. virtual net::SSLConfigService* GetSSLConfigService() = 0; @@ -360,7 +355,7 @@ class Profile { #ifdef UNIT_TEST // Use with caution. GetDefaultRequestContext may be called on any thread! - static void set_default_request_context(URLRequestContext* c) { + static void set_default_request_context(URLRequestContextGetter* c) { default_request_context_ = c; } #endif @@ -374,7 +369,7 @@ class Profile { } protected: - static URLRequestContext* default_request_context_; + static URLRequestContextGetter* default_request_context_; private: bool restored_last_session_; @@ -395,7 +390,6 @@ class ProfileImpl : public Profile, virtual Profile* GetOffTheRecordProfile(); virtual void DestroyOffTheRecordProfile(); virtual Profile* GetOriginalProfile(); - virtual ChromeAppCacheService* GetAppCacheService(); virtual VisitedLinkMaster* GetVisitedLinkMaster(); virtual UserScriptMaster* GetUserScriptMaster(); virtual SSLHostState* GetSSLHostState(); @@ -421,9 +415,9 @@ class ProfileImpl : public Profile, virtual ThemeProvider* GetThemeProvider(); virtual ThumbnailStore* GetThumbnailStore(); virtual bool HasCreatedDownloadManager() const; - virtual URLRequestContext* GetRequestContext(); - virtual URLRequestContext* GetRequestContextForMedia(); - virtual URLRequestContext* GetRequestContextForExtensions(); + virtual URLRequestContextGetter* GetRequestContext(); + virtual URLRequestContextGetter* GetRequestContextForMedia(); + virtual URLRequestContextGetter* GetRequestContextForExtensions(); virtual net::SSLConfigService* GetSSLConfigService(); virtual Blacklist* GetBlacklist(); virtual SessionService* GetSessionService(); @@ -505,13 +499,11 @@ class ProfileImpl : public Profile, scoped_ptr<ProfileSyncService> sync_service_; #endif - ChromeAppCacheService* appcache_service_; - - ChromeURLRequestContext* request_context_; + ChromeURLRequestContextGetter* request_context_; - ChromeURLRequestContext* media_request_context_; + ChromeURLRequestContextGetter* media_request_context_; - ChromeURLRequestContext* extensions_request_context_; + ChromeURLRequestContextGetter* extensions_request_context_; scoped_ptr<SSLConfigServiceManager> ssl_config_service_manager_; diff --git a/chrome/browser/profile_manager.cc b/chrome/browser/profile_manager.cc index 3d15524..94bbfe9 100644 --- a/chrome/browser/profile_manager.cc +++ b/chrome/browser/profile_manager.cc @@ -15,6 +15,7 @@ #include "chrome/browser/browser_process.h" #include "chrome/browser/browser_window.h" #include "chrome/browser/chrome_thread.h" +#include "chrome/browser/net/url_request_context_getter.h" #include "chrome/common/chrome_constants.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/logging_chrome.h" @@ -242,14 +243,16 @@ void ProfileManager::SuspendProfile(Profile* profile) { i != g_url_request_job_tracker.end(); ++i) (*i)->Kill(); - profile->GetRequestContext()->http_transaction_factory()->Suspend(true); + profile->GetRequestContext()->GetURLRequestContext()-> + http_transaction_factory()->Suspend(true); } void ProfileManager::ResumeProfile(Profile* profile) { DCHECK(profile); DCHECK(MessageLoop::current() == ChromeThread::GetMessageLoop(ChromeThread::IO)); - profile->GetRequestContext()->http_transaction_factory()->Suspend(false); + profile->GetRequestContext()->GetURLRequestContext()-> + http_transaction_factory()->Suspend(false); } diff --git a/chrome/browser/renderer_host/resource_dispatcher_host.cc b/chrome/browser/renderer_host/resource_dispatcher_host.cc index 3ce96d1..fd42868 100644 --- a/chrome/browser/renderer_host/resource_dispatcher_host.cc +++ b/chrome/browser/renderer_host/resource_dispatcher_host.cc @@ -402,8 +402,12 @@ void ResourceDispatcherHost::BeginRequest( ChromeURLRequestContext* context = static_cast<ChromeURLRequestContext*>( receiver_->GetRequestContext(request_id, request_data)); if (!context) { - context = static_cast<ChromeURLRequestContext*>( - Profile::GetDefaultRequestContext()); + URLRequestContextGetter* context_getter = + Profile::GetDefaultRequestContext(); + if (context_getter) { + context = static_cast<ChromeURLRequestContext*>( + context_getter->GetURLRequestContext()); + } } if (is_shutdown_ || diff --git a/chrome/browser/renderer_host/resource_dispatcher_host.h b/chrome/browser/renderer_host/resource_dispatcher_host.h index 776f720..1cfe9a8 100644 --- a/chrome/browser/renderer_host/resource_dispatcher_host.h +++ b/chrome/browser/renderer_host/resource_dispatcher_host.h @@ -61,7 +61,7 @@ class ResourceDispatcherHost : public URLRequest::Delegate { class Receiver : public IPC::Message::Sender, public ChildProcessInfo { public: - // Return the URLRequestContext for the given request. + // Returns the URLRequestContext for the given request. // If NULL is returned, the default context for the profile is used. virtual URLRequestContext* GetRequestContext( uint32 request_id, diff --git a/chrome/browser/renderer_host/resource_message_filter.cc b/chrome/browser/renderer_host/resource_message_filter.cc index 6818a90..0650fa7 100644 --- a/chrome/browser/renderer_host/resource_message_filter.cc +++ b/chrome/browser/renderer_host/resource_message_filter.cc @@ -163,7 +163,7 @@ ResourceMessageFilter::ResourceMessageFilter( render_widget_helper_(render_widget_helper), audio_renderer_host_(audio_renderer_host), appcache_dispatcher_host_( - new AppCacheDispatcherHost(profile->GetAppCacheService())), + new AppCacheDispatcherHost(profile->GetRequestContext())), ALLOW_THIS_IN_INITIALIZER_LIST(dom_storage_dispatcher_host_( new DOMStorageDispatcherHost(this, profile->GetWebKitContext(), resource_dispatcher_host->webkit_thread()))), @@ -174,10 +174,8 @@ ResourceMessageFilter::ResourceMessageFilter( off_the_record_(profile->IsOffTheRecord()), next_route_id_callback_(NewCallbackWithReturnValue( render_widget_helper, &RenderWidgetHelper::GetNextRoutingID)) { - DCHECK(request_context_.get()); - DCHECK(request_context_->cookie_store()); - DCHECK(media_request_context_.get()); - DCHECK(media_request_context_->cookie_store()); + DCHECK(request_context_); + DCHECK(media_request_context_); DCHECK(audio_renderer_host_.get()); DCHECK(appcache_dispatcher_host_.get()); DCHECK(dom_storage_dispatcher_host_.get()); @@ -439,13 +437,13 @@ bool ResourceMessageFilter::Send(IPC::Message* message) { URLRequestContext* ResourceMessageFilter::GetRequestContext( uint32 request_id, const ViewHostMsg_Resource_Request& request_data) { - URLRequestContext* request_context = request_context_; + URLRequestContextGetter* request_context = request_context_; // If the request has resource type of ResourceType::MEDIA, we use a request // context specific to media for handling it because these resources have // specific needs for caching. if (request_data.resource_type == ResourceType::MEDIA) request_context = media_request_context_; - return request_context; + return request_context->GetURLRequestContext(); } MessageLoop* ResourceMessageFilter::ui_loop() { @@ -469,9 +467,8 @@ void ResourceMessageFilter::OnMsgCreateWidget(int opener_id, void ResourceMessageFilter::OnSetCookie(const GURL& url, const GURL& first_party_for_cookies, const std::string& cookie) { - ChromeURLRequestContext* context = static_cast<ChromeURLRequestContext*>( - url.SchemeIs(chrome::kExtensionScheme) ? - extensions_request_context_.get() : request_context_.get()); + ChromeURLRequestContext* context = GetRequestContextForURL(url); + if (context->cookie_policy()->CanSetCookie(url, first_party_for_cookies)) { if (context->blacklist()) { Blacklist::Match* match = context->blacklist()->findMatch(url); @@ -493,8 +490,7 @@ void ResourceMessageFilter::OnSetCookie(const GURL& url, void ResourceMessageFilter::OnGetCookies(const GURL& url, const GURL& first_party_for_cookies, std::string* cookies) { - URLRequestContext* context = url.SchemeIs(chrome::kExtensionScheme) ? - extensions_request_context_.get() : request_context_.get(); + URLRequestContext* context = GetRequestContextForURL(url); if (context->cookie_policy()->CanGetCookies(url, first_party_for_cookies)) *cookies = context->cookie_store()->GetCookies(url); } @@ -636,11 +632,12 @@ void ResourceMessageFilter::OnForwardToWorker(const IPC::Message& message) { void ResourceMessageFilter::OnDownloadUrl(const IPC::Message& message, const GURL& url, const GURL& referrer) { + URLRequestContext* context = request_context_->GetURLRequestContext(); resource_dispatcher_host_->BeginDownload(url, referrer, id(), message.routing_id(), - request_context_); + context); } void ResourceMessageFilter::OnClipboardWriteObjects( @@ -735,8 +732,8 @@ void ResourceMessageFilter::OnGetPreferredExtensionForMimeType( void ResourceMessageFilter::OnGetCPBrowsingContext(uint32* context) { // Always allocate a new context when a plugin requests one, since it needs to // be unique for that plugin instance. - *context = - CPBrowsingContextManager::Instance()->Allocate(request_context_.get()); + *context = CPBrowsingContextManager::Instance()->Allocate( + request_context_->GetURLRequestContext()); } #if defined(OS_WIN) @@ -924,6 +921,16 @@ Clipboard* ResourceMessageFilter::GetClipboard() { return clipboard; } +ChromeURLRequestContext* +ResourceMessageFilter::GetRequestContextForURL( + const GURL& url) { + URLRequestContextGetter* context_getter = + url.SchemeIs(chrome::kExtensionScheme) ? + extensions_request_context_ : request_context_; + return static_cast<ChromeURLRequestContext*>( + context_getter->GetURLRequestContext()); +} + // Notes about SpellCheck. // // Spellchecking generally uses a fair amount of RAM. For this reason, we load @@ -1060,7 +1067,7 @@ void ResourceMessageFilter::OnCloseIdleConnections() { // benchmarking extensions. if (!CheckBenchmarkingEnabled()) return; - request_context_-> + request_context_->GetURLRequestContext()-> http_transaction_factory()->GetCache()->CloseIdleConnections(); } @@ -1072,7 +1079,8 @@ void ResourceMessageFilter::OnSetCacheMode(bool enabled) { net::HttpCache::Mode mode = enabled ? net::HttpCache::NORMAL : net::HttpCache::DISABLE; - request_context_->http_transaction_factory()->GetCache()->set_mode(mode); + request_context_->GetURLRequestContext()-> + http_transaction_factory()->GetCache()->set_mode(mode); } void ResourceMessageFilter::OnGetFileSize(const FilePath& path, diff --git a/chrome/browser/renderer_host/resource_message_filter.h b/chrome/browser/renderer_host/resource_message_filter.h index 95df005..029fb20 100644 --- a/chrome/browser/renderer_host/resource_message_filter.h +++ b/chrome/browser/renderer_host/resource_message_filter.h @@ -32,6 +32,7 @@ class AppCacheDispatcherHost; class AudioRendererHost; +class ChromeURLRequestContext; class DatabaseDispatcherHost; class DOMStorageDispatcherHost; class ExtensionMessageService; @@ -39,6 +40,7 @@ class NotificationsPrefsCache; class Profile; class RenderWidgetHelper; class SpellChecker; +class URLRequestContextGetter; struct ViewHostMsg_Audio_CreateStream; struct WebPluginInfo; @@ -299,6 +301,10 @@ class ResourceMessageFilter : public IPC::ChannelProxy::MessageFilter, // thread. static Clipboard* GetClipboard(); + // Returns either the extension URLRequestContext or regular URLRequestContext + // depending on whether |url| is an extension URL. + ChromeURLRequestContext* GetRequestContextForURL(const GURL& url); + NotificationRegistrar registrar_; // The channel associated with the renderer connection. This pointer is not @@ -326,13 +332,13 @@ class ResourceMessageFilter : public IPC::ChannelProxy::MessageFilter, ResolveProxyMsgHelper resolve_proxy_msg_helper_; // Contextual information to be used for requests created here. - scoped_refptr<URLRequestContext> request_context_; + scoped_refptr<URLRequestContextGetter> request_context_; // A request context specific for media resources. - scoped_refptr<URLRequestContext> media_request_context_; + scoped_refptr<URLRequestContextGetter> media_request_context_; // A request context that holds a cookie store for chrome-extension URLs. - scoped_refptr<URLRequestContext> extensions_request_context_; + scoped_refptr<URLRequestContextGetter> extensions_request_context_; // Used for routing extension messages. scoped_refptr<ExtensionMessageService> extensions_message_service_; diff --git a/chrome/browser/spellchecker.cc b/chrome/browser/spellchecker.cc index 51c9a7d..2056517 100644 --- a/chrome/browser/spellchecker.cc +++ b/chrome/browser/spellchecker.cc @@ -463,7 +463,7 @@ FilePath SpellChecker::GetVersionedFileName(const std::string& input_language, SpellChecker::SpellChecker(const FilePath& dict_dir, const std::string& language, - URLRequestContext* request_context, + URLRequestContextGetter* request_context_getter, const FilePath& custom_dictionary_file_name) : given_dictionary_directory_(dict_dir), custom_dictionary_file_name_(custom_dictionary_file_name), @@ -472,7 +472,7 @@ SpellChecker::SpellChecker(const FilePath& dict_dir, worker_loop_(NULL), tried_to_download_dictionary_file_(false), file_loop_(NULL), - url_request_context_(request_context), + request_context_getter_(request_context_getter), obtaining_dictionary_(false), auto_spell_correct_turned_on_(false), is_using_platform_spelling_engine_(false), @@ -524,7 +524,7 @@ void SpellChecker::StartDictionaryDownload(const FilePath& file_name) { GURL url = GURL(std::string(kDownloadServerUrl) + WideToUTF8( l10n_util::ToLower(bdic_file_name_.ToWStringHack()))); fetcher_.reset(new URLFetcher(url, URLFetcher::GET, this)); - fetcher_->set_request_context(url_request_context_); + fetcher_->set_request_context(request_context_getter_); obtaining_dictionary_ = true; fetcher_->Start(); } @@ -654,7 +654,7 @@ void SpellChecker::HunspellInited(Hunspell* hunspell, void SpellChecker::DoDictionaryDownload() { // Download the dictionary file. - if (file_loop_ && url_request_context_) { + if (file_loop_ && request_context_getter_) { if (!tried_to_download_dictionary_file_) { FilePath dictionary_file_name_app = GetVersionedFileName(language_, given_dictionary_directory_); diff --git a/chrome/browser/spellchecker.h b/chrome/browser/spellchecker.h index 1a78f61..295ab43 100644 --- a/chrome/browser/spellchecker.h +++ b/chrome/browser/spellchecker.h @@ -26,8 +26,8 @@ class Hunspell; class PrefService; class Profile; class MessageLoop; -class URLRequestContext; class URLFetcher; +class URLRequestContextGetter; namespace file_util { class MemoryMappedFile; @@ -56,7 +56,7 @@ class SpellChecker : public base::RefCountedThreadSafe<SpellChecker>, // testing. SpellChecker(const FilePath& dict_dir, const std::string& language, - URLRequestContext* request_context, + URLRequestContextGetter* request_context_getter, const FilePath& custom_dictionary_file_name); // Only delete on the I/O thread (see above). @@ -210,7 +210,7 @@ class SpellChecker : public base::RefCountedThreadSafe<SpellChecker>, MessageLoop* file_loop_; // Used for requests. MAY BE NULL which means don't try to download. - URLRequestContext* url_request_context_; + URLRequestContextGetter* request_context_getter_; // True when we're downloading or saving a dictionary. bool obtaining_dictionary_; diff --git a/chrome/browser/sync/glue/http_bridge.cc b/chrome/browser/sync/glue/http_bridge.cc index dfda3b5..3448755 100644 --- a/chrome/browser/sync/glue/http_bridge.cc +++ b/chrome/browser/sync/glue/http_bridge.cc @@ -21,24 +21,46 @@ namespace browser_sync { +HttpBridge::RequestContextGetter::RequestContextGetter( + URLRequestContextGetter* baseline_context_getter) + : baseline_context_getter_(baseline_context_getter) { +} + +URLRequestContext* HttpBridge::RequestContextGetter::GetURLRequestContext() { + // Lazily create the context. + if (!context_) { + URLRequestContext* baseline_context = + baseline_context_getter_->GetURLRequestContext(); + context_ = new RequestContext(baseline_context); + baseline_context_getter_ = NULL; + } + + // Apply the user agent which was set earlier. + if (is_user_agent_set()) + context_->set_user_agent(user_agent_); + + return context_; +} + HttpBridgeFactory::HttpBridgeFactory( - URLRequestContext* baseline_context) { - DCHECK(baseline_context != NULL); - request_context_ = new HttpBridge::RequestContext(baseline_context); - request_context_->AddRef(); + URLRequestContextGetter* baseline_context_getter) { + DCHECK(baseline_context_getter != NULL); + request_context_getter_ = + new HttpBridge::RequestContextGetter(baseline_context_getter); + request_context_getter_->AddRef(); } HttpBridgeFactory::~HttpBridgeFactory() { - if (request_context_) { - // Clean up request context on IO thread. + if (request_context_getter_) { + // Clean up request context getter on IO thread. ChromeThread::GetMessageLoop(ChromeThread::IO)->ReleaseSoon(FROM_HERE, - request_context_); - request_context_ = NULL; + request_context_getter_); + request_context_getter_ = NULL; } } sync_api::HttpPostProviderInterface* HttpBridgeFactory::Create() { - HttpBridge* http = new HttpBridge(request_context_, + HttpBridge* http = new HttpBridge(request_context_getter_, ChromeThread::GetMessageLoop(ChromeThread::IO)); http->AddRef(); return http; @@ -87,9 +109,9 @@ HttpBridge::RequestContext::~RequestContext() { delete http_transaction_factory_; } -HttpBridge::HttpBridge(HttpBridge::RequestContext* context, +HttpBridge::HttpBridge(HttpBridge::RequestContextGetter* context_getter, MessageLoop* io_loop) - : context_for_request_(context), + : context_getter_for_request_(context_getter), url_poster_(NULL), created_on_loop_(MessageLoop::current()), io_loop_(io_loop), @@ -98,17 +120,17 @@ HttpBridge::HttpBridge(HttpBridge::RequestContext* context, http_response_code_(-1), http_post_completed_(false, false), use_io_loop_for_testing_(false) { - context_for_request_->AddRef(); + context_getter_for_request_->AddRef(); } HttpBridge::~HttpBridge() { - io_loop_->ReleaseSoon(FROM_HERE, context_for_request_); + io_loop_->ReleaseSoon(FROM_HERE, context_getter_for_request_); } void HttpBridge::SetUserAgent(const char* user_agent) { DCHECK_EQ(MessageLoop::current(), created_on_loop_); DCHECK(!request_completed_); - context_for_request_->set_user_agent(user_agent); + context_getter_for_request_->set_user_agent(user_agent); } void HttpBridge::SetExtraRequestHeaders(const char * headers) { @@ -153,7 +175,6 @@ bool HttpBridge::MakeSynchronousPost(int* os_error_code, int* response_code) { DCHECK(!request_completed_); DCHECK(url_for_request_.is_valid()) << "Invalid URL for request"; DCHECK(!content_type_.empty()) << "Payload not set"; - DCHECK(context_for_request_->is_user_agent_set()) << "User agent not set"; io_loop_->PostTask(FROM_HERE, NewRunnableMethod(this, &HttpBridge::CallMakeAsynchronousPost)); @@ -172,7 +193,7 @@ void HttpBridge::MakeAsynchronousPost() { DCHECK(!request_completed_); url_poster_ = new URLFetcher(url_for_request_, URLFetcher::POST, this); - url_poster_->set_request_context(context_for_request_); + url_poster_->set_request_context(context_getter_for_request_); url_poster_->set_upload_data(content_type_, request_content_); url_poster_->set_extra_request_headers(extra_headers_); @@ -194,10 +215,6 @@ const char* HttpBridge::GetResponseContent() const { return response_content_.data(); } -URLRequestContext* HttpBridge::GetRequestContext() const { - return context_for_request_; -} - void HttpBridge::OnURLFetchComplete(const URLFetcher *source, const GURL &url, const URLRequestStatus &status, int response_code, diff --git a/chrome/browser/sync/glue/http_bridge.h b/chrome/browser/sync/glue/http_bridge.h index ab491a0..7e1d967 100644 --- a/chrome/browser/sync/glue/http_bridge.h +++ b/chrome/browser/sync/glue/http_bridge.h @@ -12,6 +12,7 @@ #include "base/ref_counted.h" #include "base/waitable_event.h" #include "chrome/browser/net/url_fetcher.h" +#include "chrome/browser/net/url_request_context_getter.h" #include "chrome/browser/sync/engine/syncapi.h" #include "googleurl/src/gurl.h" #include "net/url_request/url_request_context.h" @@ -53,7 +54,6 @@ class HttpBridge : public base::RefCountedThreadSafe<HttpBridge>, // Set the user agent for requests using this context. The default is // the browser's UA string. void set_user_agent(const std::string& ua) { user_agent_ = ua; } - bool is_user_agent_set() const { return !user_agent_.empty(); } virtual const std::string& GetUserAgent(const GURL& url) const { // If the user agent is set explicitly return that, otherwise call the @@ -73,7 +73,31 @@ class HttpBridge : public base::RefCountedThreadSafe<HttpBridge>, DISALLOW_COPY_AND_ASSIGN(RequestContext); }; - HttpBridge(RequestContext* context, MessageLoop* io_loop); + // Lazy-getter for RequestContext objects. + class RequestContextGetter : public URLRequestContextGetter { + public: + explicit RequestContextGetter( + URLRequestContextGetter* baseline_context_getter); + + void set_user_agent(const std::string& ua) { user_agent_ = ua; } + bool is_user_agent_set() const { return !user_agent_.empty(); } + + // URLRequestContextGetter implementation. + virtual URLRequestContext* GetURLRequestContext(); + + private: + // User agent to apply to the URLRequestContext. + std::string user_agent_; + + scoped_refptr<URLRequestContextGetter> baseline_context_getter_; + + // Lazily initialized by GetURLRequestContext(). + scoped_refptr<RequestContext> context_; + + DISALLOW_COPY_AND_ASSIGN(RequestContextGetter); + }; + + HttpBridge(RequestContextGetter* context, MessageLoop* io_loop); virtual ~HttpBridge(); // sync_api::HttpPostProvider implementation. @@ -98,7 +122,11 @@ class HttpBridge : public base::RefCountedThreadSafe<HttpBridge>, const ResponseCookies& cookies, const std::string& data); - URLRequestContext* GetRequestContext() const; +#if defined(UNIT_TEST) + URLRequestContextGetter* GetRequestContextGetter() const { + return context_getter_for_request_; + } +#endif protected: // Protected virtual so the unit test can override to shunt network requests. @@ -112,9 +140,9 @@ class HttpBridge : public base::RefCountedThreadSafe<HttpBridge>, // still have a function to statically pass to PostTask. void CallMakeAsynchronousPost() { MakeAsynchronousPost(); } - // A customized URLRequestContext for bridged requests. See RequestContext - // definition for details. - RequestContext* context_for_request_; + // Gets a customized URLRequestContext for bridged requests. See + // RequestContext definition for details. + RequestContextGetter* context_getter_for_request_; // Our hook into the network layer is a URLFetcher. USED ONLY ON THE IO LOOP, // so we can block created_on_loop_ while the fetch is in progress. @@ -165,16 +193,16 @@ class HttpBridge : public base::RefCountedThreadSafe<HttpBridge>, class HttpBridgeFactory : public sync_api::HttpPostProviderFactory { public: - explicit HttpBridgeFactory(URLRequestContext* baseline_context); + explicit HttpBridgeFactory(URLRequestContextGetter* baseline_context_getter); virtual ~HttpBridgeFactory(); virtual sync_api::HttpPostProviderInterface* Create(); virtual void Destroy(sync_api::HttpPostProviderInterface* http); private: // This request context is built on top of the baseline context and shares // common components. - HttpBridge::RequestContext* GetRequestContext(); + HttpBridge::RequestContextGetter* GetRequestContextGetter(); // We must Release() this from the IO thread. - HttpBridge::RequestContext* request_context_; + HttpBridge::RequestContextGetter* request_context_getter_; DISALLOW_COPY_AND_ASSIGN(HttpBridgeFactory); }; diff --git a/chrome/browser/sync/glue/http_bridge_unittest.cc b/chrome/browser/sync/glue/http_bridge_unittest.cc index 32e0bc8..da3eb67 100644 --- a/chrome/browser/sync/glue/http_bridge_unittest.cc +++ b/chrome/browser/sync/glue/http_bridge_unittest.cc @@ -16,10 +16,22 @@ namespace { const wchar_t kDocRoot[] = L"chrome/test/data"; } +// Lazy getter for TestURLRequestContext instances. +class TestURLRequestContextGetter : public URLRequestContextGetter { + public: + virtual URLRequestContext* GetURLRequestContext() { + if (!context_) + context_ = new TestURLRequestContext; + return context_; + } + private: + scoped_refptr<URLRequestContext> context_; +}; + class HttpBridgeTest : public testing::Test { public: HttpBridgeTest() - : fake_default_request_context_(NULL), + : fake_default_request_context_getter_(NULL), io_thread_("HttpBridgeTest IO thread") { } @@ -30,19 +42,21 @@ class HttpBridgeTest : public testing::Test { } virtual void TearDown() { - io_thread_loop()->ReleaseSoon(FROM_HERE, fake_default_request_context_); + io_thread_loop()->ReleaseSoon(FROM_HERE, + fake_default_request_context_getter_); io_thread_.Stop(); - fake_default_request_context_ = NULL; + fake_default_request_context_getter_ = NULL; } HttpBridge* BuildBridge() { - if (!fake_default_request_context_) { - fake_default_request_context_ = new TestURLRequestContext(); - fake_default_request_context_->AddRef(); + if (!fake_default_request_context_getter_) { + fake_default_request_context_getter_ = new TestURLRequestContextGetter(); + fake_default_request_context_getter_->AddRef(); } HttpBridge* bridge = new HttpBridge( - new HttpBridge::RequestContext(fake_default_request_context_), - io_thread_.message_loop()); + new HttpBridge::RequestContextGetter( + fake_default_request_context_getter_), + io_thread_loop()); bridge->use_io_loop_for_testing_ = true; return bridge; } @@ -50,14 +64,14 @@ class HttpBridgeTest : public testing::Test { MessageLoop* io_thread_loop() { return io_thread_.message_loop(); } // Note this is lazy created, so don't call this before your bridge. - TestURLRequestContext* GetTestRequestContext() { - return fake_default_request_context_; + TestURLRequestContextGetter* GetTestRequestContextGetter() { + return fake_default_request_context_getter_; } private: // A make-believe "default" request context, as would be returned by // Profile::GetDefaultRequestContext(). Created lazily by BuildBridge. - TestURLRequestContext* fake_default_request_context_; + TestURLRequestContextGetter* fake_default_request_context_getter_; // Separate thread for IO used by the HttpBridge. base::Thread io_thread_; @@ -67,9 +81,10 @@ class HttpBridgeTest : public testing::Test { // back with dummy response info. class ShuntedHttpBridge : public HttpBridge { public: - ShuntedHttpBridge(URLRequestContext* baseline_context, + ShuntedHttpBridge(URLRequestContextGetter* baseline_context_getter, MessageLoop* io_loop, HttpBridgeTest* test) - : HttpBridge(new HttpBridge::RequestContext(baseline_context), + : HttpBridge(new HttpBridge::RequestContextGetter( + baseline_context_getter), io_loop), test_(test) { } protected: virtual void MakeAsynchronousPost() { @@ -94,19 +109,22 @@ class ShuntedHttpBridge : public HttpBridge { TEST_F(HttpBridgeTest, TestUsesSameHttpNetworkSession) { scoped_refptr<HttpBridge> http_bridge(this->BuildBridge()); - EXPECT_TRUE(GetTestRequestContext()); + EXPECT_TRUE(GetTestRequestContextGetter()); net::HttpNetworkSession* test_session = - GetTestRequestContext()->http_transaction_factory()->GetSession(); + GetTestRequestContextGetter()->GetURLRequestContext()-> + http_transaction_factory()->GetSession(); EXPECT_EQ(test_session, - http_bridge->GetRequestContext()-> + http_bridge->GetRequestContextGetter()-> + GetURLRequestContext()-> http_transaction_factory()->GetSession()); } // Test the HttpBridge without actually making any network requests. TEST_F(HttpBridgeTest, TestMakeSynchronousPostShunted) { - scoped_refptr<TestURLRequestContext> ctx(new TestURLRequestContext()); + scoped_refptr<URLRequestContextGetter> ctx_getter( + new TestURLRequestContextGetter()); scoped_refptr<HttpBridge> http_bridge(new ShuntedHttpBridge( - ctx, io_thread_loop(), this)); + ctx_getter, io_thread_loop(), this)); http_bridge->SetUserAgent("bob"); http_bridge->SetURL("http://www.google.com", 9999); http_bridge->SetPostPayload("text/plain", 2, " "); diff --git a/chrome/browser/sync/glue/sync_backend_host.cc b/chrome/browser/sync/glue/sync_backend_host.cc index 8432381..4c38711 100644 --- a/chrome/browser/sync/glue/sync_backend_host.cc +++ b/chrome/browser/sync/glue/sync_backend_host.cc @@ -40,8 +40,9 @@ SyncBackendHost::~SyncBackendHost() { DCHECK(!core_ && !frontend_) << "Must call Shutdown before destructor."; } -void SyncBackendHost::Initialize(const GURL& sync_service_url, - URLRequestContext* baseline_context) { +void SyncBackendHost::Initialize( + const GURL& sync_service_url, + URLRequestContextGetter* baseline_context_getter) { if (!core_thread_.Start()) return; bookmark_model_worker_ = new BookmarkModelWorker(frontend_loop_); @@ -49,8 +50,8 @@ void SyncBackendHost::Initialize(const GURL& sync_service_url, core_thread_.message_loop()->PostTask(FROM_HERE, NewRunnableMethod(core_.get(), &SyncBackendHost::Core::DoInitialize, sync_service_url, bookmark_model_worker_, true, - new HttpBridgeFactory(baseline_context), - new HttpBridgeFactory(baseline_context))); + new HttpBridgeFactory(baseline_context_getter), + new HttpBridgeFactory(baseline_context_getter))); } void SyncBackendHost::Authenticate(const std::string& username, diff --git a/chrome/browser/sync/glue/sync_backend_host.h b/chrome/browser/sync/glue/sync_backend_host.h index 3fad2c7..f0a1cd4 100644 --- a/chrome/browser/sync/glue/sync_backend_host.h +++ b/chrome/browser/sync/glue/sync_backend_host.h @@ -15,11 +15,11 @@ #include "base/ref_counted.h" #include "base/thread.h" #include "base/timer.h" +#include "chrome/browser/net/url_request_context_getter.h" #include "chrome/browser/sync/auth_error_state.h" #include "chrome/browser/sync/engine/syncapi.h" #include "chrome/browser/sync/glue/bookmark_model_worker.h" #include "googleurl/src/gurl.h" -#include "net/url_request/url_request_context.h" namespace browser_sync { @@ -85,7 +85,8 @@ class SyncBackendHost { ~SyncBackendHost(); // Called on |frontend_loop_| to kick off asynchronous initialization. - void Initialize(const GURL& service_url, URLRequestContext* baseline_context); + void Initialize(const GURL& service_url, + URLRequestContextGetter* baseline_context_getter); // Called on |frontend_loop_| to kick off asynchronous authentication. void Authenticate(const std::string& username, const std::string& password); |