diff options
author | tburkard@chromium.org <tburkard@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-07-30 20:18:22 +0000 |
---|---|---|
committer | tburkard@chromium.org <tburkard@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-07-30 20:18:22 +0000 |
commit | 5a07c19cb57f297222a4bf036f2995b194223b2d (patch) | |
tree | 1a465cd26a6516730864793af195663390e7e7df | |
parent | 109acb8db570f1a9958b70f5284699ea0c18b036 (diff) | |
download | chromium_src-5a07c19cb57f297222a4bf036f2995b194223b2d.zip chromium_src-5a07c19cb57f297222a4bf036f2995b194223b2d.tar.gz chromium_src-5a07c19cb57f297222a4bf036f2995b194223b2d.tar.bz2 |
Adding histograms showing fraction of page load times spent in the disk cache, for full and partial page loads.
R=mmenke@chromium.org, jam@chromium.org, willchan@chromium.org, brettw@chromium.org
BUG=139210
Review URL: https://chromiumcodereview.appspot.com/10736066
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@149007 0039d316-1c4b-4281-b951-d872f2087c98
49 files changed, 940 insertions, 117 deletions
diff --git a/chrome/browser/extensions/api/web_request/web_request_api_unittest.cc b/chrome/browser/extensions/api/web_request/web_request_api_unittest.cc index 756566a..175926a 100644 --- a/chrome/browser/extensions/api/web_request/web_request_api_unittest.cc +++ b/chrome/browser/extensions/api/web_request/web_request_api_unittest.cc @@ -127,7 +127,8 @@ class ExtensionWebRequestTest : public testing::Test { prefs::kEnableReferrers, profile_.GetTestingPrefService(), NULL); network_delegate_.reset(new ChromeNetworkDelegate( event_router_.get(), NULL, NULL, &profile_, - CookieSettings::Factory::GetForProfile(&profile_), &enable_referrers_)); + CookieSettings::Factory::GetForProfile(&profile_), &enable_referrers_, + NULL)); context_.reset(new TestURLRequestContext(true)); context_->set_network_delegate(network_delegate_.get()); context_->Init(); @@ -441,7 +442,8 @@ class ExtensionWebRequestHeaderModificationTest : prefs::kEnableReferrers, profile_.GetTestingPrefService(), NULL); network_delegate_.reset(new ChromeNetworkDelegate( event_router_.get(), NULL, NULL, &profile_, - CookieSettings::Factory::GetForProfile(&profile_), &enable_referrers_)); + CookieSettings::Factory::GetForProfile(&profile_), &enable_referrers_, + NULL)); context_.reset(new TestURLRequestContext(true)); host_resolver_.reset(new net::MockHostResolver()); host_resolver_->rules()->AddSimulatedFailure("doesnotexist"); diff --git a/chrome/browser/io_thread.cc b/chrome/browser/io_thread.cc index 6aad7d2..5ada21b 100644 --- a/chrome/browser/io_thread.cc +++ b/chrome/browser/io_thread.cc @@ -21,6 +21,7 @@ #include "build/build_config.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/extensions/event_router_forwarder.h" +#include "chrome/browser/net/cache_stats.h" #include "chrome/browser/net/chrome_net_log.h" #include "chrome/browser/net/chrome_network_delegate.h" #include "chrome/browser/net/chrome_url_request_context.h" @@ -402,7 +403,8 @@ void IOThread::Init() { NULL, NULL, NULL, - &system_enable_referrers_); + &system_enable_referrers_, + NULL); if (CommandLine::ForCurrentProcess()->HasSwitch( switches::kDisableExtensionsHttpThrottling)) { network_delegate->NeverThrottleRequests(); @@ -426,6 +428,7 @@ void IOThread::Init() { new net::ServerBoundCertService( new net::DefaultServerBoundCertStore(NULL), base::WorkerPool::GetTaskRunner(true))); + globals_->cache_stats.reset(new chrome_browser_net::CacheStats()); net::HttpNetworkSession::Params session_params; session_params.host_resolver = globals_->host_resolver.get(); session_params.cert_verifier = globals_->cert_verifier.get(); diff --git a/chrome/browser/io_thread.h b/chrome/browser/io_thread.h index e4e4faf..aa9cc0c 100644 --- a/chrome/browser/io_thread.h +++ b/chrome/browser/io_thread.h @@ -24,6 +24,7 @@ class PrefService; class SystemURLRequestContextGetter; namespace chrome_browser_net { +class CacheStats; class HttpPipeliningCompatibilityClient; } @@ -111,6 +112,7 @@ class IOThread : public content::BrowserThreadDelegate { extension_event_router_forwarder; scoped_ptr<chrome_browser_net::HttpPipeliningCompatibilityClient> http_pipelining_compatibility_client; + scoped_ptr<chrome_browser_net::CacheStats> cache_stats; }; // |net_log| must either outlive the IOThread or be NULL. diff --git a/chrome/browser/net/cache_stats.cc b/chrome/browser/net/cache_stats.cc new file mode 100644 index 0000000..68cb96f --- /dev/null +++ b/chrome/browser/net/cache_stats.cc @@ -0,0 +1,342 @@ +// Copyright (c) 2012 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/cache_stats.h" + +#include "base/metrics/histogram.h" +#include "base/stl_util.h" +#include "base/string_number_conversions.h" +#include "base/timer.h" +#include "chrome/browser/browser_process.h" +#include "chrome/browser/io_thread.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/tab_contents/tab_contents.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/browser/render_process_host.h" +#include "content/public/browser/render_view_host.h" +#include "content/public/browser/resource_request_info.h" +#include "content/public/browser/web_contents.h" +#include "net/url_request/url_request.h" + +using content::BrowserThread; +using content::RenderViewHost; +using content::ResourceRequestInfo; + +#if defined(COMPILER_GCC) + +namespace BASE_HASH_NAMESPACE { +template <> +struct hash<const net::URLRequest*> { + std::size_t operator()(const net::URLRequest* value) const { + return reinterpret_cast<std::size_t>(value); + } +}; +} + +#endif + +namespace { + +bool GetRenderView(const net::URLRequest& request, + int* process_id, int* route_id) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(&request); + if (!info) + return false; + return info->GetAssociatedRenderView(process_id, route_id); +} + +void CallCacheStatsTabEventOnIOThread( + std::pair<int, int> render_view_id, + chrome_browser_net::CacheStats::TabEvent event, + IOThread* io_thread) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + if (io_thread) + io_thread->globals()->cache_stats->OnTabEvent(render_view_id, event); +} + +// Times after a load has started at which stats are collected. +const int kStatsCollectionTimesMs[] = { + 500, + 1000, + 2000, + 3000, + 4000, + 5000, + 7500, + 10000, + 15000, + 20000 +}; + +static int kTabLoadStatsAutoCleanupTimeoutSeconds = 30; + +} // namespace + +namespace chrome_browser_net { + +// Helper struct keeping stats about the page load progress & cache usage +// stats during the pageload so far for a given RenderView, identified +// by a pair of process id and route id. +struct CacheStats::TabLoadStats { + TabLoadStats(std::pair<int, int> render_view_id, CacheStats* owner) + : render_view_id(render_view_id), + num_active(0), + spinner_started(false), + next_timer_index(0), + timer(false, false) { + // Initialize the timer to do an automatic cleanup. If a pageload is + // started for the TabLoadStats within that timeframe, CacheStats + // will start using the timer, thereby cancelling the cleanup. + // Once CacheStats starts the timer, the object is guaranteed to be + // destroyed eventually, so there is no more need for automatic cleanup at + // that point. + timer.Start(FROM_HERE, + base::TimeDelta::FromSeconds( + kTabLoadStatsAutoCleanupTimeoutSeconds), + base::Bind(&CacheStats::RemoveTabLoadStats, + base::Unretained(owner), + render_view_id)); + } + + std::pair<int, int> render_view_id; + int num_active; + bool spinner_started; + base::TimeTicks load_start_time; + base::TimeTicks cache_start_time; + base::TimeDelta cache_total_time; + int next_timer_index; + base::Timer timer; + // URLRequest's for which there are outstanding cache transactions. + base::hash_set<const net::URLRequest*> active_requests; +}; + +CacheStatsTabHelper::CacheStatsTabHelper(TabContents* tab) + : content::WebContentsObserver(tab->web_contents()), + cache_stats_(NULL) { + is_otr_profile_ = tab->profile()->IsOffTheRecord(); +} + +CacheStatsTabHelper::~CacheStatsTabHelper() { +} + +void CacheStatsTabHelper::DidStartProvisionalLoadForFrame( + int64 frame_id, + bool is_main_frame, + const GURL& validated_url, + bool is_error_page, + content::RenderViewHost* render_view_host) { + if (!is_main_frame) + return; + if (!validated_url.SchemeIs("http")) + return; + NotifyCacheStats(CacheStats::SPINNER_START, render_view_host); +} + +void CacheStatsTabHelper::DidStopLoading(RenderViewHost* render_view_host) { + NotifyCacheStats(CacheStats::SPINNER_STOP, render_view_host); +} + +void CacheStatsTabHelper::NotifyCacheStats( + CacheStats::TabEvent event, + RenderViewHost* render_view_host) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + if (is_otr_profile_) + return; + int process_id = render_view_host->GetProcess()->GetID(); + int route_id = render_view_host->GetRoutingID(); + BrowserThread::PostTask( + BrowserThread::IO, FROM_HERE, + base::Bind(&CallCacheStatsTabEventOnIOThread, + std::pair<int, int>(process_id, route_id), + event, + base::Unretained(g_browser_process->io_thread()))); +} + +CacheStats::CacheStats() { + for (int i = 0; + i < static_cast<int>(arraysize(kStatsCollectionTimesMs)); + i++) { + final_histograms_.push_back( + base::LinearHistogram::FactoryGet( + "CacheStats.FractionCacheUseFinalPLT_" + + base::IntToString(kStatsCollectionTimesMs[i]), + 0, 101, 102, base::Histogram::kUmaTargetedHistogramFlag)); + intermediate_histograms_.push_back( + base::LinearHistogram::FactoryGet( + "DiskCache.FractionCacheUseIntermediatePLT_" + + base::IntToString(kStatsCollectionTimesMs[i]), + 0, 101, 102, base::Histogram::kNoFlags)); + } + DCHECK_EQ(final_histograms_.size(), arraysize(kStatsCollectionTimesMs)); + DCHECK_EQ(intermediate_histograms_.size(), + arraysize(kStatsCollectionTimesMs)); +} + +CacheStats::~CacheStats() { + STLDeleteValues(&tab_load_stats_); +} + +CacheStats::TabLoadStats* CacheStats::GetTabLoadStats( + std::pair<int, int> render_view_id) { + TabLoadStatsMap::const_iterator it = tab_load_stats_.find(render_view_id); + if (it != tab_load_stats_.end()) + return it->second; + TabLoadStats* new_tab_load_stats = new TabLoadStats(render_view_id, this); + tab_load_stats_[render_view_id] = new_tab_load_stats; + return new_tab_load_stats; +} + +void CacheStats::RemoveTabLoadStats(std::pair<int, int> render_view_id) { + TabLoadStatsMap::iterator it = tab_load_stats_.find(render_view_id); + if (it != tab_load_stats_.end()) { + delete it->second; + tab_load_stats_.erase(it); + } +} + +void CacheStats::OnCacheWaitStateChange( + const net::URLRequest& request, + net::NetworkDelegate::CacheWaitState state) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + if (main_request_contexts_.count(request.context()) < 1) + return; + int process_id, route_id; + if (!GetRenderView(request, &process_id, &route_id)) + return; + TabLoadStats* stats = + GetTabLoadStats(std::pair<int, int>(process_id, route_id)); + bool newly_started = false; + bool newly_finished = false; + switch (state) { + case net::NetworkDelegate::CACHE_WAIT_STATE_START: + DCHECK(stats->active_requests.count(&request) == 0); + newly_started = true; + stats->active_requests.insert(&request); + break; + case net::NetworkDelegate::CACHE_WAIT_STATE_FINISH: + if (stats->active_requests.count(&request) > 0) { + stats->active_requests.erase(&request); + newly_finished = true; + } + break; + case net::NetworkDelegate::CACHE_WAIT_STATE_RESET: + if (stats->active_requests.count(&request) > 0) { + stats->active_requests.erase(&request); + newly_finished = true; + } + break; + } + DCHECK_GE(stats->num_active, 0); + if (newly_started) { + DCHECK(!newly_finished); + if (stats->num_active == 0) { + stats->cache_start_time = base::TimeTicks::Now(); + } + stats->num_active++; + } + if (newly_finished) { + DCHECK(!newly_started); + if (stats->num_active == 1) { + stats->cache_total_time += + base::TimeTicks::Now() - stats->cache_start_time; + } + stats->num_active--; + } + DCHECK_GE(stats->num_active, 0); +} + +void CacheStats::OnTabEvent(std::pair<int, int> render_view_id, + TabEvent event) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + TabLoadStats* stats = GetTabLoadStats(render_view_id); + if (event == SPINNER_START) { + stats->spinner_started = true; + stats->cache_total_time = base::TimeDelta(); + stats->cache_start_time = base::TimeTicks::Now(); + stats->load_start_time = base::TimeTicks::Now(); + stats->next_timer_index = 0; + ScheduleTimer(stats); + } else { + DCHECK_EQ(event, SPINNER_STOP); + if (stats->spinner_started) { + stats->spinner_started = false; + base::TimeDelta load_time = + base::TimeTicks::Now() - stats->load_start_time; + if (stats->num_active > 1) + stats->cache_total_time += + base::TimeTicks::Now() - stats->cache_start_time; + RecordCacheFractionHistogram(load_time, stats->cache_total_time, true, + stats->next_timer_index); + } + RemoveTabLoadStats(render_view_id); + } +} + +void CacheStats::ScheduleTimer(TabLoadStats* stats) { + int timer_index = stats->next_timer_index; + DCHECK(timer_index >= 0 && + timer_index < static_cast<int>(arraysize(kStatsCollectionTimesMs))); + base::TimeDelta delta = + base::TimeDelta::FromMilliseconds(kStatsCollectionTimesMs[timer_index]); + delta -= base::TimeTicks::Now() - stats->load_start_time; + stats->timer.Start(FROM_HERE, + delta, + base::Bind(&CacheStats::TimerCallback, + base::Unretained(this), + base::Unretained(stats))); +} + +void CacheStats::TimerCallback(TabLoadStats* stats) { + DCHECK(stats->spinner_started); + base::TimeDelta load_time = base::TimeTicks::Now() - stats->load_start_time; + base::TimeDelta cache_time = stats->cache_total_time; + if (stats->num_active > 1) + cache_time += base::TimeTicks::Now() - stats->cache_start_time; + RecordCacheFractionHistogram(load_time, cache_time, false, + stats->next_timer_index); + stats->next_timer_index++; + if (stats->next_timer_index < + static_cast<int>(arraysize(kStatsCollectionTimesMs))) { + ScheduleTimer(stats); + } else { + RemoveTabLoadStats(stats->render_view_id); + } +} + +void CacheStats::RecordCacheFractionHistogram(base::TimeDelta elapsed, + base::TimeDelta cache_time, + bool is_load_done, + int timer_index) { + DCHECK(timer_index >= 0 && + timer_index < static_cast<int>(arraysize(kStatsCollectionTimesMs))); + + if (elapsed.InMilliseconds() <= 0) + return; + + int64 cache_fraction_percentage = + 100 * cache_time.InMilliseconds() / elapsed.InMilliseconds(); + + DCHECK(cache_fraction_percentage >= 0 && cache_fraction_percentage <= 100); + + if (is_load_done) { + final_histograms_[timer_index]->Add(cache_fraction_percentage); + } else { + intermediate_histograms_[timer_index]->Add(cache_fraction_percentage); + } +} + +void CacheStats::RegisterURLRequestContext( + const net::URLRequestContext* context, + ChromeURLRequestContext::ContextType type) { + if (type == ChromeURLRequestContext::CONTEXT_TYPE_MAIN) + main_request_contexts_.insert(context); +} + +void CacheStats::UnregisterURLRequestContext( + const net::URLRequestContext* context) { + main_request_contexts_.erase(context); +} + +} // namespace chrome_browser_net diff --git a/chrome/browser/net/cache_stats.h b/chrome/browser/net/cache_stats.h new file mode 100644 index 0000000..a3db95b --- /dev/null +++ b/chrome/browser/net/cache_stats.h @@ -0,0 +1,127 @@ +// Copyright (c) 2012 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_CACHE_STATS_H_ +#define CHROME_BROWSER_NET_CACHE_STATS_H_ + +#include <map> +#include <vector> + +#include "base/basictypes.h" +#include "base/compiler_specific.h" +#include "base/hash_tables.h" +#include "base/memory/scoped_ptr.h" +#include "base/message_loop.h" +#include "base/time.h" +#include "chrome/browser/net/chrome_url_request_context.h" +#include "content/public/browser/web_contents_observer.h" +#include "net/base/network_delegate.h" + +class TabContents; + +namespace base { +class Histogram; +} + +namespace net { +class URLRequest; +class URLRequestContext; +} + +#if defined(COMPILER_GCC) + +namespace BASE_HASH_NAMESPACE { +template <> +struct hash<const net::URLRequestContext*> { + std::size_t operator()(const net::URLRequestContext* value) const { + return reinterpret_cast<std::size_t>(value); + } +}; +} + +#endif + +namespace chrome_browser_net { + +// This class collects UMA stats about cache performance. +class CacheStats { + public: + enum TabEvent { + SPINNER_START, + SPINNER_STOP + }; + CacheStats(); + ~CacheStats(); + + void OnCacheWaitStateChange(const net::URLRequest& request, + net::NetworkDelegate::CacheWaitState state); + void OnTabEvent(std::pair<int, int> render_view_id, TabEvent event); + void RegisterURLRequestContext(const net::URLRequestContext* context, + ChromeURLRequestContext::ContextType type); + void UnregisterURLRequestContext(const net::URLRequestContext* context); + + private: + struct TabLoadStats; + // A map mapping a renderer's process id and route id to a TabLoadStats, + // representing that renderer's load statistics. + typedef std::map<std::pair<int, int>, TabLoadStats*> TabLoadStatsMap; + + // Gets TabLoadStats for a given RenderView. + TabLoadStats* GetTabLoadStats(std::pair<int, int> render_view_id); + // Deletes TabLoadStats no longer needed for a render view. + void RemoveTabLoadStats(std::pair<int, int> render_view_id); + // Sets a timer for a given tab to collect stats. |timer_index| indicates + // how many times stats have been collected since the navigation has started + // for this tab. + void ScheduleTimer(TabLoadStats* stats); + // The callback when a timer fires to collect stats again. + void TimerCallback(TabLoadStats* stats); + // Helper function to put the current set of cache statistics into an UMA + // histogram. + void RecordCacheFractionHistogram(base::TimeDelta elapsed, + base::TimeDelta cache_time, + bool is_load_done, + int timer_index); + + TabLoadStatsMap tab_load_stats_; + std::vector<base::Histogram*> final_histograms_; + std::vector<base::Histogram*> intermediate_histograms_; + base::hash_set<const net::URLRequestContext*> main_request_contexts_; + + DISALLOW_COPY_AND_ASSIGN(CacheStats); +}; + +// A WebContentsObserver watching all tabs, notifying CacheStats +// whenever the spinner starts or stops for a given tab, and when a renderer +// is no longer used. +class CacheStatsTabHelper : public content::WebContentsObserver { + public: + explicit CacheStatsTabHelper(TabContents* tab); + virtual ~CacheStatsTabHelper(); + + // content::WebContentsObserver implementation + virtual void DidStartProvisionalLoadForFrame( + int64 frame_id, + bool is_main_frame, + const GURL& validated_url, + bool is_error_page, + content::RenderViewHost* render_view_host) OVERRIDE; + virtual void DidStopLoading( + content::RenderViewHost* render_view_host) OVERRIDE; + + private: + // Calls into CacheStats to notify that a reportable event has occurred + // for the tab being observed. + void NotifyCacheStats(CacheStats::TabEvent event, + content::RenderViewHost* render_view_host); + + CacheStats* cache_stats_; + bool is_otr_profile_; + + DISALLOW_COPY_AND_ASSIGN(CacheStatsTabHelper); +}; + +} // namespace chrome_browser_net + +#endif // CHROME_BROWSER_NET_CACHE_STATS_H_ diff --git a/chrome/browser/net/chrome_fraudulent_certificate_reporter_unittest.cc b/chrome/browser/net/chrome_fraudulent_certificate_reporter_unittest.cc index 7dc092a..3246553 100644 --- a/chrome/browser/net/chrome_fraudulent_certificate_reporter_unittest.cc +++ b/chrome/browser/net/chrome_fraudulent_certificate_reporter_unittest.cc @@ -121,7 +121,7 @@ class NotSendingTestReporter : public TestReporter { // This class doesn't do anything now, but in near future versions it will. class MockURLRequest : public net::URLRequest { public: - MockURLRequest(net::URLRequestContext* context) + explicit MockURLRequest(net::URLRequestContext* context) : net::URLRequest(GURL(""), NULL, context) { } @@ -152,21 +152,24 @@ class MockReporter : public ChromeFraudulentCertificateReporter { }; static void DoReportIsSent() { - ChromeURLRequestContext context; + ChromeURLRequestContext context(ChromeURLRequestContext::CONTEXT_TYPE_MAIN, + NULL); SendingTestReporter reporter(&context); SSLInfo info = GetGoodSSLInfo(); reporter.SendReport("mail.google.com", info, true); } static void DoReportIsNotSent() { - ChromeURLRequestContext context; + ChromeURLRequestContext context(ChromeURLRequestContext::CONTEXT_TYPE_MAIN, + NULL); NotSendingTestReporter reporter(&context); SSLInfo info = GetBadSSLInfo(); reporter.SendReport("www.example.com", info, true); } static void DoMockReportIsSent() { - ChromeURLRequestContext context; + ChromeURLRequestContext context(ChromeURLRequestContext::CONTEXT_TYPE_MAIN, + NULL); MockReporter reporter(&context); SSLInfo info = GetGoodSSLInfo(); reporter.SendReport("mail.google.com", info, true); diff --git a/chrome/browser/net/chrome_network_delegate.cc b/chrome/browser/net/chrome_network_delegate.cc index 207bb08..0295195 100644 --- a/chrome/browser/net/chrome_network_delegate.cc +++ b/chrome/browser/net/chrome_network_delegate.cc @@ -14,6 +14,7 @@ #include "chrome/browser/extensions/event_router_forwarder.h" #include "chrome/browser/extensions/extension_info_map.h" #include "chrome/browser/extensions/extension_process_manager.h" +#include "chrome/browser/net/cache_stats.h" #include "chrome/browser/prefs/pref_member.h" #include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/task_manager/task_manager.h" @@ -126,14 +127,16 @@ ChromeNetworkDelegate::ChromeNetworkDelegate( const policy::URLBlacklistManager* url_blacklist_manager, void* profile, CookieSettings* cookie_settings, - BooleanPrefMember* enable_referrers) + BooleanPrefMember* enable_referrers, + chrome_browser_net::CacheStats* cache_stats) : event_router_(event_router), profile_(profile), cookie_settings_(cookie_settings), extension_info_map_(extension_info_map), enable_referrers_(enable_referrers), never_throttle_requests_(false), - url_blacklist_manager_(url_blacklist_manager) { + url_blacklist_manager_(url_blacklist_manager), + cache_stats_(cache_stats) { DCHECK(event_router); DCHECK(enable_referrers); DCHECK(!profile || cookie_settings); @@ -389,3 +392,10 @@ int ChromeNetworkDelegate::OnBeforeSocketStreamConnect( #endif return net::OK; } + +void ChromeNetworkDelegate::OnCacheWaitStateChange( + const net::URLRequest& request, + CacheWaitState state) { + if (cache_stats_) + cache_stats_->OnCacheWaitStateChange(request, state); +} diff --git a/chrome/browser/net/chrome_network_delegate.h b/chrome/browser/net/chrome_network_delegate.h index 8cf28d6..a5fb87d 100644 --- a/chrome/browser/net/chrome_network_delegate.h +++ b/chrome/browser/net/chrome_network_delegate.h @@ -17,6 +17,10 @@ template<class T> class PrefMember; typedef PrefMember<bool> BooleanPrefMember; +namespace chrome_browser_net { +class CacheStats; +} + namespace extensions { class EventRouterForwarder; } @@ -41,7 +45,8 @@ class ChromeNetworkDelegate : public net::NetworkDelegate { const policy::URLBlacklistManager* url_blacklist_manager, void* profile, CookieSettings* cookie_settings, - BooleanPrefMember* enable_referrers); + BooleanPrefMember* enable_referrers, + chrome_browser_net::CacheStats* cache_stats); virtual ~ChromeNetworkDelegate(); // Causes |OnCanThrottleRequest| to never return true. @@ -98,6 +103,8 @@ class ChromeNetworkDelegate : public net::NetworkDelegate { virtual int OnBeforeSocketStreamConnect( net::SocketStream* stream, const net::CompletionCallback& callback) OVERRIDE; + virtual void OnCacheWaitStateChange(const net::URLRequest& request, + CacheWaitState state) OVERRIDE; scoped_refptr<extensions::EventRouterForwarder> event_router_; void* profile_; @@ -117,6 +124,9 @@ class ChromeNetworkDelegate : public net::NetworkDelegate { // When true, allow access to all file:// URLs. static bool g_allow_file_access_; + // Pointer to IOThread global, should outlive ChromeNetworkDelegate. + chrome_browser_net::CacheStats* cache_stats_; + DISALLOW_COPY_AND_ASSIGN(ChromeNetworkDelegate); }; diff --git a/chrome/browser/net/chrome_url_request_context.cc b/chrome/browser/net/chrome_url_request_context.cc index 0b3d77d..ee067c8 100644 --- a/chrome/browser/net/chrome_url_request_context.cc +++ b/chrome/browser/net/chrome_url_request_context.cc @@ -10,6 +10,7 @@ #include "base/message_loop_proxy.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/io_thread.h" +#include "chrome/browser/net/cache_stats.h" #include "chrome/browser/prefs/pref_service.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_io_data.h" @@ -290,14 +291,21 @@ void ChromeURLRequestContextGetter::OnDefaultCharsetChange( // ChromeURLRequestContext // ---------------------------------------------------------------------------- -ChromeURLRequestContext::ChromeURLRequestContext() +ChromeURLRequestContext::ChromeURLRequestContext( + ContextType type, + chrome_browser_net::CacheStats* cache_stats) : ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)), - is_incognito_(false) { + is_incognito_(false), + cache_stats_(cache_stats) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + if (cache_stats_) + cache_stats_->RegisterURLRequestContext(this, type); } ChromeURLRequestContext::~ChromeURLRequestContext() { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + if (cache_stats_) + cache_stats_->UnregisterURLRequestContext(this); } void ChromeURLRequestContext::CopyFrom(ChromeURLRequestContext* other) { diff --git a/chrome/browser/net/chrome_url_request_context.h b/chrome/browser/net/chrome_url_request_context.h index 61345e1..83f8037 100644 --- a/chrome/browser/net/chrome_url_request_context.h +++ b/chrome/browser/net/chrome_url_request_context.h @@ -20,6 +20,10 @@ class IOThread; class Profile; class ProfileIOData; +namespace chrome_browser_net { +class CacheStats; +} + // Subclass of net::URLRequestContext which can be used to store extra // information for requests. // @@ -27,7 +31,14 @@ class ProfileIOData; // including the constructor and destructor. class ChromeURLRequestContext : public net::URLRequestContext { public: - ChromeURLRequestContext(); + enum ContextType { + CONTEXT_TYPE_MAIN, + CONTEXT_TYPE_MEDIA, + CONTEXT_TYPE_EXTENSIONS, + CONTEXT_TYPE_APP + }; + ChromeURLRequestContext(ContextType type, + chrome_browser_net::CacheStats* cache_stats); virtual ~ChromeURLRequestContext(); base::WeakPtr<ChromeURLRequestContext> GetWeakPtr() { @@ -70,6 +81,7 @@ class ChromeURLRequestContext : public net::URLRequestContext { ChromeURLDataManagerBackend* chrome_url_data_manager_backend_; bool is_incognito_; + chrome_browser_net::CacheStats* cache_stats_; // --------------------------------------------------------------------------- // Important: When adding any new members above, consider whether they need to diff --git a/chrome/browser/profiles/off_the_record_profile_io_data.cc b/chrome/browser/profiles/off_the_record_profile_io_data.cc index 830d6df..471bac3 100644 --- a/chrome/browser/profiles/off_the_record_profile_io_data.cc +++ b/chrome/browser/profiles/off_the_record_profile_io_data.cc @@ -272,7 +272,7 @@ ChromeURLRequestContext* OffTheRecordProfileIOData::InitializeAppRequestContext( ChromeURLRequestContext* main_context, const std::string& app_id) const { - AppRequestContext* context = new AppRequestContext; + AppRequestContext* context = new AppRequestContext(cache_stats()); // Copy most state from the main context. context->CopyFrom(main_context); @@ -320,3 +320,7 @@ void OffTheRecordProfileIOData::CreateFtpProtocolHandler( network_delegate(), ftp_factory_.get(), ftp_auth_cache)); } +chrome_browser_net::CacheStats* OffTheRecordProfileIOData::GetCacheStats( + IOThread::Globals* io_thread_globals) const { + return NULL; +} diff --git a/chrome/browser/profiles/off_the_record_profile_io_data.h b/chrome/browser/profiles/off_the_record_profile_io_data.h index c939932..984e8c6 100644 --- a/chrome/browser/profiles/off_the_record_profile_io_data.h +++ b/chrome/browser/profiles/off_the_record_profile_io_data.h @@ -110,6 +110,9 @@ class OffTheRecordProfileIOData : public ProfileIOData { void CreateFtpProtocolHandler(net::URLRequestJobFactory* job_factory, net::FtpAuthCache* ftp_auth_cache) const; + virtual chrome_browser_net::CacheStats* GetCacheStats( + IOThread::Globals* io_thread_globals) const OVERRIDE; + mutable scoped_ptr<net::HttpServerPropertiesImpl> http_server_properties_; mutable scoped_ptr<net::HttpTransactionFactory> main_http_factory_; diff --git a/chrome/browser/profiles/profile_impl_io_data.cc b/chrome/browser/profiles/profile_impl_io_data.cc index 8bf761e..d757e86 100644 --- a/chrome/browser/profiles/profile_impl_io_data.cc +++ b/chrome/browser/profiles/profile_impl_io_data.cc @@ -267,7 +267,8 @@ void ProfileImplIOData::LazyInitializeInternal( ProfileParams* profile_params) const { ChromeURLRequestContext* main_context = main_request_context(); ChromeURLRequestContext* extensions_context = extensions_request_context(); - media_request_context_.reset(new ChromeURLRequestContext); + media_request_context_.reset(new ChromeURLRequestContext( + ChromeURLRequestContext::CONTEXT_TYPE_MEDIA, cache_stats())); IOThread* const io_thread = profile_params->io_thread; IOThread::Globals* const io_thread_globals = io_thread->globals(); @@ -477,7 +478,7 @@ ChromeURLRequestContext* ProfileImplIOData::InitializeAppRequestContext( ChromeURLRequestContext* main_context, const std::string& app_id) const { - AppRequestContext* context = new AppRequestContext; + AppRequestContext* context = new AppRequestContext(cache_stats()); // If this is for a guest process, we should not persist cookies and http // cache. @@ -564,6 +565,11 @@ ProfileImplIOData::AcquireIsolatedAppRequestContext( return app_request_context; } +chrome_browser_net::CacheStats* ProfileImplIOData::GetCacheStats( + IOThread::Globals* io_thread_globals) const { + return io_thread_globals->cache_stats.get(); +} + void ProfileImplIOData::CreateFtpProtocolHandler( net::URLRequestJobFactory* job_factory, net::FtpAuthCache* ftp_auth_cache) const { diff --git a/chrome/browser/profiles/profile_impl_io_data.h b/chrome/browser/profiles/profile_impl_io_data.h index 5435063..e7ef8f2 100644 --- a/chrome/browser/profiles/profile_impl_io_data.h +++ b/chrome/browser/profiles/profile_impl_io_data.h @@ -139,6 +139,8 @@ class ProfileImplIOData : public ProfileIOData { AcquireIsolatedAppRequestContext( ChromeURLRequestContext* main_context, const std::string& app_id) const OVERRIDE; + virtual chrome_browser_net::CacheStats* GetCacheStats( + IOThread::Globals* io_thread_globals) const OVERRIDE; void CreateFtpProtocolHandler(net::URLRequestJobFactory* job_factory, net::FtpAuthCache* ftp_auth_cache) const; diff --git a/chrome/browser/profiles/profile_io_data.cc b/chrome/browser/profiles/profile_io_data.cc index 12fec63..4277fd3 100644 --- a/chrome/browser/profiles/profile_io_data.cc +++ b/chrome/browser/profiles/profile_io_data.cc @@ -28,6 +28,7 @@ #include "chrome/browser/extensions/extension_resource_protocols.h" #include "chrome/browser/extensions/extension_system.h" #include "chrome/browser/io_thread.h" +#include "chrome/browser/net/cache_stats.h" #include "chrome/browser/net/chrome_cookie_notification_details.h" #include "chrome/browser/net/chrome_fraudulent_certificate_reporter.h" #include "chrome/browser/net/chrome_net_log.h" @@ -220,7 +221,11 @@ void ProfileIOData::InitializeOnUIThread(Profile* profile) { BrowserContext::EnsureResourceContextInitialized(profile); } -ProfileIOData::AppRequestContext::AppRequestContext() {} +ProfileIOData::AppRequestContext::AppRequestContext( + chrome_browser_net::CacheStats* cache_stats) + : ChromeURLRequestContext(ChromeURLRequestContext::CONTEXT_TYPE_APP, + cache_stats) { +} void ProfileIOData::AppRequestContext::SetCookieStore( net::CookieStore* cookie_store) { @@ -456,10 +461,16 @@ void ProfileIOData::LazyInitialize() const { IOThread* const io_thread = profile_params_->io_thread; IOThread::Globals* const io_thread_globals = io_thread->globals(); const CommandLine& command_line = *CommandLine::ForCurrentProcess(); + cache_stats_ = GetCacheStats(io_thread_globals); // Create the common request contexts. - main_request_context_.reset(new ChromeURLRequestContext); - extensions_request_context_.reset(new ChromeURLRequestContext); + main_request_context_.reset( + new ChromeURLRequestContext(ChromeURLRequestContext::CONTEXT_TYPE_MAIN, + cache_stats_)); + extensions_request_context_.reset( + new ChromeURLRequestContext( + ChromeURLRequestContext::CONTEXT_TYPE_EXTENSIONS, + cache_stats_)); chrome_url_data_manager_backend_.reset(new ChromeURLDataManagerBackend); @@ -469,7 +480,8 @@ void ProfileIOData::LazyInitialize() const { url_blacklist_manager_.get(), profile_params_->profile, profile_params_->cookie_settings, - &enable_referrers_)); + &enable_referrers_, + cache_stats_)); fraudulent_certificate_reporter_.reset( new chrome_browser_net::ChromeFraudulentCertificateReporter( diff --git a/chrome/browser/profiles/profile_io_data.h b/chrome/browser/profiles/profile_io_data.h index 6a900a3..ff5c463 100644 --- a/chrome/browser/profiles/profile_io_data.h +++ b/chrome/browser/profiles/profile_io_data.h @@ -14,6 +14,7 @@ #include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" #include "base/synchronization/lock.h" +#include "chrome/browser/io_thread.h" #include "chrome/browser/net/chrome_url_request_context.h" #include "chrome/browser/prefs/pref_member.h" #include "content/public/browser/resource_context.h" @@ -24,12 +25,12 @@ class CookieSettings; class DesktopNotificationService; class ExtensionInfoMap; class HostContentSettingsMap; -class IOThread; class Profile; class ProtocolHandlerRegistry; class TransportSecurityPersister; namespace chrome_browser_net { +class CacheStats; class HttpServerPropertiesManager; class ResourcePrefetchPredictorObserver; } @@ -136,7 +137,7 @@ class ProfileIOData { protected: class AppRequestContext : public ChromeURLRequestContext { public: - AppRequestContext(); + explicit AppRequestContext(chrome_browser_net::CacheStats* cache_stats); void SetCookieStore(net::CookieStore* cookie_store); void SetHttpTransactionFactory(net::HttpTransactionFactory* http_factory); @@ -239,6 +240,10 @@ class ProfileIOData { return main_request_context_.get(); } + chrome_browser_net::CacheStats* cache_stats() const { + return cache_stats_; + } + // Destroys the ResourceContext first, to cancel any URLRequests that are // using it still, before we destroy the member variables that those // URLRequests may be accessing. @@ -291,6 +296,10 @@ class ProfileIOData { ChromeURLRequestContext* main_context, const std::string& app_id) const = 0; + // Returns the CacheStats object to be used for this profile. + virtual chrome_browser_net::CacheStats* GetCacheStats( + IOThread::Globals* io_thread_globals) const = 0; + // The order *DOES* matter for the majority of these member variables, so // don't move them around unless you know what you're doing! // General rules: @@ -364,6 +373,8 @@ class ProfileIOData { mutable scoped_ptr<chrome_browser_net::ResourcePrefetchPredictorObserver> resource_prefetch_predictor_observer_; + mutable chrome_browser_net::CacheStats* cache_stats_; + // TODO(jhawkins): Remove once crbug.com/102004 is fixed. bool initialized_on_UI_thread_; diff --git a/chrome/browser/ui/tab_contents/tab_contents.cc b/chrome/browser/ui/tab_contents/tab_contents.cc index 407ac05..aa24534 100644 --- a/chrome/browser/ui/tab_contents/tab_contents.cc +++ b/chrome/browser/ui/tab_contents/tab_contents.cc @@ -18,6 +18,7 @@ #include "chrome/browser/favicon/favicon_tab_helper.h" #include "chrome/browser/history/history_tab_helper.h" #include "chrome/browser/infobars/infobar_tab_helper.h" +#include "chrome/browser/net/cache_stats.h" #include "chrome/browser/omnibox_search_hint.h" #include "chrome/browser/password_manager/password_manager.h" #include "chrome/browser/password_manager/password_manager_delegate_impl.h" @@ -102,6 +103,8 @@ TabContents::TabContents(WebContents* contents) #endif blocked_content_tab_helper_.reset(new BlockedContentTabHelper(this)); bookmark_tab_helper_.reset(new BookmarkTabHelper(this)); + cache_stats_tab_helper_.reset( + new chrome_browser_net::CacheStatsTabHelper(this)); #if defined(ENABLE_CAPTIVE_PORTAL_DETECTION) captive_portal_tab_helper_.reset( new captive_portal::CaptivePortalTabHelper(profile(), web_contents())); diff --git a/chrome/browser/ui/tab_contents/tab_contents.h b/chrome/browser/ui/tab_contents/tab_contents.h index cef0962..e53ad96 100644 --- a/chrome/browser/ui/tab_contents/tab_contents.h +++ b/chrome/browser/ui/tab_contents/tab_contents.h @@ -65,6 +65,10 @@ class SearchTabHelper; } } +namespace chrome_browser_net { +class CacheStatsTabHelper; +} + namespace extensions { class TabHelper; class WebNavigationTabObserver; @@ -267,6 +271,7 @@ class TabContents : public content::WebContentsObserver { scoped_ptr<AutomationTabHelper> automation_tab_helper_; scoped_ptr<BlockedContentTabHelper> blocked_content_tab_helper_; scoped_ptr<BookmarkTabHelper> bookmark_tab_helper_; + scoped_ptr<chrome_browser_net::CacheStatsTabHelper> cache_stats_tab_helper_; #if defined(ENABLE_CAPTIVE_PORTAL_DETECTION) scoped_ptr<captive_portal::CaptivePortalTabHelper> captive_portal_tab_helper_; #endif diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index da49fac..4fe3047 100644 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -1450,6 +1450,8 @@ 'browser/metrics/variations_service.cc', 'browser/metrics/variations_service.h', 'browser/native_window_notification_source.h', + 'browser/net/cache_stats.cc', + 'browser/net/cache_stats.h', 'browser/net/chrome_cookie_notification_details.h', 'browser/net/chrome_fraudulent_certificate_reporter.cc', 'browser/net/chrome_fraudulent_certificate_reporter.h', diff --git a/content/shell/shell_network_delegate.cc b/content/shell/shell_network_delegate.cc index 1bf35fb..57886eb 100644 --- a/content/shell/shell_network_delegate.cc +++ b/content/shell/shell_network_delegate.cc @@ -97,4 +97,9 @@ int ShellNetworkDelegate::OnBeforeSocketStreamConnect( return net::OK; } +void ShellNetworkDelegate::OnCacheWaitStateChange( + const net::URLRequest& request, + CacheWaitState waiting) { +} + } // namespace content diff --git a/content/shell/shell_network_delegate.h b/content/shell/shell_network_delegate.h index da15ff8..a3e01bc 100644 --- a/content/shell/shell_network_delegate.h +++ b/content/shell/shell_network_delegate.h @@ -58,6 +58,8 @@ class ShellNetworkDelegate : public net::NetworkDelegate { virtual int OnBeforeSocketStreamConnect( net::SocketStream* stream, const net::CompletionCallback& callback) OVERRIDE; + virtual void OnCacheWaitStateChange(const net::URLRequest& request, + CacheWaitState state) OVERRIDE; DISALLOW_COPY_AND_ASSIGN(ShellNetworkDelegate); }; diff --git a/net/base/network_delegate.cc b/net/base/network_delegate.cc index 96e9a23..f52900c 100644 --- a/net/base/network_delegate.cc +++ b/net/base/network_delegate.cc @@ -127,4 +127,10 @@ int NetworkDelegate::NotifyBeforeSocketStreamConnect( return OnBeforeSocketStreamConnect(socket, callback); } +void NetworkDelegate::NotifyCacheWaitStateChange(const URLRequest& request, + CacheWaitState state) { + DCHECK(CalledOnValidThread()); + OnCacheWaitStateChange(request, state); +} + } // namespace net diff --git a/net/base/network_delegate.h b/net/base/network_delegate.h index 5ecd0f8..f3bc758 100644 --- a/net/base/network_delegate.h +++ b/net/base/network_delegate.h @@ -48,6 +48,12 @@ class NetworkDelegate : public base::NonThreadSafe { }; typedef base::Callback<void(AuthRequiredResponse)> AuthCallback; + enum CacheWaitState { + CACHE_WAIT_STATE_START, + CACHE_WAIT_STATE_FINISH, + CACHE_WAIT_STATE_RESET + }; + virtual ~NetworkDelegate() {} // Notification interface called by the network stack. Note that these @@ -90,6 +96,9 @@ class NetworkDelegate : public base::NonThreadSafe { int NotifyBeforeSocketStreamConnect(SocketStream* socket, const CompletionCallback& callback); + void NotifyCacheWaitStateChange(const URLRequest& request, + CacheWaitState state); + private: // This is the interface for subclasses of NetworkDelegate to implement. These // member functions will be called by the respective public notification @@ -214,6 +223,17 @@ class NetworkDelegate : public base::NonThreadSafe { // Called before a SocketStream tries to connect. virtual int OnBeforeSocketStreamConnect( SocketStream* socket, const CompletionCallback& callback) = 0; + + // Called when the completion of a URLRequest is blocking on a cache + // transaction (CACHE_WAIT_STATE_START), or when a URLRequest is no longer + // blocked on a cache transaction (CACHE_WAIT_STATE_FINISH), or when a + // URLRequest is reset (CACHE_WAIT_STATE_RESET), indicating + // cancellation of any pending cache waits for this request. Notice that + // START can be called several times for the same request. It is the + // responsibility of the delegate to keep track of the number of outstanding + // cache transactions. + virtual void OnCacheWaitStateChange(const URLRequest& request, + CacheWaitState state) = 0; }; } // namespace net diff --git a/net/http/http_cache.cc b/net/http/http_cache.cc index defc365..8579471 100644 --- a/net/http/http_cache.cc +++ b/net/http/http_cache.cc @@ -409,7 +409,7 @@ void HttpCache::WriteMetadata(const GURL& url, CreateBackend(NULL, net::CompletionCallback()); } - HttpCache::Transaction* trans = new HttpCache::Transaction(this); + HttpCache::Transaction* trans = new HttpCache::Transaction(this, NULL); MetadataWriter* writer = new MetadataWriter(trans); // The writer will self destruct when done. @@ -444,14 +444,15 @@ void HttpCache::OnExternalCacheHit(const GURL& url, disk_cache_->OnExternalCacheHit(key); } -int HttpCache::CreateTransaction(scoped_ptr<HttpTransaction>* trans) { +int HttpCache::CreateTransaction(scoped_ptr<HttpTransaction>* trans, + HttpTransactionDelegate* delegate) { // Do lazy initialization of disk cache if needed. if (!disk_cache_.get()) { // We don't care about the result. CreateBackend(NULL, net::CompletionCallback()); } - trans->reset(new HttpCache::Transaction(this)); + trans->reset(new HttpCache::Transaction(this, delegate)); return OK; } diff --git a/net/http/http_cache.h b/net/http/http_cache.h index f5c391e..4ff00b5 100644 --- a/net/http/http_cache.h +++ b/net/http/http_cache.h @@ -191,7 +191,8 @@ class NET_EXPORT HttpCache : public HttpTransactionFactory, void OnExternalCacheHit(const GURL& url, const std::string& http_method); // HttpTransactionFactory implementation: - virtual int CreateTransaction(scoped_ptr<HttpTransaction>* trans) OVERRIDE; + virtual int CreateTransaction(scoped_ptr<HttpTransaction>* trans, + HttpTransactionDelegate* delegate) OVERRIDE; virtual HttpCache* GetCache() OVERRIDE; virtual HttpNetworkSession* GetSession() OVERRIDE; diff --git a/net/http/http_cache_transaction.cc b/net/http/http_cache_transaction.cc index 652a3b2..c6a7c9f 100644 --- a/net/http/http_cache_transaction.cc +++ b/net/http/http_cache_transaction.cc @@ -31,6 +31,7 @@ #include "net/http/http_network_session.h" #include "net/http/http_request_info.h" #include "net/http/http_response_headers.h" +#include "net/http/http_transaction_delegate.h" #include "net/http/http_transaction.h" #include "net/http/http_util.h" #include "net/http/partial_data.h" @@ -101,7 +102,9 @@ static bool HeaderMatches(const HttpRequestHeaders& headers, //----------------------------------------------------------------------------- -HttpCache::Transaction::Transaction(HttpCache* cache) +HttpCache::Transaction::Transaction( + HttpCache* cache, + HttpTransactionDelegate* transaction_delegate) : next_state_(STATE_NONE), request_(NULL), cache_(cache->AsWeakPtr()), @@ -126,7 +129,8 @@ HttpCache::Transaction::Transaction(HttpCache* cache) ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)), ALLOW_THIS_IN_INITIALIZER_LIST(io_callback_( base::Bind(&Transaction::OnIOComplete, - weak_factory_.GetWeakPtr()))) { + weak_factory_.GetWeakPtr()))), + transaction_delegate_(transaction_delegate) { COMPILE_ASSERT(HttpCache::Transaction::kNumValidationHeaders == arraysize(kValidationHeaders), Invalid_number_of_validation_headers); @@ -654,11 +658,13 @@ int HttpCache::Transaction::DoGetBackend() { cache_pending_ = true; next_state_ = STATE_GET_BACKEND_COMPLETE; net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_GET_BACKEND); + ReportCacheActionStart(); return cache_->GetBackendForTransaction(this); } int HttpCache::Transaction::DoGetBackendComplete(int result) { DCHECK(result == OK || result == ERR_FAILED); + ReportCacheActionFinish(); net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_GET_BACKEND, result); cache_pending_ = false; @@ -719,7 +725,7 @@ int HttpCache::Transaction::DoSendRequest() { DCHECK(!network_trans_.get()); // Create a network transaction. - int rv = cache_->network_layer_->CreateTransaction(&network_trans_); + int rv = cache_->network_layer_->CreateTransaction(&network_trans_, NULL); if (rv != OK) return rv; @@ -847,6 +853,7 @@ int HttpCache::Transaction::DoOpenEntry() { next_state_ = STATE_OPEN_ENTRY_COMPLETE; cache_pending_ = true; net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_OPEN_ENTRY); + ReportCacheActionStart(); return cache_->OpenEntry(cache_key_, &new_entry_, this); } @@ -854,6 +861,7 @@ int HttpCache::Transaction::DoOpenEntryComplete(int result) { // It is important that we go to STATE_ADD_TO_ENTRY whenever the result is // OK, otherwise the cache will end up with an active entry without any // transaction attached. + ReportCacheActionFinish(); net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_OPEN_ENTRY, result); cache_pending_ = false; if (result == OK) { @@ -897,6 +905,7 @@ int HttpCache::Transaction::DoCreateEntry() { next_state_ = STATE_CREATE_ENTRY_COMPLETE; cache_pending_ = true; net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_CREATE_ENTRY); + ReportCacheActionStart(); return cache_->CreateEntry(cache_key_, &new_entry_, this); } @@ -904,6 +913,7 @@ int HttpCache::Transaction::DoCreateEntryComplete(int result) { // It is important that we go to STATE_ADD_TO_ENTRY whenever the result is // OK, otherwise the cache will end up with an active entry without any // transaction attached. + ReportCacheActionFinish(); net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_CREATE_ENTRY, result); cache_pending_ = false; @@ -932,10 +942,12 @@ int HttpCache::Transaction::DoDoomEntry() { next_state_ = STATE_DOOM_ENTRY_COMPLETE; cache_pending_ = true; net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_DOOM_ENTRY); + ReportCacheActionStart(); return cache_->DoomEntry(cache_key_, this); } int HttpCache::Transaction::DoDoomEntryComplete(int result) { + ReportCacheActionFinish(); net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_DOOM_ENTRY, result); next_state_ = STATE_CREATE_ENTRY; cache_pending_ = false; @@ -1137,15 +1149,18 @@ int HttpCache::Transaction::DoTruncateCachedData() { return OK; if (net_log_.IsLoggingAllEvents()) net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_WRITE_DATA); - + ReportCacheActionStart(); // Truncate the stream. return WriteToEntry(kResponseContentIndex, 0, NULL, 0, io_callback_); } int HttpCache::Transaction::DoTruncateCachedDataComplete(int result) { - if (net_log_.IsLoggingAllEvents() && entry_) { - net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_WRITE_DATA, - result); + if (entry_) { + ReportCacheActionFinish(); + if (net_log_.IsLoggingAllEvents()) { + net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_WRITE_DATA, + result); + } } next_state_ = STATE_TRUNCATE_CACHED_METADATA; @@ -1159,13 +1174,17 @@ int HttpCache::Transaction::DoTruncateCachedMetadata() { if (net_log_.IsLoggingAllEvents()) net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_WRITE_INFO); + ReportCacheActionStart(); return WriteToEntry(kMetadataIndex, 0, NULL, 0, io_callback_); } int HttpCache::Transaction::DoTruncateCachedMetadataComplete(int result) { - if (net_log_.IsLoggingAllEvents() && entry_) { - net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_WRITE_INFO, - result); + if (entry_) { + ReportCacheActionFinish(); + if (net_log_.IsLoggingAllEvents()) { + net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_WRITE_INFO, + result); + } } // If this response is a redirect, then we can stop writing now. (We don't @@ -1207,11 +1226,13 @@ int HttpCache::Transaction::DoCacheReadResponse() { read_buf_ = new IOBuffer(io_buf_len_); net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_READ_INFO); + ReportCacheActionStart(); return entry_->disk_entry->ReadData(kResponseInfoIndex, 0, read_buf_, io_buf_len_, io_callback_); } int HttpCache::Transaction::DoCacheReadResponseComplete(int result) { + ReportCacheActionFinish(); net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_READ_INFO, result); if (result != io_buf_len_ || !HttpCache::ParseResponseInfo(read_buf_->data(), io_buf_len_, @@ -1256,14 +1277,20 @@ int HttpCache::Transaction::DoCacheReadResponseComplete(int result) { } int HttpCache::Transaction::DoCacheWriteResponse() { - if (net_log_.IsLoggingAllEvents() && entry_) - net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_WRITE_INFO); + if (entry_) { + if (net_log_.IsLoggingAllEvents()) + net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_WRITE_INFO); + ReportCacheActionStart(); + } return WriteResponseInfoToEntry(false); } int HttpCache::Transaction::DoCacheWriteTruncatedResponse() { - if (net_log_.IsLoggingAllEvents() && entry_) - net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_WRITE_INFO); + if (entry_) { + if (net_log_.IsLoggingAllEvents() && entry_) + net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_WRITE_INFO); + ReportCacheActionStart(); + } return WriteResponseInfoToEntry(true); } @@ -1272,6 +1299,7 @@ int HttpCache::Transaction::DoCacheWriteResponseComplete(int result) { target_state_ = STATE_NONE; if (!entry_) return OK; + ReportCacheActionFinish(); if (net_log_.IsLoggingAllEvents()) { net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_WRITE_INFO, result); @@ -1294,12 +1322,14 @@ int HttpCache::Transaction::DoCacheReadMetadata() { new IOBufferWithSize(entry_->disk_entry->GetDataSize(kMetadataIndex)); net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_READ_INFO); + ReportCacheActionStart(); return entry_->disk_entry->ReadData(kMetadataIndex, 0, response_.metadata, response_.metadata->size(), io_callback_); } int HttpCache::Transaction::DoCacheReadMetadataComplete(int result) { + ReportCacheActionFinish(); net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_READ_INFO, result); if (result != response_.metadata->size()) return OnCacheReadError(result, false); @@ -1328,6 +1358,7 @@ int HttpCache::Transaction::DoCacheReadData() { if (net_log_.IsLoggingAllEvents()) net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_READ_DATA); + ReportCacheActionStart(); if (partial_.get()) { return partial_->CacheRead(entry_->disk_entry, read_buf_, io_buf_len_, io_callback_); @@ -1338,6 +1369,7 @@ int HttpCache::Transaction::DoCacheReadData() { } int HttpCache::Transaction::DoCacheReadDataComplete(int result) { + ReportCacheActionFinish(); if (net_log_.IsLoggingAllEvents()) { net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_READ_DATA, result); @@ -1363,16 +1395,22 @@ int HttpCache::Transaction::DoCacheReadDataComplete(int result) { int HttpCache::Transaction::DoCacheWriteData(int num_bytes) { next_state_ = STATE_CACHE_WRITE_DATA_COMPLETE; write_len_ = num_bytes; - if (net_log_.IsLoggingAllEvents() && entry_) - net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_WRITE_DATA); + if (entry_) { + if (net_log_.IsLoggingAllEvents()) + net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_WRITE_DATA); + ReportCacheActionStart(); + } return AppendResponseDataToEntry(read_buf_, num_bytes, io_callback_); } int HttpCache::Transaction::DoCacheWriteDataComplete(int result) { - if (net_log_.IsLoggingAllEvents() && entry_) { - net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_WRITE_DATA, - result); + if (entry_) { + ReportCacheActionFinish(); + if (net_log_.IsLoggingAllEvents()) { + net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_WRITE_DATA, + result); + } } // Balance the AddRef from DoCacheWriteData. if (!cache_) @@ -2112,4 +2150,14 @@ void HttpCache::Transaction::OnIOComplete(int result) { DoLoop(result); } +void HttpCache::Transaction::ReportCacheActionStart() { + if (transaction_delegate_) + transaction_delegate_->OnCacheActionStart(); +} + +void HttpCache::Transaction::ReportCacheActionFinish() { + if (transaction_delegate_) + transaction_delegate_->OnCacheActionFinish(); +} + } // namespace net diff --git a/net/http/http_cache_transaction.h b/net/http/http_cache_transaction.h index 5b1dc6c..3f8a5e5 100644 --- a/net/http/http_cache_transaction.h +++ b/net/http/http_cache_transaction.h @@ -22,6 +22,7 @@ namespace net { class PartialData; struct HttpRequestInfo; +class HttpTransactionDelegate; // This is the transaction that is returned by the HttpCache transaction // factory. @@ -56,7 +57,7 @@ class HttpCache::Transaction : public HttpTransaction { UPDATE = READ_META | WRITE, // READ_WRITE & ~READ_DATA }; - explicit Transaction(HttpCache* cache); + Transaction(HttpCache* cache, HttpTransactionDelegate* transaction_delegate); virtual ~Transaction(); Mode mode() const { return mode_; } @@ -334,6 +335,9 @@ class HttpCache::Transaction : public HttpTransaction { // Called to signal completion of asynchronous IO. void OnIOComplete(int result); + void ReportCacheActionStart(); + void ReportCacheActionFinish(); + State next_state_; const HttpRequestInfo* request_; BoundNetLog net_log_; @@ -371,6 +375,7 @@ class HttpCache::Transaction : public HttpTransaction { uint64 final_upload_progress_; base::WeakPtrFactory<Transaction> weak_factory_; CompletionCallback io_callback_; + HttpTransactionDelegate* transaction_delegate_; }; } // namespace net diff --git a/net/http/http_cache_unittest.cc b/net/http/http_cache_unittest.cc index d692c51..c43d49d 100644 --- a/net/http/http_cache_unittest.cc +++ b/net/http/http_cache_unittest.cc @@ -24,6 +24,7 @@ #include "net/http/http_response_headers.h" #include "net/http/http_response_info.h" #include "net/http/http_transaction.h" +#include "net/http/http_transaction_delegate.h" #include "net/http/http_transaction_unittest.h" #include "net/http/http_util.h" #include "net/http/mock_http_cache.h" @@ -59,6 +60,32 @@ class DeleteCacheCompletionCallback : public net::TestCompletionCallbackBase { //----------------------------------------------------------------------------- // helpers +class TestHttpTransactionDelegate : public net::HttpTransactionDelegate { + public: + explicit TestHttpTransactionDelegate(int num_actions_to_observe) + : num_remaining_actions_to_observe_(num_actions_to_observe), + action_in_progress_(false) { + } + virtual ~TestHttpTransactionDelegate() { + EXPECT_EQ(0, num_remaining_actions_to_observe_); + EXPECT_FALSE(action_in_progress_); + } + virtual void OnCacheActionStart() { + EXPECT_FALSE(action_in_progress_); + EXPECT_GT(num_remaining_actions_to_observe_, 0); + num_remaining_actions_to_observe_--; + action_in_progress_ = true; + } + virtual void OnCacheActionFinish() { + EXPECT_TRUE(action_in_progress_); + action_in_progress_ = false; + } + + private: + int num_remaining_actions_to_observe_; + bool action_in_progress_; +}; + void ReadAndVerifyTransaction(net::HttpTransaction* trans, const MockTransaction& trans_info) { std::string content; @@ -69,17 +96,25 @@ void ReadAndVerifyTransaction(net::HttpTransaction* trans, EXPECT_EQ(expected, content); } -void RunTransactionTestWithRequestAndLog(net::HttpCache* cache, - const MockTransaction& trans_info, - const MockHttpRequest& request, - net::HttpResponseInfo* response_info, - const net::BoundNetLog& net_log) { +const int kNoDelegateTransactionCheck = -1; + +void RunTransactionTestWithRequestAndLogAndDelegate( + net::HttpCache* cache, + const MockTransaction& trans_info, + const MockHttpRequest& request, + net::HttpResponseInfo* response_info, + const net::BoundNetLog& net_log, + int num_delegate_actions) { net::TestCompletionCallback callback; // write to the cache + scoped_ptr<TestHttpTransactionDelegate> delegate; + if (num_delegate_actions != kNoDelegateTransactionCheck) { + delegate.reset(new TestHttpTransactionDelegate(num_delegate_actions)); + } scoped_ptr<net::HttpTransaction> trans; - int rv = cache->CreateTransaction(&trans); + int rv = cache->CreateTransaction(&trans, delegate.get()); EXPECT_EQ(net::OK, rv); ASSERT_TRUE(trans.get()); @@ -101,15 +136,25 @@ void RunTransactionTestWithRequest(net::HttpCache* cache, const MockTransaction& trans_info, const MockHttpRequest& request, net::HttpResponseInfo* response_info) { - RunTransactionTestWithRequestAndLog(cache, trans_info, request, - response_info, net::BoundNetLog()); + RunTransactionTestWithRequestAndLogAndDelegate( + cache, trans_info, request, response_info, net::BoundNetLog(), + kNoDelegateTransactionCheck); } void RunTransactionTestWithLog(net::HttpCache* cache, const MockTransaction& trans_info, const net::BoundNetLog& log) { - RunTransactionTestWithRequestAndLog( - cache, trans_info, MockHttpRequest(trans_info), NULL, log); + RunTransactionTestWithRequestAndLogAndDelegate( + cache, trans_info, MockHttpRequest(trans_info), NULL, log, + kNoDelegateTransactionCheck); +} + +void RunTransactionTestWithDelegate(net::HttpCache* cache, + const MockTransaction& trans_info, + int num_delegate_actions) { + RunTransactionTestWithRequestAndLogAndDelegate( + cache, trans_info, MockHttpRequest(trans_info), NULL, net::BoundNetLog(), + num_delegate_actions); } void RunTransactionTest(net::HttpCache* cache, @@ -396,7 +441,7 @@ TEST(HttpCache, CreateThenDestroy) { MockHttpCache cache; scoped_ptr<net::HttpTransaction> trans; - int rv = cache.http_cache()->CreateTransaction(&trans); + int rv = cache.http_cache()->CreateTransaction(&trans, NULL); EXPECT_EQ(net::OK, rv); ASSERT_TRUE(trans.get()); } @@ -500,7 +545,7 @@ TEST(HttpCache, SimpleGETWithDiskFailures2) { MockHttpRequest request(kSimpleGET_Transaction); scoped_ptr<Context> c(new Context()); - int rv = cache.http_cache()->CreateTransaction(&c->trans); + int rv = cache.http_cache()->CreateTransaction(&c->trans, NULL); EXPECT_EQ(net::OK, rv); rv = c->trans->Start(&request, c->callback.callback(), net::BoundNetLog()); @@ -545,7 +590,7 @@ TEST(HttpCache, SimpleGETWithDiskFailures3) { // Now fail to read from the cache. scoped_ptr<Context> c(new Context()); - int rv = cache.http_cache()->CreateTransaction(&c->trans); + int rv = cache.http_cache()->CreateTransaction(&c->trans, NULL); EXPECT_EQ(net::OK, rv); MockHttpRequest request(kSimpleGET_Transaction); @@ -645,7 +690,7 @@ TEST(HttpCache, SimpleGET_LoadOnlyFromCache_Miss) { net::TestCompletionCallback callback; scoped_ptr<net::HttpTransaction> trans; - int rv = cache.http_cache()->CreateTransaction(&trans); + int rv = cache.http_cache()->CreateTransaction(&trans, NULL); EXPECT_EQ(net::OK, rv); ASSERT_TRUE(trans.get()); @@ -871,7 +916,7 @@ TEST(HttpCache, SimpleGET_ManyReaders) { context_list.push_back(new Context()); Context* c = context_list[i]; - c->result = cache.http_cache()->CreateTransaction(&c->trans); + c->result = cache.http_cache()->CreateTransaction(&c->trans, NULL); EXPECT_EQ(net::OK, c->result); EXPECT_EQ(net::LOAD_STATE_IDLE, c->trans->GetLoadState()); @@ -939,7 +984,7 @@ TEST(HttpCache, SimpleGET_RacingReaders) { context_list.push_back(new Context()); Context* c = context_list[i]; - c->result = cache.http_cache()->CreateTransaction(&c->trans); + c->result = cache.http_cache()->CreateTransaction(&c->trans, NULL); EXPECT_EQ(net::OK, c->result); MockHttpRequest* this_request = &request; @@ -1024,7 +1069,7 @@ TEST(HttpCache, SimpleGET_DoomWithPending) { context_list.push_back(new Context()); Context* c = context_list[i]; - c->result = cache.http_cache()->CreateTransaction(&c->trans); + c->result = cache.http_cache()->CreateTransaction(&c->trans, NULL); EXPECT_EQ(net::OK, c->result); MockHttpRequest* this_request = &request; @@ -1072,7 +1117,7 @@ TEST(HttpCache, FastNoStoreGET_DoneWithPending) { context_list.push_back(new Context()); Context* c = context_list[i]; - c->result = cache.http_cache()->CreateTransaction(&c->trans); + c->result = cache.http_cache()->CreateTransaction(&c->trans, NULL); EXPECT_EQ(net::OK, c->result); c->result = c->trans->Start( @@ -1119,7 +1164,7 @@ TEST(HttpCache, SimpleGET_ManyWriters_CancelFirst) { context_list.push_back(new Context()); Context* c = context_list[i]; - c->result = cache.http_cache()->CreateTransaction(&c->trans); + c->result = cache.http_cache()->CreateTransaction(&c->trans, NULL); EXPECT_EQ(net::OK, c->result); c->result = c->trans->Start( @@ -1179,7 +1224,7 @@ TEST(HttpCache, SimpleGET_ManyWriters_CancelCreate) { context_list.push_back(new Context()); Context* c = context_list[i]; - c->result = cache.http_cache()->CreateTransaction(&c->trans); + c->result = cache.http_cache()->CreateTransaction(&c->trans, NULL); EXPECT_EQ(net::OK, c->result); c->result = c->trans->Start( @@ -1230,7 +1275,7 @@ TEST(HttpCache, SimpleGET_CancelCreate) { Context* c = new Context(); - c->result = cache.http_cache()->CreateTransaction(&c->trans); + c->result = cache.http_cache()->CreateTransaction(&c->trans, NULL); EXPECT_EQ(net::OK, c->result); c->result = c->trans->Start( @@ -1260,7 +1305,7 @@ TEST(HttpCache, SimpleGET_ManyWriters_BypassCache) { context_list.push_back(new Context()); Context* c = context_list[i]; - c->result = cache.http_cache()->CreateTransaction(&c->trans); + c->result = cache.http_cache()->CreateTransaction(&c->trans, NULL); EXPECT_EQ(net::OK, c->result); c->result = c->trans->Start( @@ -1302,7 +1347,7 @@ TEST(HttpCache, SimpleGET_AbandonedCacheRead) { net::TestCompletionCallback callback; scoped_ptr<net::HttpTransaction> trans; - int rv = cache.http_cache()->CreateTransaction(&trans); + int rv = cache.http_cache()->CreateTransaction(&trans, NULL); EXPECT_EQ(net::OK, rv); rv = trans->Start(&request, callback.callback(), net::BoundNetLog()); if (rv == net::ERR_IO_PENDING) @@ -1337,7 +1382,7 @@ TEST(HttpCache, SimpleGET_ManyWriters_DeleteCache) { context_list.push_back(new Context()); Context* c = context_list[i]; - c->result = cache->http_cache()->CreateTransaction(&c->trans); + c->result = cache->http_cache()->CreateTransaction(&c->trans, NULL); EXPECT_EQ(net::OK, c->result); c->result = c->trans->Start( @@ -1376,7 +1421,7 @@ TEST(HttpCache, SimpleGET_WaitForBackend) { context_list.push_back(new Context()); Context* c = context_list[i]; - c->result = cache.http_cache()->CreateTransaction(&c->trans); + c->result = cache.http_cache()->CreateTransaction(&c->trans, NULL); EXPECT_EQ(net::OK, c->result); } @@ -1422,7 +1467,7 @@ TEST(HttpCache, SimpleGET_WaitForBackend_CancelCreate) { context_list.push_back(new Context()); Context* c = context_list[i]; - c->result = cache.http_cache()->CreateTransaction(&c->trans); + c->result = cache.http_cache()->CreateTransaction(&c->trans, NULL); EXPECT_EQ(net::OK, c->result); } @@ -1468,7 +1513,7 @@ TEST(HttpCache, DeleteCacheWaitingForBackend) { MockHttpRequest request(kSimpleGET_Transaction); scoped_ptr<Context> c(new Context()); - c->result = cache->http_cache()->CreateTransaction(&c->trans); + c->result = cache->http_cache()->CreateTransaction(&c->trans, NULL); EXPECT_EQ(net::OK, c->result); c->trans->Start(&request, c->callback.callback(), net::BoundNetLog()); @@ -1506,7 +1551,7 @@ TEST(HttpCache, DeleteCacheWaitingForBackend2) { MockHttpRequest request(kSimpleGET_Transaction); scoped_ptr<Context> c(new Context()); - c->result = cache->http_cache()->CreateTransaction(&c->trans); + c->result = cache->http_cache()->CreateTransaction(&c->trans, NULL); EXPECT_EQ(net::OK, c->result); c->trans->Start(&request, c->callback.callback(), net::BoundNetLog()); @@ -2192,7 +2237,7 @@ TEST(HttpCache, SimplePOST_LoadOnlyFromCache_Miss) { net::TestCompletionCallback callback; scoped_ptr<net::HttpTransaction> trans; - int rv = cache.http_cache()->CreateTransaction(&trans); + int rv = cache.http_cache()->CreateTransaction(&trans, NULL); EXPECT_EQ(net::OK, rv); ASSERT_TRUE(trans.get()); @@ -3253,7 +3298,7 @@ TEST(HttpCache, RangeGET_Cancel) { MockHttpRequest request(kRangeGET_TransactionOK); Context* c = new Context(); - int rv = cache.http_cache()->CreateTransaction(&c->trans); + int rv = cache.http_cache()->CreateTransaction(&c->trans, NULL); EXPECT_EQ(net::OK, rv); rv = c->trans->Start(&request, c->callback.callback(), net::BoundNetLog()); @@ -3292,7 +3337,7 @@ TEST(HttpCache, RangeGET_Cancel2) { request.load_flags |= net::LOAD_VALIDATE_CACHE; Context* c = new Context(); - int rv = cache.http_cache()->CreateTransaction(&c->trans); + int rv = cache.http_cache()->CreateTransaction(&c->trans, NULL); EXPECT_EQ(net::OK, rv); rv = c->trans->Start(&request, c->callback.callback(), net::BoundNetLog()); @@ -3337,7 +3382,7 @@ TEST(HttpCache, RangeGET_Cancel3) { request.load_flags |= net::LOAD_VALIDATE_CACHE; Context* c = new Context(); - int rv = cache.http_cache()->CreateTransaction(&c->trans); + int rv = cache.http_cache()->CreateTransaction(&c->trans, NULL); EXPECT_EQ(net::OK, rv); rv = c->trans->Start(&request, c->callback.callback(), net::BoundNetLog()); @@ -3364,7 +3409,7 @@ TEST(HttpCache, RangeGET_Cancel3) { // active entry (no open or create). c = new Context(); - rv = cache.http_cache()->CreateTransaction(&c->trans); + rv = cache.http_cache()->CreateTransaction(&c->trans, NULL); EXPECT_EQ(net::OK, rv); rv = c->trans->Start(&request, c->callback.callback(), net::BoundNetLog()); @@ -3645,7 +3690,7 @@ TEST(HttpCache, RangeGET_OK_LoadOnlyFromCache) { net::TestCompletionCallback callback; scoped_ptr<net::HttpTransaction> trans; - int rv = cache.http_cache()->CreateTransaction(&trans); + int rv = cache.http_cache()->CreateTransaction(&trans, NULL); EXPECT_EQ(net::OK, rv); ASSERT_TRUE(trans.get()); @@ -3723,7 +3768,7 @@ TEST(HttpCache, DoomOnDestruction) { MockHttpRequest request(kSimpleGET_Transaction); Context* c = new Context(); - int rv = cache.http_cache()->CreateTransaction(&c->trans); + int rv = cache.http_cache()->CreateTransaction(&c->trans, NULL); EXPECT_EQ(net::OK, rv); rv = c->trans->Start(&request, c->callback.callback(), net::BoundNetLog()); @@ -3753,7 +3798,7 @@ TEST(HttpCache, DoomOnDestruction2) { MockHttpRequest request(kSimpleGET_Transaction); Context* c = new Context(); - int rv = cache.http_cache()->CreateTransaction(&c->trans); + int rv = cache.http_cache()->CreateTransaction(&c->trans, NULL); EXPECT_EQ(net::OK, rv); rv = c->trans->Start(&request, c->callback.callback(), net::BoundNetLog()); @@ -3796,7 +3841,7 @@ TEST(HttpCache, DoomOnDestruction3) { MockHttpRequest request(transaction); Context* c = new Context(); - int rv = cache.http_cache()->CreateTransaction(&c->trans); + int rv = cache.http_cache()->CreateTransaction(&c->trans, NULL); EXPECT_EQ(net::OK, rv); rv = c->trans->Start(&request, c->callback.callback(), net::BoundNetLog()); @@ -3839,7 +3884,7 @@ TEST(HttpCache, SetTruncatedFlag) { MockHttpRequest request(transaction); scoped_ptr<Context> c(new Context()); - int rv = cache.http_cache()->CreateTransaction(&c->trans); + int rv = cache.http_cache()->CreateTransaction(&c->trans, NULL); EXPECT_EQ(net::OK, rv); rv = c->trans->Start(&request, c->callback.callback(), net::BoundNetLog()); @@ -3899,7 +3944,7 @@ TEST(HttpCache, DontSetTruncatedFlag) { MockHttpRequest request(transaction); scoped_ptr<Context> c(new Context()); - int rv = cache.http_cache()->CreateTransaction(&c->trans); + int rv = cache.http_cache()->CreateTransaction(&c->trans, NULL); EXPECT_EQ(net::OK, rv); rv = c->trans->Start(&request, c->callback.callback(), net::BoundNetLog()); @@ -4043,7 +4088,7 @@ TEST(HttpCache, GET_IncompleteResource_Cancel) { MockHttpRequest request(transaction); Context* c = new Context(); - int rv = cache.http_cache()->CreateTransaction(&c->trans); + int rv = cache.http_cache()->CreateTransaction(&c->trans, NULL); EXPECT_EQ(net::OK, rv); // Queue another request to this transaction. We have to start this request @@ -4051,7 +4096,8 @@ TEST(HttpCache, GET_IncompleteResource_Cancel) { // otherwise it will just create a new entry without being queued to the first // request. Context* pending = new Context(); - EXPECT_EQ(net::OK, cache.http_cache()->CreateTransaction(&pending->trans)); + EXPECT_EQ(net::OK, + cache.http_cache()->CreateTransaction(&pending->trans, NULL)); rv = c->trans->Start(&request, c->callback.callback(), net::BoundNetLog()); EXPECT_EQ(net::ERR_IO_PENDING, @@ -4135,7 +4181,7 @@ TEST(HttpCache, GET_IncompleteResource3) { "rg: 50-59 rg: 60-69 rg: 70-79 "; scoped_ptr<Context> c(new Context); - EXPECT_EQ(net::OK, cache.http_cache()->CreateTransaction(&c->trans)); + EXPECT_EQ(net::OK, cache.http_cache()->CreateTransaction(&c->trans, NULL)); MockHttpRequest request(transaction); int rv = c->trans->Start( @@ -4207,7 +4253,7 @@ TEST(HttpCache, GET_CancelIncompleteResource) { MockHttpRequest request(transaction); Context* c = new Context(); - EXPECT_EQ(net::OK, cache.http_cache()->CreateTransaction(&c->trans)); + EXPECT_EQ(net::OK, cache.http_cache()->CreateTransaction(&c->trans, NULL)); int rv = c->trans->Start( &request, c->callback.callback(), net::BoundNetLog()); @@ -4335,7 +4381,7 @@ TEST(HttpCache, CachedRedirect) { // write to the cache { scoped_ptr<net::HttpTransaction> trans; - int rv = cache.http_cache()->CreateTransaction(&trans); + int rv = cache.http_cache()->CreateTransaction(&trans, NULL); EXPECT_EQ(net::OK, rv); ASSERT_TRUE(trans.get()); @@ -4363,7 +4409,7 @@ TEST(HttpCache, CachedRedirect) { // read from the cache { scoped_ptr<net::HttpTransaction> trans; - int rv = cache.http_cache()->CreateTransaction(&trans); + int rv = cache.http_cache()->CreateTransaction(&trans, NULL); EXPECT_EQ(net::OK, rv); ASSERT_TRUE(trans.get()); @@ -4488,7 +4534,7 @@ TEST(HttpCache, SimpleGET_SSLError) { net::TestCompletionCallback callback; scoped_ptr<net::HttpTransaction> trans; - int rv = cache.http_cache()->CreateTransaction(&trans); + int rv = cache.http_cache()->CreateTransaction(&trans, NULL); EXPECT_EQ(net::OK, rv); ASSERT_TRUE(trans.get()); @@ -4503,7 +4549,7 @@ TEST(HttpCache, OutlivedTransactions) { MockHttpCache* cache = new MockHttpCache; scoped_ptr<net::HttpTransaction> trans; - int rv = cache->http_cache()->CreateTransaction(&trans); + int rv = cache->http_cache()->CreateTransaction(&trans, NULL); EXPECT_EQ(net::OK, rv); delete cache; @@ -4741,7 +4787,7 @@ TEST(HttpCache, FilterCompletion) { { scoped_ptr<net::HttpTransaction> trans; - int rv = cache.http_cache()->CreateTransaction(&trans); + int rv = cache.http_cache()->CreateTransaction(&trans, NULL); EXPECT_EQ(net::OK, rv); MockHttpRequest request(kSimpleGET_Transaction); @@ -4775,7 +4821,7 @@ TEST(HttpCache, StopCachingDeletesEntry) { { scoped_ptr<net::HttpTransaction> trans; - int rv = cache.http_cache()->CreateTransaction(&trans); + int rv = cache.http_cache()->CreateTransaction(&trans, NULL); EXPECT_EQ(net::OK, rv); rv = trans->Start(&request, callback.callback(), net::BoundNetLog()); @@ -4813,7 +4859,7 @@ TEST(HttpCache, StopCachingSavesEntry) { { scoped_ptr<net::HttpTransaction> trans; - int rv = cache.http_cache()->CreateTransaction(&trans); + int rv = cache.http_cache()->CreateTransaction(&trans, NULL); EXPECT_EQ(net::OK, rv); // Force a response that can be resumed. @@ -4870,7 +4916,7 @@ TEST(HttpCache, StopCachingTruncatedEntry) { { // Now make a regular request. scoped_ptr<net::HttpTransaction> trans; - int rv = cache.http_cache()->CreateTransaction(&trans); + int rv = cache.http_cache()->CreateTransaction(&trans, NULL); EXPECT_EQ(net::OK, rv); rv = trans->Start(&request, callback.callback(), net::BoundNetLog()); @@ -4949,3 +4995,20 @@ TEST(HttpCache, TruncatedByContentLength2) { EXPECT_TRUE(truncated); entry->Close(); } + +TEST(HttpCache, SimpleGET_LoadOnlyFromCache_Hit_TransactionDelegate) { + MockHttpCache cache; + + // Write to the cache. + RunTransactionTestWithDelegate(cache.http_cache(), + kSimpleGET_Transaction, + 8); + + // Force this transaction to read from the cache. + MockTransaction transaction(kSimpleGET_Transaction); + transaction.load_flags |= net::LOAD_ONLY_FROM_CACHE; + + RunTransactionTestWithDelegate(cache.http_cache(), + kSimpleGET_Transaction, + 5); +} diff --git a/net/http/http_network_layer.cc b/net/http/http_network_layer.cc index 0650b45..b326438 100644 --- a/net/http/http_network_layer.cc +++ b/net/http/http_network_layer.cc @@ -102,7 +102,8 @@ void HttpNetworkLayer::EnableSpdy(const std::string& mode) { //----------------------------------------------------------------------------- -int HttpNetworkLayer::CreateTransaction(scoped_ptr<HttpTransaction>* trans) { +int HttpNetworkLayer::CreateTransaction(scoped_ptr<HttpTransaction>* trans, + HttpTransactionDelegate* delegate) { if (suspended_) return ERR_NETWORK_IO_SUSPENDED; diff --git a/net/http/http_network_layer.h b/net/http/http_network_layer.h index 283bcca..d9eb676 100644 --- a/net/http/http_network_layer.h +++ b/net/http/http_network_layer.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 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. @@ -47,7 +47,8 @@ class NET_EXPORT HttpNetworkLayer static void EnableSpdy(const std::string& mode); // HttpTransactionFactory methods: - virtual int CreateTransaction(scoped_ptr<HttpTransaction>* trans) OVERRIDE; + virtual int CreateTransaction(scoped_ptr<HttpTransaction>* trans, + HttpTransactionDelegate* delegate) OVERRIDE; virtual HttpCache* GetCache() OVERRIDE; virtual HttpNetworkSession* GetSession() OVERRIDE; diff --git a/net/http/http_network_layer_unittest.cc b/net/http/http_network_layer_unittest.cc index 167b209..a82dd00 100644 --- a/net/http/http_network_layer_unittest.cc +++ b/net/http/http_network_layer_unittest.cc @@ -50,28 +50,28 @@ class HttpNetworkLayerTest : public PlatformTest { TEST_F(HttpNetworkLayerTest, CreateAndDestroy) { scoped_ptr<HttpTransaction> trans; - int rv = factory_->CreateTransaction(&trans); + int rv = factory_->CreateTransaction(&trans, NULL); EXPECT_EQ(OK, rv); EXPECT_TRUE(trans.get() != NULL); } TEST_F(HttpNetworkLayerTest, Suspend) { scoped_ptr<HttpTransaction> trans; - int rv = factory_->CreateTransaction(&trans); + int rv = factory_->CreateTransaction(&trans, NULL); EXPECT_EQ(OK, rv); trans.reset(); factory_->OnSuspend(); - rv = factory_->CreateTransaction(&trans); + rv = factory_->CreateTransaction(&trans, NULL); EXPECT_EQ(ERR_NETWORK_IO_SUSPENDED, rv); ASSERT_TRUE(trans == NULL); factory_->OnResume(); - rv = factory_->CreateTransaction(&trans); + rv = factory_->CreateTransaction(&trans, NULL); EXPECT_EQ(OK, rv); } @@ -101,7 +101,7 @@ TEST_F(HttpNetworkLayerTest, GET) { request_info.load_flags = LOAD_NORMAL; scoped_ptr<HttpTransaction> trans; - int rv = factory_->CreateTransaction(&trans); + int rv = factory_->CreateTransaction(&trans, NULL); EXPECT_EQ(OK, rv); rv = trans->Start(&request_info, callback.callback(), BoundNetLog()); diff --git a/net/http/http_transaction_delegate.h b/net/http/http_transaction_delegate.h new file mode 100644 index 0000000..99f348d --- /dev/null +++ b/net/http/http_transaction_delegate.h @@ -0,0 +1,23 @@ +// Copyright (c) 2012 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 NET_HTTP_HTTP_TRANSACTION_DELEGATE_H_ +#define NET_HTTP_HTTP_TRANSACTION_DELEGATE_H_ + +namespace net { + +// Delegate class receiving notifications when cache actions start and finish, +// i.e. when the object starts and finishes waiting on an underlying cache. +// The owner of a HttpTransaction can use this to register a delegate to +// receive notifications when these events happen. +class HttpTransactionDelegate { + public: + virtual ~HttpTransactionDelegate() {} + virtual void OnCacheActionStart() = 0; + virtual void OnCacheActionFinish() = 0; +}; + +} // namespace net + +#endif // NET_HTTP_HTTP_TRANSACTION_DELEGATE_H_ diff --git a/net/http/http_transaction_factory.h b/net/http/http_transaction_factory.h index 6d2dfe0..08f43e5 100644 --- a/net/http/http_transaction_factory.h +++ b/net/http/http_transaction_factory.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 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. @@ -13,7 +13,7 @@ namespace net { class HttpCache; class HttpNetworkSession; class HttpTransaction; - +class HttpTransactionDelegate; // An interface to a class that can create HttpTransaction objects. class NET_EXPORT HttpTransactionFactory { @@ -22,7 +22,8 @@ class NET_EXPORT HttpTransactionFactory { // Creates a HttpTransaction object. On success, saves the new // transaction to |*trans| and returns OK. - virtual int CreateTransaction(scoped_ptr<HttpTransaction>* trans) = 0; + virtual int CreateTransaction(scoped_ptr<HttpTransaction>* trans, + HttpTransactionDelegate* delegate) = 0; // Returns the associated cache if any (may be NULL). virtual HttpCache* GetCache() = 0; diff --git a/net/http/http_transaction_unittest.cc b/net/http/http_transaction_unittest.cc index 9c09c42..f8d1958 100644 --- a/net/http/http_transaction_unittest.cc +++ b/net/http/http_transaction_unittest.cc @@ -151,7 +151,7 @@ TestTransactionConsumer::TestTransactionConsumer( trans_(NULL), error_(net::OK) { // Disregard the error code. - factory->CreateTransaction(&trans_); + factory->CreateTransaction(&trans_, NULL); ++quit_counter_; } @@ -341,7 +341,8 @@ void MockNetworkLayer::TransactionDoneReading() { } int MockNetworkLayer::CreateTransaction( - scoped_ptr<net::HttpTransaction>* trans) { + scoped_ptr<net::HttpTransaction>* trans, + net::HttpTransactionDelegate* delegate) { transaction_count_++; trans->reset(new MockNetworkTransaction(this)); return net::OK; diff --git a/net/http/http_transaction_unittest.h b/net/http/http_transaction_unittest.h index ad2aaf8..43a9fa7 100644 --- a/net/http/http_transaction_unittest.h +++ b/net/http/http_transaction_unittest.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 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. @@ -210,7 +210,8 @@ class MockNetworkLayer : public net::HttpTransactionFactory, // net::HttpTransactionFactory: virtual int CreateTransaction( - scoped_ptr<net::HttpTransaction>* trans) OVERRIDE; + scoped_ptr<net::HttpTransaction>* trans, + net::HttpTransactionDelegate* delegate) OVERRIDE; virtual net::HttpCache* GetCache() OVERRIDE; virtual net::HttpNetworkSession* GetSession() OVERRIDE; diff --git a/net/net.gyp b/net/net.gyp index e320152..99f4298 100644 --- a/net/net.gyp +++ b/net/net.gyp @@ -515,6 +515,7 @@ 'http/http_stream_parser.cc', 'http/http_stream_parser.h', 'http/http_transaction.h', + 'http/http_transaction_delegate.h', 'http/http_transaction_factory.h', 'http/http_util.cc', 'http/http_util.h', diff --git a/net/proxy/network_delegate_error_observer_unittest.cc b/net/proxy/network_delegate_error_observer_unittest.cc index b8084e0..46d2b01 100644 --- a/net/proxy/network_delegate_error_observer_unittest.cc +++ b/net/proxy/network_delegate_error_observer_unittest.cc @@ -84,6 +84,9 @@ class TestNetworkDelegate : public net::NetworkDelegate { const CompletionCallback& callback) OVERRIDE { return OK; } + virtual void OnCacheWaitStateChange(const net::URLRequest& request, + CacheWaitState state) OVERRIDE { + } bool got_pac_error_; }; diff --git a/net/proxy/proxy_script_fetcher_impl_unittest.cc b/net/proxy/proxy_script_fetcher_impl_unittest.cc index 74e37ae..62b5fbc 100644 --- a/net/proxy/proxy_script_fetcher_impl_unittest.cc +++ b/net/proxy/proxy_script_fetcher_impl_unittest.cc @@ -193,6 +193,10 @@ class BasicNetworkDelegate : public NetworkDelegate { return OK; } + virtual void OnCacheWaitStateChange(const net::URLRequest& request, + CacheWaitState state) OVERRIDE { + } + DISALLOW_COPY_AND_ASSIGN(BasicNetworkDelegate); }; diff --git a/net/tools/fetch/fetch_client.cc b/net/tools/fetch/fetch_client.cc index 32feba3..b69b2c9 100644 --- a/net/tools/fetch/fetch_client.cc +++ b/net/tools/fetch/fetch_client.cc @@ -59,7 +59,7 @@ class Client { Client(net::HttpTransactionFactory* factory, const std::string& url) : url_(url), buffer_(new net::IOBuffer(kBufferSize)) { - int rv = factory->CreateTransaction(&transaction_); + int rv = factory->CreateTransaction(&transaction_, NULL); DCHECK_EQ(net::OK, rv); buffer_->AddRef(); g_driver.Get().ClientStarted(); diff --git a/net/url_request/url_request_context_builder.cc b/net/url_request/url_request_context_builder.cc index 69038c5..e6baddc 100644 --- a/net/url_request/url_request_context_builder.cc +++ b/net/url_request/url_request_context_builder.cc @@ -111,6 +111,10 @@ class BasicNetworkDelegate : public NetworkDelegate { return OK; } + virtual void OnCacheWaitStateChange(const URLRequest& request, + CacheWaitState state) OVERRIDE { + } + DISALLOW_COPY_AND_ASSIGN(BasicNetworkDelegate); }; diff --git a/net/url_request/url_request_http_job.cc b/net/url_request/url_request_http_job.cc index 718b454..06214e6 100644 --- a/net/url_request/url_request_http_job.cc +++ b/net/url_request/url_request_http_job.cc @@ -34,6 +34,7 @@ #include "net/http/http_response_info.h" #include "net/http/http_status_code.h" #include "net/http/http_transaction.h" +#include "net/http/http_transaction_delegate.h" #include "net/http/http_transaction_factory.h" #include "net/http/http_util.h" #include "net/url_request/fraudulent_certificate_reporter.h" @@ -74,6 +75,43 @@ class URLRequestHttpJob::HttpFilterContext : public FilterContext { DISALLOW_COPY_AND_ASSIGN(HttpFilterContext); }; +class URLRequestHttpJob::HttpTransactionDelegateImpl + : public HttpTransactionDelegate { + public: + explicit HttpTransactionDelegateImpl(URLRequest* request) + : request_(request), + network_delegate_(request->context()->network_delegate()) { + } + virtual ~HttpTransactionDelegateImpl() { + OnDetachRequest(); + } + void OnDetachRequest() { + if (request_ == NULL || network_delegate_ == NULL) + return; + network_delegate_->NotifyCacheWaitStateChange( + *request_, + NetworkDelegate::CACHE_WAIT_STATE_RESET); + request_ = NULL; + } + virtual void OnCacheActionStart() OVERRIDE { + if (request_ == NULL || network_delegate_ == NULL) + return; + network_delegate_->NotifyCacheWaitStateChange( + *request_, + NetworkDelegate::CACHE_WAIT_STATE_START); + } + virtual void OnCacheActionFinish() OVERRIDE { + if (request_ == NULL || network_delegate_ == NULL) + return; + network_delegate_->NotifyCacheWaitStateChange( + *request_, + NetworkDelegate::CACHE_WAIT_STATE_FINISH); + } + private: + URLRequest* request_; + NetworkDelegate* network_delegate_; +}; + URLRequestHttpJob::HttpFilterContext::HttpFilterContext(URLRequestHttpJob* job) : job_(job) { DCHECK(job_); @@ -178,7 +216,8 @@ URLRequestHttpJob::URLRequestHttpJob(URLRequest* request) ALLOW_THIS_IN_INITIALIZER_LIST(on_headers_received_callback_( base::Bind(&URLRequestHttpJob::OnHeadersReceivedCallback, base::Unretained(this)))), - awaiting_callback_(false) { + awaiting_callback_(false), + http_transaction_delegate_(new HttpTransactionDelegateImpl(request)) { URLRequestThrottlerManager* manager = request->context()->throttler_manager(); if (manager) throttling_entry_ = manager->RegisterRequestUrl(request->url()); @@ -306,7 +345,7 @@ void URLRequestHttpJob::StartTransactionInternal() { DCHECK(request_->context()->http_transaction_factory()); rv = request_->context()->http_transaction_factory()->CreateTransaction( - &transaction_); + &transaction_, http_transaction_delegate_.get()); if (rv == OK) { if (!throttling_entry_ || !throttling_entry_->ShouldRejectRequest(*request_)) { @@ -1437,4 +1476,8 @@ void URLRequestHttpJob::NotifyURLRequestDestroyed() { awaiting_callback_ = false; } +void URLRequestHttpJob::OnDetachRequest() { + http_transaction_delegate_->OnDetachRequest(); +} + } // namespace net diff --git a/net/url_request/url_request_http_job.h b/net/url_request/url_request_http_job.h index 39451c6..874955e 100644 --- a/net/url_request/url_request_http_job.h +++ b/net/url_request/url_request_http_job.h @@ -142,6 +142,7 @@ class URLRequestHttpJob : public URLRequestJob { typedef base::RefCountedData<bool> SharedBoolean; class HttpFilterContext; + class HttpTransactionDelegateImpl; virtual ~URLRequestHttpJob(); @@ -187,6 +188,9 @@ class URLRequestHttpJob : public URLRequestJob { // overridden by |override_response_headers_|. HttpResponseHeaders* GetResponseHeaders() const; + // Override of the private interface of URLRequestJob. + virtual void OnDetachRequest() OVERRIDE; + base::Time request_creation_time_; // Data used for statistics gathering. This data is only used for histograms @@ -234,6 +238,8 @@ class URLRequestHttpJob : public URLRequestJob { // to inform the NetworkDelegate that it may not call back. bool awaiting_callback_; + scoped_ptr<HttpTransactionDelegateImpl> http_transaction_delegate_; + DISALLOW_COPY_AND_ASSIGN(URLRequestHttpJob); }; diff --git a/net/url_request/url_request_job.cc b/net/url_request/url_request_job.cc index 91dc5ba..9ba5578 100644 --- a/net/url_request/url_request_job.cc +++ b/net/url_request/url_request_job.cc @@ -55,6 +55,7 @@ void URLRequestJob::Kill() { void URLRequestJob::DetachRequest() { request_ = NULL; + OnDetachRequest(); } // This function calls ReadData to get stream data. If a filter exists, passes diff --git a/net/url_request/url_request_job.h b/net/url_request/url_request_job.h index 92ceb14..6e3dbba 100644 --- a/net/url_request/url_request_job.h +++ b/net/url_request/url_request_job.h @@ -334,6 +334,9 @@ class NET_EXPORT URLRequestJob : public base::RefCounted<URLRequestJob>, // The default implementation does nothing. virtual void UpdatePacketReadTimes(); + // Custom handler for derived classes when the request is detached. + virtual void OnDetachRequest() {} + // Indicates that the job is done producing data, either it has completed // all the data or an error has been encountered. Set exclusively by // NotifyDone so that it is kept in sync with the request. diff --git a/net/url_request/url_request_test_util.cc b/net/url_request/url_request_test_util.cc index 45ed7b7..7880041 100644 --- a/net/url_request/url_request_test_util.cc +++ b/net/url_request/url_request_test_util.cc @@ -500,6 +500,10 @@ int TestNetworkDelegate::OnBeforeSocketStreamConnect( return net::OK; } +void TestNetworkDelegate::OnCacheWaitStateChange(const net::URLRequest& request, + CacheWaitState state) { +} + // static std::string ScopedCustomUrlRequestTestHttpHost::value_("127.0.0.1"); diff --git a/net/url_request/url_request_test_util.h b/net/url_request/url_request_test_util.h index 256264d..48a928f 100644 --- a/net/url_request/url_request_test_util.h +++ b/net/url_request/url_request_test_util.h @@ -245,6 +245,8 @@ class TestNetworkDelegate : public net::NetworkDelegate { virtual int OnBeforeSocketStreamConnect( net::SocketStream* stream, const net::CompletionCallback& callback) OVERRIDE; + virtual void OnCacheWaitStateChange(const net::URLRequest& request, + CacheWaitState state) OVERRIDE; void InitRequestStatesIfNew(int request_id); diff --git a/net/websockets/websocket_job_spdy2_unittest.cc b/net/websockets/websocket_job_spdy2_unittest.cc index 4835f34..f1ed00d 100644 --- a/net/websockets/websocket_job_spdy2_unittest.cc +++ b/net/websockets/websocket_job_spdy2_unittest.cc @@ -304,7 +304,8 @@ class MockHttpTransactionFactory : public net::HttpTransactionFactory { } virtual int CreateTransaction( - scoped_ptr<net::HttpTransaction>* trans) OVERRIDE { + scoped_ptr<net::HttpTransaction>* trans, + net::HttpTransactionDelegate* delegate) OVERRIDE { NOTREACHED(); return net::ERR_UNEXPECTED; } diff --git a/net/websockets/websocket_job_spdy3_unittest.cc b/net/websockets/websocket_job_spdy3_unittest.cc index f69cae4..a05c094 100644 --- a/net/websockets/websocket_job_spdy3_unittest.cc +++ b/net/websockets/websocket_job_spdy3_unittest.cc @@ -306,7 +306,8 @@ class MockHttpTransactionFactory : public net::HttpTransactionFactory { EXPECT_EQ(net::OK, session_->InitializeWithSocket(connection, false, net::OK)); } - virtual int CreateTransaction(scoped_ptr<net::HttpTransaction>* trans) { + virtual int CreateTransaction(scoped_ptr<net::HttpTransaction>* trans, + net::HttpTransactionDelegate* delegate) { NOTREACHED(); return net::ERR_UNEXPECTED; } diff --git a/webkit/tools/test_shell/simple_resource_loader_bridge.cc b/webkit/tools/test_shell/simple_resource_loader_bridge.cc index 8519e42..106defa 100644 --- a/webkit/tools/test_shell/simple_resource_loader_bridge.cc +++ b/webkit/tools/test_shell/simple_resource_loader_bridge.cc @@ -187,6 +187,10 @@ class TestShellNetworkDelegate : public net::NetworkDelegate { const net::CompletionCallback& callback) OVERRIDE { return net::OK; } + + virtual void OnCacheWaitStateChange(const net::URLRequest& request, + CacheWaitState state) OVERRIDE { + } }; TestShellRequestContextParams* g_request_context_params = NULL; |