diff options
author | mmenke@chromium.org <mmenke@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-12-04 20:11:53 +0000 |
---|---|---|
committer | mmenke@chromium.org <mmenke@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-12-04 20:11:53 +0000 |
commit | f8fe5cf6449af0c8f096b1c2e38b3c76c1c923cb (patch) | |
tree | 360be63caedeab943cc4d8c936b112ce0868d2e6 | |
parent | 8f89638bcddd0325782e4b3bd1c4eaaf8f6fcc52 (diff) | |
download | chromium_src-f8fe5cf6449af0c8f096b1c2e38b3c76c1c923cb.zip chromium_src-f8fe5cf6449af0c8f096b1c2e38b3c76c1c923cb.tar.gz chromium_src-f8fe5cf6449af0c8f096b1c2e38b3c76c1c923cb.tar.bz2 |
Make resource throttles and AsyncResourceHandler add events to NetLog
when they block a request. This is aimed at making issues easier to
debug when a delegate defers an request for significant periods of time.
Also display that information in about:net-internals when a request is
already active and blocked on a delegate.
BUG=94920
Review URL: https://codereview.chromium.org/25108004
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@238746 0039d316-1c4b-4281-b951-d872f2087c98
36 files changed, 206 insertions, 134 deletions
diff --git a/android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.cc b/android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.cc index 189c39d..c88722b 100644 --- a/android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.cc +++ b/android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.cc @@ -65,6 +65,7 @@ class IoThreadClientThrottle : public content::ResourceThrottle { // From content::ResourceThrottle virtual void WillStartRequest(bool* defer) OVERRIDE; virtual void WillRedirectRequest(const GURL& new_url, bool* defer) OVERRIDE; + virtual const char* GetNameForLogging() const OVERRIDE; bool MaybeDeferRequest(bool* defer); void OnIoThreadClientReady(int new_child_id, int new_route_id); @@ -110,6 +111,10 @@ void IoThreadClientThrottle::WillRedirectRequest(const GURL& new_url, WillStartRequest(defer); } +const char* IoThreadClientThrottle::GetNameForLogging() const { + return "IoThreadClientThrottle"; +} + bool IoThreadClientThrottle::MaybeDeferRequest(bool* defer) { *defer = false; diff --git a/chrome/browser/android/intercept_download_resource_throttle.cc b/chrome/browser/android/intercept_download_resource_throttle.cc index 5700ff9..d29010d 100644 --- a/chrome/browser/android/intercept_download_resource_throttle.cc +++ b/chrome/browser/android/intercept_download_resource_throttle.cc @@ -33,6 +33,10 @@ void InterceptDownloadResourceThrottle::WillProcessResponse(bool* defer) { ProcessDownloadRequest(); } +const char* InterceptDownloadResourceThrottle::GetNameForLogging() const { + return "InterceptDownloadResourceThrottle"; +} + void InterceptDownloadResourceThrottle::ProcessDownloadRequest() { if (request_->method() != net::HttpRequestHeaders::kGetMethod || request_->response_info().did_use_http_auth) @@ -50,4 +54,4 @@ void InterceptDownloadResourceThrottle::ProcessDownloadRequest() { controller()->Cancel(); } -} // namespace +} // namespace chrome diff --git a/chrome/browser/android/intercept_download_resource_throttle.h b/chrome/browser/android/intercept_download_resource_throttle.h index a42a502..8b14d74 100644 --- a/chrome/browser/android/intercept_download_resource_throttle.h +++ b/chrome/browser/android/intercept_download_resource_throttle.h @@ -27,6 +27,7 @@ class InterceptDownloadResourceThrottle : public content::ResourceThrottle { // content::ResourceThrottle implementation: virtual void WillStartRequest(bool* defer) OVERRIDE; virtual void WillProcessResponse(bool* defer) OVERRIDE; + virtual const char* GetNameForLogging() const OVERRIDE; private: virtual ~InterceptDownloadResourceThrottle(); @@ -41,6 +42,6 @@ class InterceptDownloadResourceThrottle : public content::ResourceThrottle { DISALLOW_COPY_AND_ASSIGN(InterceptDownloadResourceThrottle); }; -} // namespace +} // namespace chrome #endif // CHROME_BROWSER_ANDROID_INTERCEPT_DOWNLOAD_RESOURCE_THROTTLE_H_ diff --git a/chrome/browser/chromeos/login/merge_session_throttle.cc b/chrome/browser/chromeos/login/merge_session_throttle.cc index 2672851..e73894b 100644 --- a/chrome/browser/chromeos/login/merge_session_throttle.cc +++ b/chrome/browser/chromeos/login/merge_session_throttle.cc @@ -99,6 +99,10 @@ void MergeSessionThrottle::WillStartRequest(bool* defer) { *defer = true; } +const char* MergeSessionThrottle::GetNameForLogging() const { + return "MergeSessionThrottle"; +} + // static. bool MergeSessionThrottle::AreAllSessionMergedAlready() { return !base::AtomicRefCountIsZero(&all_profiles_restored_); diff --git a/chrome/browser/chromeos/login/merge_session_throttle.h b/chrome/browser/chromeos/login/merge_session_throttle.h index e53352f..ddcc9ad 100644 --- a/chrome/browser/chromeos/login/merge_session_throttle.h +++ b/chrome/browser/chromeos/login/merge_session_throttle.h @@ -36,6 +36,7 @@ class MergeSessionThrottle // content::ResourceThrottle implementation: virtual void WillStartRequest(bool* defer) OVERRIDE; + virtual const char* GetNameForLogging() const OVERRIDE; // Checks if session is already merged. static bool AreAllSessionMergedAlready(); diff --git a/chrome/browser/component_updater/component_updater_service.cc b/chrome/browser/component_updater/component_updater_service.cc index b790dad..ad95f70 100644 --- a/chrome/browser/component_updater/component_updater_service.cc +++ b/chrome/browser/component_updater/component_updater_service.cc @@ -168,6 +168,7 @@ class CUResourceThrottle // Overriden from ResourceThrottle. virtual void WillStartRequest(bool* defer) OVERRIDE; virtual void WillRedirectRequest(const GURL& new_url, bool* defer) OVERRIDE; + virtual const char* GetNameForLogging() const OVERRIDE; // Component updater calls this function via PostTask to unblock the request. void Unblock(); @@ -1103,6 +1104,10 @@ void CUResourceThrottle::WillRedirectRequest(const GURL& new_url, bool* defer) { WillStartRequest(defer); } +const char* CUResourceThrottle::GetNameForLogging() const { + return "ComponentUpdateResourceThrottle"; +} + void CUResourceThrottle::Unblock() { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); if (state_ == BLOCKED) diff --git a/chrome/browser/download/download_resource_throttle.cc b/chrome/browser/download/download_resource_throttle.cc index 1fae14d..c66e985 100644 --- a/chrome/browser/download/download_resource_throttle.cc +++ b/chrome/browser/download/download_resource_throttle.cc @@ -42,6 +42,10 @@ void DownloadResourceThrottle::WillProcessResponse(bool* defer) { WillDownload(defer); } +const char* DownloadResourceThrottle::GetNameForLogging() const { + return "DownloadResourceThrottle"; +} + void DownloadResourceThrottle::WillDownload(bool* defer) { DCHECK(!request_deferred_); diff --git a/chrome/browser/download/download_resource_throttle.h b/chrome/browser/download/download_resource_throttle.h index b3c6ad7..4627b25 100644 --- a/chrome/browser/download/download_resource_throttle.h +++ b/chrome/browser/download/download_resource_throttle.h @@ -32,6 +32,7 @@ class DownloadResourceThrottle virtual void WillStartRequest(bool* defer) OVERRIDE; virtual void WillRedirectRequest(const GURL& new_url, bool* defer) OVERRIDE; virtual void WillProcessResponse(bool* defer) OVERRIDE; + virtual const char* GetNameForLogging() const OVERRIDE; private: virtual ~DownloadResourceThrottle(); diff --git a/chrome/browser/extensions/api/web_navigation/web_navigation_apitest.cc b/chrome/browser/extensions/api/web_navigation/web_navigation_apitest.cc index 9767b23..321a90b 100644 --- a/chrome/browser/extensions/api/web_navigation/web_navigation_apitest.cc +++ b/chrome/browser/extensions/api/web_navigation/web_navigation_apitest.cc @@ -135,6 +135,10 @@ class TestNavigationListener virtual void WillStartRequest(bool* defer) OVERRIDE { *defer = true; } + + virtual const char* GetNameForLogging() const OVERRIDE { + return "TestNavigationListener::Throttle"; + } }; typedef base::WeakPtr<Throttle> WeakThrottle; typedef std::list<WeakThrottle> WeakThrottleList; diff --git a/chrome/browser/extensions/api/web_request/web_request_api.cc b/chrome/browser/extensions/api/web_request/web_request_api.cc index 500d885..008b6fc 100644 --- a/chrome/browser/extensions/api/web_request/web_request_api.cc +++ b/chrome/browser/extensions/api/web_request/web_request_api.cc @@ -1181,9 +1181,9 @@ bool ExtensionWebRequestEventRouter::DispatchEvent( std::string delegate_info = l10n_util::GetStringFUTF8(IDS_LOAD_STATE_PARAMETER_EXTENSION, UTF8ToUTF16((*it)->extension_name)); - request->SetDelegateInfo( - delegate_info.c_str(), - net::URLRequest::DELEGATE_INFO_DISPLAY_TO_USER); + // LobAndReport allows extensions that block requests to be displayed in + // the load status bar. + request->LogAndReportBlockedBy(delegate_info.c_str()); } ++num_handlers_blocking; } @@ -1750,8 +1750,7 @@ void ExtensionWebRequestEventRouter::DecrementBlockCount( } if (num_handlers_blocking == 0) { - blocked_request.request->SetDelegateInfo( - NULL, net::URLRequest::DELEGATE_INFO_DEBUG_ONLY); + blocked_request.request->LogUnblocked(); ExecuteDeltas(profile, request_id, true); } else { // Update the URLRequest to make sure it's tagged with an extension that's @@ -1765,9 +1764,7 @@ void ExtensionWebRequestEventRouter::DecrementBlockCount( std::string delegate_info = l10n_util::GetStringFUTF8(IDS_LOAD_STATE_PARAMETER_EXTENSION, UTF8ToUTF16(it->extension_name)); - blocked_request.request->SetDelegateInfo( - delegate_info.c_str(), - net::URLRequest::DELEGATE_INFO_DISPLAY_TO_USER); + blocked_request.request->LogAndReportBlockedBy(delegate_info.c_str()); break; } } diff --git a/chrome/browser/extensions/user_script_listener.cc b/chrome/browser/extensions/user_script_listener.cc index b04b326..7102e36 100644 --- a/chrome/browser/extensions/user_script_listener.cc +++ b/chrome/browser/extensions/user_script_listener.cc @@ -46,6 +46,10 @@ class UserScriptListener::Throttle } } + virtual const char* GetNameForLogging() const OVERRIDE { + return "UserScriptListener::Throttle"; + } + private: bool should_defer_; bool did_defer_; diff --git a/chrome/browser/managed_mode/managed_mode_resource_throttle.cc b/chrome/browser/managed_mode/managed_mode_resource_throttle.cc index 03f41a1..001508d 100644 --- a/chrome/browser/managed_mode/managed_mode_resource_throttle.cc +++ b/chrome/browser/managed_mode/managed_mode_resource_throttle.cc @@ -57,6 +57,10 @@ void ManagedModeResourceThrottle::WillRedirectRequest(const GURL& new_url, ShowInterstitialIfNeeded(true, new_url, defer); } +const char* ManagedModeResourceThrottle::GetNameForLogging() const { + return "ManagedModeResourceThrottle"; +} + void ManagedModeResourceThrottle::OnInterstitialResult(bool continue_request) { if (continue_request) controller()->Resume(); diff --git a/chrome/browser/managed_mode/managed_mode_resource_throttle.h b/chrome/browser/managed_mode/managed_mode_resource_throttle.h index b4b8f5a..6cd17ee 100644 --- a/chrome/browser/managed_mode/managed_mode_resource_throttle.h +++ b/chrome/browser/managed_mode/managed_mode_resource_throttle.h @@ -28,6 +28,8 @@ class ManagedModeResourceThrottle : public content::ResourceThrottle { virtual void WillRedirectRequest(const GURL& new_url, bool* defer) OVERRIDE; + virtual const char* GetNameForLogging() const OVERRIDE; + private: void ShowInterstitialIfNeeded(bool is_redirect, const GURL& url, diff --git a/chrome/browser/prerender/prerender_pending_swap_throttle.cc b/chrome/browser/prerender/prerender_pending_swap_throttle.cc index 23b7ae59..b1a3455 100644 --- a/chrome/browser/prerender/prerender_pending_swap_throttle.cc +++ b/chrome/browser/prerender/prerender_pending_swap_throttle.cc @@ -47,6 +47,10 @@ void PrerenderPendingSwapThrottle::WillStartRequest(bool* defer) { this->AsWeakPtr()); } +const char* PrerenderPendingSwapThrottle::GetNameForLogging() const { + return "PrerenderPendingSwapThrottle"; +} + void PrerenderPendingSwapThrottle::Resume() { DCHECK(throttled_); diff --git a/chrome/browser/prerender/prerender_pending_swap_throttle.h b/chrome/browser/prerender/prerender_pending_swap_throttle.h index 8165871..ebc3e1a 100644 --- a/chrome/browser/prerender/prerender_pending_swap_throttle.h +++ b/chrome/browser/prerender/prerender_pending_swap_throttle.h @@ -33,6 +33,8 @@ class PrerenderPendingSwapThrottle // content::ResourceThrottle implementation: virtual void WillStartRequest(bool* defer) OVERRIDE; + virtual const char* GetNameForLogging() const OVERRIDE; + // Called by the PrerenderTracker when the swap failed. // May only be called if currently throttling the resource. void Resume(); diff --git a/chrome/browser/prerender/prerender_resource_throttle.cc b/chrome/browser/prerender/prerender_resource_throttle.cc index 045d40e..8499c0c 100644 --- a/chrome/browser/prerender/prerender_resource_throttle.cc +++ b/chrome/browser/prerender/prerender_resource_throttle.cc @@ -112,6 +112,10 @@ void PrerenderResourceThrottle::WillRedirectRequest(const GURL& new_url, this->AsWeakPtr()); } +const char* PrerenderResourceThrottle::GetNameForLogging() const { + return "PrerenderResourceThrottle"; +} + void PrerenderResourceThrottle::Resume() { DCHECK(throttled_); diff --git a/chrome/browser/prerender/prerender_resource_throttle.h b/chrome/browser/prerender/prerender_resource_throttle.h index 63f2cd0..3ac4c5e 100644 --- a/chrome/browser/prerender/prerender_resource_throttle.h +++ b/chrome/browser/prerender/prerender_resource_throttle.h @@ -34,6 +34,7 @@ class PrerenderResourceThrottle // content::ResourceThrottle implementation: virtual void WillStartRequest(bool* defer) OVERRIDE; virtual void WillRedirectRequest(const GURL& new_url, bool* defer) OVERRIDE; + virtual const char* GetNameForLogging() const OVERRIDE; // Called by the PrerenderTracker when a prerender becomes visible. // May only be called if currently throttling the resource. diff --git a/chrome/browser/renderer_host/offline_resource_throttle.cc b/chrome/browser/renderer_host/offline_resource_throttle.cc index 4613437..598debd 100644 --- a/chrome/browser/renderer_host/offline_resource_throttle.cc +++ b/chrome/browser/renderer_host/offline_resource_throttle.cc @@ -103,6 +103,10 @@ void OfflineResourceThrottle::WillStartRequest(bool* defer) { *defer = true; } +const char* OfflineResourceThrottle::GetNameForLogging() const { + return "OfflineResourceThrottle"; +} + void OfflineResourceThrottle::OnBlockingPageComplete(bool proceed) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); diff --git a/chrome/browser/renderer_host/offline_resource_throttle.h b/chrome/browser/renderer_host/offline_resource_throttle.h index 95d8674..a78fadc 100644 --- a/chrome/browser/renderer_host/offline_resource_throttle.h +++ b/chrome/browser/renderer_host/offline_resource_throttle.h @@ -31,6 +31,7 @@ class OfflineResourceThrottle // content::ResourceThrottle implementation: virtual void WillStartRequest(bool* defer) OVERRIDE; + virtual const char* GetNameForLogging() const OVERRIDE; private: // OfflineLoadPage callback. diff --git a/chrome/browser/renderer_host/safe_browsing_resource_throttle.cc b/chrome/browser/renderer_host/safe_browsing_resource_throttle.cc index 4427ca0bd..e5cebb1 100644 --- a/chrome/browser/renderer_host/safe_browsing_resource_throttle.cc +++ b/chrome/browser/renderer_host/safe_browsing_resource_throttle.cc @@ -71,6 +71,10 @@ void SafeBrowsingResourceThrottle::WillRedirectRequest(const GURL& new_url, *defer = true; } +const char* SafeBrowsingResourceThrottle::GetNameForLogging() const { + return "SafeBrowsingResourceThrottle"; +} + // SafeBrowsingService::Client implementation, called on the IO thread once // the URL has been classified. void SafeBrowsingResourceThrottle::OnCheckBrowseUrlResult( diff --git a/chrome/browser/renderer_host/safe_browsing_resource_throttle.h b/chrome/browser/renderer_host/safe_browsing_resource_throttle.h index 88ec0e4..45483c1 100644 --- a/chrome/browser/renderer_host/safe_browsing_resource_throttle.h +++ b/chrome/browser/renderer_host/safe_browsing_resource_throttle.h @@ -55,6 +55,7 @@ class SafeBrowsingResourceThrottle // content::ResourceThrottle implementation (called on IO thread): virtual void WillStartRequest(bool* defer) OVERRIDE; virtual void WillRedirectRequest(const GURL& new_url, bool* defer) OVERRIDE; + virtual const char* GetNameForLogging() const OVERRIDE; // SafeBrowsingDabaseManager::Client implementation (called on IO thread): virtual void OnCheckBrowseUrlResult( diff --git a/chrome/browser/ui/webui/net_internals/net_internals_ui.cc b/chrome/browser/ui/webui/net_internals/net_internals_ui.cc index 427a0a3..2f40b4d 100644 --- a/chrome/browser/ui/webui/net_internals/net_internals_ui.cc +++ b/chrome/browser/ui/webui/net_internals/net_internals_ui.cc @@ -150,52 +150,9 @@ bool Base64StringToHashes(const std::string& hashes_str, // Returns a Value representing the state of a pre-existing URLRequest when // net-internals was opened. -Value* RequestStateToValue(const net::URLRequest* request, - net::NetLog::LogLevel log_level) { - DictionaryValue* dict = new DictionaryValue(); - dict->SetString("url", request->original_url().possibly_invalid_spec()); - - const std::vector<GURL>& url_chain = request->url_chain(); - if (url_chain.size() > 1) { - ListValue* list = new ListValue(); - for (std::vector<GURL>::const_iterator url = url_chain.begin(); - url != url_chain.end(); ++url) { - list->AppendString(url->spec()); - } - dict->Set("url_chain", list); - } - - dict->SetInteger("load_flags", request->load_flags()); - - net::LoadStateWithParam load_state = request->GetLoadState(); - dict->SetInteger("load_state", load_state.state); - if (!load_state.param.empty()) - dict->SetString("load_state_param", load_state.param); - - dict->SetString("method", request->method()); - dict->SetBoolean("has_upload", request->has_upload()); - dict->SetBoolean("is_pending", request->is_pending()); - - // Add the status of the request. The status should always be IO_PENDING, and - // the error should always be OK, unless something is holding onto a request - // that has finished or a request was leaked. Neither of these should happen. - switch (request->status().status()) { - case net::URLRequestStatus::SUCCESS: - dict->SetString("status", "SUCCESS"); - break; - case net::URLRequestStatus::IO_PENDING: - dict->SetString("status", "IO_PENDING"); - break; - case net::URLRequestStatus::CANCELED: - dict->SetString("status", "CANCELED"); - break; - case net::URLRequestStatus::FAILED: - dict->SetString("status", "FAILED"); - break; - } - if (request->status().error() != net::OK) - dict->SetInteger("net_error", request->status().error()); - return dict; +Value* GetRequestStateAsValue(const net::URLRequest* request, + net::NetLog::LogLevel log_level) { + return request->GetStateAsValue(); } // Returns true if |request1| was created before |request2|. @@ -1816,7 +1773,7 @@ void NetInternalsMessageHandler::IOThreadImpl::PrePopulateEventList() { request_it != requests.end(); ++request_it) { const net::URLRequest* request = *request_it; net::NetLog::ParametersCallback callback = - base::Bind(&RequestStateToValue, base::Unretained(request)); + base::Bind(&GetRequestStateAsValue, base::Unretained(request)); // Create and add the entry directly, to avoid sending it to any other // NetLog observers. diff --git a/components/navigation_interception/intercept_navigation_resource_throttle.cc b/components/navigation_interception/intercept_navigation_resource_throttle.cc index 73513ef..3cbdad6 100644 --- a/components/navigation_interception/intercept_navigation_resource_throttle.cc +++ b/components/navigation_interception/intercept_navigation_resource_throttle.cc @@ -80,6 +80,10 @@ void InterceptNavigationResourceThrottle::WillRedirectRequest( CheckIfShouldIgnoreNavigation(new_url, GetMethodAfterRedirect(), true); } +const char* InterceptNavigationResourceThrottle::GetNameForLogging() const { + return "InterceptNavigationResourceThrottle"; +} + std::string InterceptNavigationResourceThrottle::GetMethodAfterRedirect() { net::HttpResponseHeaders* headers = request_->response_headers(); if (!headers) diff --git a/components/navigation_interception/intercept_navigation_resource_throttle.h b/components/navigation_interception/intercept_navigation_resource_throttle.h index 79ed57e..f4d2bf7 100644 --- a/components/navigation_interception/intercept_navigation_resource_throttle.h +++ b/components/navigation_interception/intercept_navigation_resource_throttle.h @@ -42,6 +42,7 @@ class InterceptNavigationResourceThrottle : public content::ResourceThrottle { // content::ResourceThrottle implementation: virtual void WillStartRequest(bool* defer) OVERRIDE; virtual void WillRedirectRequest(const GURL& new_url, bool* defer) OVERRIDE; + virtual const char* GetNameForLogging() const OVERRIDE; private: std::string GetMethodAfterRedirect(); diff --git a/content/browser/loader/async_resource_handler.cc b/content/browser/loader/async_resource_handler.cc index 5983052..93d7e83 100644 --- a/content/browser/loader/async_resource_handler.cc +++ b/content/browser/loader/async_resource_handler.cc @@ -151,6 +151,7 @@ bool AsyncResourceHandler::OnRequestRedirected(int request_id, return false; *defer = did_defer_ = true; + OnDefer(); if (rdh_->delegate()) { rdh_->delegate()->OnRequestRedirected( @@ -287,6 +288,7 @@ bool AsyncResourceHandler::OnReadCompleted(int request_id, int bytes_read, "Net.AsyncResourceHandler_PendingDataCount_WhenFull", pending_data_count_, 0, 100, 100); *defer = did_defer_ = true; + OnDefer(); } return true; @@ -377,8 +379,13 @@ bool AsyncResourceHandler::EnsureResourceBufferIsInitialized() { void AsyncResourceHandler::ResumeIfDeferred() { if (did_defer_) { did_defer_ = false; + request()->LogUnblocked(); controller()->Resume(); } } +void AsyncResourceHandler::OnDefer() { + request()->LogBlockedBy("AsyncResourceHandler"); +} + } // namespace content diff --git a/content/browser/loader/async_resource_handler.h b/content/browser/loader/async_resource_handler.h index ac15b59..f603f4f 100644 --- a/content/browser/loader/async_resource_handler.h +++ b/content/browser/loader/async_resource_handler.h @@ -72,6 +72,7 @@ class AsyncResourceHandler : public ResourceHandler, bool EnsureResourceBufferIsInitialized(); void ResumeIfDeferred(); + void OnDefer(); scoped_refptr<ResourceBuffer> buffer_; ResourceDispatcherHostImpl* rdh_; diff --git a/content/browser/loader/power_save_block_resource_throttle.cc b/content/browser/loader/power_save_block_resource_throttle.cc index d9b843c..7a084b0 100644 --- a/content/browser/loader/power_save_block_resource_throttle.cc +++ b/content/browser/loader/power_save_block_resource_throttle.cc @@ -34,6 +34,10 @@ void PowerSaveBlockResourceThrottle::WillProcessResponse(bool* defer) { timer_.Stop(); } +const char* PowerSaveBlockResourceThrottle::GetNameForLogging() const { + return "PowerSaveBlockResourceThrottle"; +} + void PowerSaveBlockResourceThrottle::ActivatePowerSaveBlocker() { power_save_blocker_ = PowerSaveBlocker::Create( PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension, diff --git a/content/browser/loader/power_save_block_resource_throttle.h b/content/browser/loader/power_save_block_resource_throttle.h index e94b542..2a4f9b3 100644 --- a/content/browser/loader/power_save_block_resource_throttle.h +++ b/content/browser/loader/power_save_block_resource_throttle.h @@ -24,6 +24,7 @@ class PowerSaveBlockResourceThrottle : public ResourceThrottle { // ResourceThrottle overrides: virtual void WillStartRequest(bool* defer) OVERRIDE; virtual void WillProcessResponse(bool* defer) OVERRIDE; + virtual const char* GetNameForLogging() const OVERRIDE; private: void ActivatePowerSaveBlocker(); diff --git a/content/browser/loader/resource_dispatcher_host_unittest.cc b/content/browser/loader/resource_dispatcher_host_unittest.cc index 895951b..52d3432 100644 --- a/content/browser/loader/resource_dispatcher_host_unittest.cc +++ b/content/browser/loader/resource_dispatcher_host_unittest.cc @@ -441,6 +441,10 @@ class GenericResourceThrottle : public ResourceThrottle { } } + virtual const char* GetNameForLogging() const OVERRIDE { + return "GenericResourceThrottle"; + } + void Resume() { ASSERT_TRUE(this == active_throttle_); active_throttle_ = NULL; diff --git a/content/browser/loader/resource_scheduler.cc b/content/browser/loader/resource_scheduler.cc index 9d05476..d24e484 100644 --- a/content/browser/loader/resource_scheduler.cc +++ b/content/browser/loader/resource_scheduler.cc @@ -159,6 +159,10 @@ class ResourceScheduler::ScheduledResourceRequest deferred_ = *defer = !ready_; } + virtual const char* GetNameForLogging() const OVERRIDE { + return "ResourceScheduler"; + } + void DidChangePriority(int request_id, net::RequestPriority new_priority) { scheduler_->ReprioritizeRequest(this, new_priority); } diff --git a/content/browser/loader/throttling_resource_handler.cc b/content/browser/loader/throttling_resource_handler.cc index 23f77da..36c595f 100644 --- a/content/browser/loader/throttling_resource_handler.cc +++ b/content/browser/loader/throttling_resource_handler.cc @@ -7,6 +7,7 @@ #include "content/browser/loader/resource_request_info_impl.h" #include "content/public/browser/resource_throttle.h" #include "content/public/common/resource_response.h" +#include "net/url_request/url_request.h" namespace content { @@ -17,10 +18,14 @@ ThrottlingResourceHandler::ThrottlingResourceHandler( : LayeredResourceHandler(request, next_handler.Pass()), deferred_stage_(DEFERRED_NONE), throttles_(throttles.Pass()), - index_(0), + next_index_(0), cancelled_by_resource_throttle_(false) { - for (size_t i = 0; i < throttles_.size(); ++i) + for (size_t i = 0; i < throttles_.size(); ++i) { throttles_[i]->set_controller(this); + // Throttles must have a name, as otherwise, bugs where a throttle fails + // to resume a request can be very difficult to debug. + DCHECK(throttles_[i]->GetNameForLogging()); + } } ThrottlingResourceHandler::~ThrottlingResourceHandler() { @@ -33,12 +38,14 @@ bool ThrottlingResourceHandler::OnRequestRedirected(int request_id, DCHECK(!cancelled_by_resource_throttle_); *defer = false; - while (index_ < throttles_.size()) { - throttles_[index_]->WillRedirectRequest(new_url, defer); - index_++; + while (next_index_ < throttles_.size()) { + int index = next_index_; + throttles_[index]->WillRedirectRequest(new_url, defer); + next_index_++; if (cancelled_by_resource_throttle_) return false; if (*defer) { + OnRequestDefered(index); deferred_stage_ = DEFERRED_REDIRECT; deferred_url_ = new_url; deferred_response_ = response; @@ -46,7 +53,7 @@ bool ThrottlingResourceHandler::OnRequestRedirected(int request_id, } } - index_ = 0; // Reset for next time. + next_index_ = 0; // Reset for next time. return next_handler_->OnRequestRedirected(request_id, new_url, response, defer); @@ -58,19 +65,21 @@ bool ThrottlingResourceHandler::OnWillStart(int request_id, DCHECK(!cancelled_by_resource_throttle_); *defer = false; - while (index_ < throttles_.size()) { - throttles_[index_]->WillStartRequest(defer); - index_++; + while (next_index_ < throttles_.size()) { + int index = next_index_; + throttles_[index]->WillStartRequest(defer); + next_index_++; if (cancelled_by_resource_throttle_) return false; if (*defer) { + OnRequestDefered(index); deferred_stage_ = DEFERRED_START; deferred_url_ = url; return true; // Do not cancel. } } - index_ = 0; // Reset for next time. + next_index_ = 0; // Reset for next time. return next_handler_->OnWillStart(request_id, url, defer); } @@ -80,19 +89,21 @@ bool ThrottlingResourceHandler::OnResponseStarted(int request_id, bool* defer) { DCHECK(!cancelled_by_resource_throttle_); - while (index_ < throttles_.size()) { - throttles_[index_]->WillProcessResponse(defer); - index_++; + while (next_index_ < throttles_.size()) { + int index = next_index_; + throttles_[index]->WillProcessResponse(defer); + next_index_++; if (cancelled_by_resource_throttle_) return false; if (*defer) { + OnRequestDefered(index); deferred_stage_ = DEFERRED_RESPONSE; deferred_response_ = response; return true; // Do not cancel. } } - index_ = 0; // Reset for next time. + next_index_ = 0; // Reset for next time. return next_handler_->OnResponseStarted(request_id, response, defer); } @@ -117,6 +128,8 @@ void ThrottlingResourceHandler::Resume() { DeferredStage last_deferred_stage = deferred_stage_; deferred_stage_ = DEFERRED_NONE; + // Clear information about the throttle that delayed the request. + request()->LogUnblocked(); switch (last_deferred_stage) { case DEFERRED_NONE: NOTREACHED(); @@ -177,4 +190,8 @@ void ThrottlingResourceHandler::ResumeResponse() { } } +void ThrottlingResourceHandler::OnRequestDefered(int throttle_index) { + request()->LogBlockedBy(throttles_[throttle_index]->GetNameForLogging()); +} + } // namespace content diff --git a/content/browser/loader/throttling_resource_handler.h b/content/browser/loader/throttling_resource_handler.h index 65117bc..9f98921 100644 --- a/content/browser/loader/throttling_resource_handler.h +++ b/content/browser/loader/throttling_resource_handler.h @@ -40,7 +40,7 @@ class ThrottlingResourceHandler : public LayeredResourceHandler, virtual bool OnWillStart(int request_id, const GURL& url, bool* defer) OVERRIDE; - // ResourceThrottleController implementation: + // ResourceController implementation: virtual void Cancel() OVERRIDE; virtual void CancelAndIgnore() OVERRIDE; virtual void CancelWithError(int error_code) OVERRIDE; @@ -51,6 +51,10 @@ class ThrottlingResourceHandler : public LayeredResourceHandler, void ResumeRedirect(); void ResumeResponse(); + // Called when the throttle at |throttle_index| defers a request. Logs the + // name of the throttle that delayed the request. + void OnRequestDefered(int throttle_index); + enum DeferredStage { DEFERRED_NONE, DEFERRED_START, @@ -60,7 +64,7 @@ class ThrottlingResourceHandler : public LayeredResourceHandler, DeferredStage deferred_stage_; ScopedVector<ResourceThrottle> throttles_; - size_t index_; + size_t next_index_; GURL deferred_url_; scoped_refptr<ResourceResponse> deferred_response_; diff --git a/content/public/browser/resource_throttle.h b/content/public/browser/resource_throttle.h index 4eb3bd7..7bcab88 100644 --- a/content/public/browser/resource_throttle.h +++ b/content/public/browser/resource_throttle.h @@ -26,6 +26,11 @@ class ResourceThrottle { virtual void WillRedirectRequest(const GURL& new_url, bool* defer) {} virtual void WillProcessResponse(bool* defer) {} + // Returns the name of the throttle, as a UTF-8 C-string, for logging + // purposes. NULL is not allowed. Caller does *not* take ownership of the + // returned string. + virtual const char* GetNameForLogging() const = 0; + void set_controller_for_testing(ResourceController* c) { controller_ = c; } diff --git a/net/url_request/url_request.cc b/net/url_request/url_request.cc index 2e4ec57..6b01247 100644 --- a/net/url_request/url_request.cc +++ b/net/url_request/url_request.cc @@ -219,7 +219,7 @@ URLRequest::URLRequest(const GURL& url, priority_(priority), identifier_(GenerateURLRequestIdentifier()), calling_delegate_(false), - delegate_info_usage_(DELEGATE_INFO_DEBUG_ONLY), + use_blocked_by_as_load_param_(false), before_request_callback_(base::Bind(&URLRequest::BeforeRequestComplete, base::Unretained(this))), has_notified_completion_(false), @@ -347,13 +347,13 @@ bool URLRequest::GetFullRequestHeaders(HttpRequestHeaders* headers) const { } LoadStateWithParam URLRequest::GetLoadState() const { - // The delegate_info_.empty() check allows |this| to report it's blocked on - // a delegate before it has been started. - if (calling_delegate_ || !delegate_info_.empty()) { + // The !blocked_by_.empty() check allows |this| to report it's blocked on a + // delegate before it has been started. + if (calling_delegate_ || !blocked_by_.empty()) { return LoadStateWithParam( LOAD_STATE_WAITING_FOR_DELEGATE, - delegate_info_usage_ == DELEGATE_INFO_DISPLAY_TO_USER ? - UTF8ToUTF16(delegate_info_) : base::string16()); + use_blocked_by_as_load_param_ ? UTF8ToUTF16(blocked_by_) : + base::string16()); } return LoadStateWithParam(job_.get() ? job_->GetLoadState() : LOAD_STATE_IDLE, base::string16()); @@ -378,8 +378,8 @@ base::Value* URLRequest::GetStateAsValue() const { dict->SetInteger("load_state", load_state.state); if (!load_state.param.empty()) dict->SetString("load_state_param", load_state.param); - if (!delegate_info_.empty()) - dict->SetString("delegate_info", delegate_info_); + if (!blocked_by_.empty()) + dict->SetString("delegate_info", blocked_by_); dict->SetString("method", method_); dict->SetBoolean("has_upload", has_upload()); @@ -407,25 +407,35 @@ base::Value* URLRequest::GetStateAsValue() const { return dict; } -void URLRequest::SetDelegateInfo(const char* delegate_info, - DelegateInfoUsage delegate_info_usage) { - // Only log delegate information to NetLog during startup and certain - // deferring calls to delegates. For all reads but the first, delegate info - // is currently ignored. +void URLRequest::LogBlockedBy(const char* blocked_by) { + DCHECK(blocked_by); + DCHECK_GT(strlen(blocked_by), 0u); + + // Only log information to NetLog during startup and certain deferring calls + // to delegates. For all reads but the first, do nothing. if (!calling_delegate_ && !response_info_.request_time.is_null()) return; - if (!delegate_info_.empty()) { - delegate_info_.clear(); - net_log_.EndEvent(NetLog::TYPE_DELEGATE_INFO); - } - if (delegate_info) { - delegate_info_ = delegate_info; - delegate_info_usage_ = delegate_info_usage; - net_log_.BeginEvent( - NetLog::TYPE_DELEGATE_INFO, - NetLog::StringCallback("delegate_info", &delegate_info_)); - } + LogUnblocked(); + blocked_by_ = blocked_by; + use_blocked_by_as_load_param_ = false; + + net_log_.BeginEvent( + NetLog::TYPE_DELEGATE_INFO, + NetLog::StringCallback("delegate_info", &blocked_by_)); +} + +void URLRequest::LogAndReportBlockedBy(const char* source) { + LogBlockedBy(source); + use_blocked_by_as_load_param_ = true; +} + +void URLRequest::LogUnblocked() { + if (blocked_by_.empty()) + return; + + net_log_.EndEvent(NetLog::TYPE_DELEGATE_INFO); + blocked_by_.clear(); } UploadProgress URLRequest::GetUploadProgress() const { @@ -593,9 +603,9 @@ void URLRequest::set_delegate(Delegate* delegate) { void URLRequest::Start() { DCHECK_EQ(network_delegate_, context_->network_delegate()); - // Anything that set delegate information before start should have cleaned up - // after itself. - DCHECK(delegate_info_.empty()); + // Anything that sets |blocked_by_| before start should have cleaned up after + // itself. + DCHECK(blocked_by_.empty()); g_url_requests_started = true; response_info_.request_time = base::Time::Now(); @@ -715,7 +725,7 @@ void URLRequest::DoCancel(int error, const SSLInfo& ssl_info) { DCHECK(error < 0); // If cancelled while calling a delegate, clear delegate info. if (calling_delegate_) { - SetDelegateInfo(NULL, DELEGATE_INFO_DEBUG_ONLY); + LogUnblocked(); OnCallToDelegateComplete(); } @@ -1162,14 +1172,14 @@ void URLRequest::NotifyRequestCompleted() { void URLRequest::OnCallToDelegate() { DCHECK(!calling_delegate_); - DCHECK(delegate_info_.empty()); + DCHECK(blocked_by_.empty()); calling_delegate_ = true; net_log_.BeginEvent(NetLog::TYPE_URL_REQUEST_DELEGATE); } void URLRequest::OnCallToDelegateComplete() { - // Delegates should clear their info when it becomes outdated. - DCHECK(delegate_info_.empty()); + // This should have been cleared before resuming the request. + DCHECK(blocked_by_.empty()); if (!calling_delegate_) return; calling_delegate_ = false; diff --git a/net/url_request/url_request.h b/net/url_request/url_request.h index 606653c..84f5050 100644 --- a/net/url_request/url_request.h +++ b/net/url_request/url_request.h @@ -135,15 +135,6 @@ class NET_EXPORT URLRequest : NON_EXPORTED_BASE(public base::NonThreadSafe), NEVER_CLEAR_REFERRER, }; - // Used with SetDelegateInfo to indicate how the string should be used. - // DELEGATE_INFO_DEBUG_ONLY indicates it should only be used when logged to - // NetLog, while DELEGATE_INFO_DISPLAY_TO_USER indicates it should also be - // returned by calls to GetLoadState for display to the user. - enum DelegateInfoUsage { - DELEGATE_INFO_DEBUG_ONLY, - DELEGATE_INFO_DISPLAY_TO_USER, - }; - // This class handles network interception. Use with // (Un)RegisterRequestInterceptor. class NET_EXPORT Interceptor { @@ -447,23 +438,31 @@ class NET_EXPORT URLRequest : NON_EXPORTED_BASE(public base::NonThreadSafe), // 2. The OnResponseStarted callback is currently running or has run. bool GetFullRequestHeaders(HttpRequestHeaders* headers) const; - // Returns the current load state for the request. |param| is an optional - // parameter describing details related to the load state. Not all load states - // have a parameter. + // Returns the current load state for the request. The returned value's + // |param| field is an optional parameter describing details related to the + // load state. Not all load states have a parameter. LoadStateWithParam GetLoadState() const; // Returns a partial representation of the request's state as a value, for // debugging. Caller takes ownership of returned value. base::Value* GetStateAsValue() const; - // Logs information about the delegate currently blocking the request. - // The delegate info must be cleared by sending NULL before resuming a - // request. |delegate_info| will be copied as needed. |delegate_info_usage| - // is used to indicate whether the value should be returned in the param field - // of GetLoadState. |delegate_info_usage_| is ignored when |delegate_info| is - // NULL. - void SetDelegateInfo(const char* delegate_info, - DelegateInfoUsage delegate_info_usage); + // Logs information about the what external object currently blocking the + // request. LogUnblocked must be called before resuming the request. This + // can be called multiple times in a row either with or without calling + // LogUnblocked between calls. |blocked_by| must not be NULL or have length + // 0. + void LogBlockedBy(const char* blocked_by); + + // Just like LogBlockedBy, but also makes GetLoadState return source as the + // |param| in the value returned by GetLoadState. Calling LogUnblocked or + // LogBlockedBy will clear the load param. |blocked_by| must not be NULL or + // have length 0. + void LogAndReportBlockedBy(const char* blocked_by); + + // Logs that the request is no longer blocked by the last caller to + // LogBlockedBy. + void LogUnblocked(); // Returns the current upload progress in bytes. When the upload data is // chunked, size is set to zero, but position will not be. @@ -851,10 +850,10 @@ class NET_EXPORT URLRequest : NON_EXPORTED_BASE(public base::NonThreadSafe), // for the URL request or network delegate to resume it. bool calling_delegate_; - // An optional parameter that provides additional information about the - // delegate |this| is currently blocked on. - std::string delegate_info_; - DelegateInfoUsage delegate_info_usage_; + // An optional parameter that provides additional information about what + // |this| is currently being blocked by. + std::string blocked_by_; + bool use_blocked_by_as_load_param_; base::debug::LeakTracker<URLRequest> leak_tracker_; diff --git a/net/url_request/url_request_unittest.cc b/net/url_request/url_request_unittest.cc index 6b53b41..d22d24f 100644 --- a/net/url_request/url_request_unittest.cc +++ b/net/url_request/url_request_unittest.cc @@ -3843,8 +3843,7 @@ class AsyncDelegateLogger : public base::RefCounted<AsyncDelegateLogger> { ~AsyncDelegateLogger() {} void Start() { - url_request_->SetDelegateInfo(kFirstDelegateInfo, - URLRequest::DELEGATE_INFO_DEBUG_ONLY); + url_request_->LogBlockedBy(kFirstDelegateInfo); LoadStateWithParam load_state = url_request_->GetLoadState(); EXPECT_EQ(expected_first_load_state_, load_state.state); EXPECT_NE(ASCIIToUTF16(kFirstDelegateInfo), load_state.param); @@ -3854,8 +3853,7 @@ class AsyncDelegateLogger : public base::RefCounted<AsyncDelegateLogger> { } void LogSecondDelegate() { - url_request_->SetDelegateInfo(kSecondDelegateInfo, - URLRequest::DELEGATE_INFO_DISPLAY_TO_USER); + url_request_->LogAndReportBlockedBy(kSecondDelegateInfo); LoadStateWithParam load_state = url_request_->GetLoadState(); EXPECT_EQ(expected_second_load_state_, load_state.state); if (expected_second_load_state_ == LOAD_STATE_WAITING_FOR_DELEGATE) { @@ -3869,8 +3867,7 @@ class AsyncDelegateLogger : public base::RefCounted<AsyncDelegateLogger> { } void LogComplete() { - url_request_->SetDelegateInfo( - NULL, URLRequest::DELEGATE_INFO_DISPLAY_TO_USER); + url_request_->LogUnblocked(); LoadStateWithParam load_state = url_request_->GetLoadState(); EXPECT_EQ(expected_third_load_state_, load_state.state); if (expected_second_load_state_ == LOAD_STATE_WAITING_FOR_DELEGATE) |