diff options
Diffstat (limited to 'chromium/chrome/browser/devtools/devtools_ui_bindings.cc')
-rw-r--r-- | chromium/chrome/browser/devtools/devtools_ui_bindings.cc | 146 |
1 files changed, 110 insertions, 36 deletions
diff --git a/chromium/chrome/browser/devtools/devtools_ui_bindings.cc b/chromium/chrome/browser/devtools/devtools_ui_bindings.cc index 1acc82d6f38..b43e8b7f7fc 100644 --- a/chromium/chrome/browser/devtools/devtools_ui_bindings.cc +++ b/chromium/chrome/browser/devtools/devtools_ui_bindings.cc @@ -77,6 +77,7 @@ #include "net/traffic_annotation/network_traffic_annotation.h" #include "services/network/public/cpp/simple_url_loader.h" #include "services/network/public/cpp/simple_url_loader_stream_consumer.h" +#include "services/network/public/mojom/url_response_head.mojom.h" #include "third_party/blink/public/mojom/renderer_preferences.mojom.h" #include "third_party/blink/public/public_buildflags.h" #include "ui/base/page_transition_types.h" @@ -199,9 +200,17 @@ InfoBarService* DefaultBindingsDelegate::GetInfoBarService() { } std::unique_ptr<base::DictionaryValue> BuildObjectForResponse( - const net::HttpResponseHeaders* rh) { + const net::HttpResponseHeaders* rh, + bool success) { auto response = std::make_unique<base::DictionaryValue>(); - response->SetInteger("statusCode", rh ? rh->response_code() : 200); + int responseCode = 200; + if (rh) { + responseCode = rh->response_code(); + } else if (!success) { + // In case of no headers, assume file:// URL and failed to load + responseCode = 404; + } + response->SetInteger("statusCode", responseCode); auto headers = std::make_unique<base::DictionaryValue>(); size_t iterator = 0; @@ -312,7 +321,7 @@ std::string SanitizeFrontendQueryParam( // Convert boolean flags to true. if (key == "can_dock" || key == "debugFrontend" || key == "experiments" || key == "isSharedWorker" || key == "v8only" || key == "remoteFrontend" || - key == "nodeFrontend" || key == "hasOtherClients") + key == "nodeFrontend" || key == "hasOtherClients" || key == "uiDevTools") return "true"; // Pass connection endpoints as is. @@ -372,28 +381,86 @@ GURL SanitizeFrontendURL(const GURL& url, return result; } +constexpr base::TimeDelta kInitialBackoffDelay = + base::TimeDelta::FromMilliseconds(250); +constexpr base::TimeDelta kMaxBackoffDelay = base::TimeDelta::FromSeconds(10); + } // namespace class DevToolsUIBindings::NetworkResourceLoader : public network::SimpleURLLoaderStreamConsumer { public: - NetworkResourceLoader(int stream_id, - DevToolsUIBindings* bindings, - std::unique_ptr<network::SimpleURLLoader> loader, - network::mojom::URLLoaderFactory* url_loader_factory, - const DispatchCallback& callback) + class URLLoaderFactoryHolder { + public: + network::mojom::URLLoaderFactory* get() { + return ptr_.get() ? ptr_.get() : refptr_.get(); + } + void operator=(std::unique_ptr<network::mojom::URLLoaderFactory>&& ptr) { + ptr_ = std::move(ptr); + } + void operator=(scoped_refptr<network::SharedURLLoaderFactory>&& refptr) { + refptr_ = std::move(refptr); + } + + private: + std::unique_ptr<network::mojom::URLLoaderFactory> ptr_; + scoped_refptr<network::SharedURLLoaderFactory> refptr_; + }; + + static void Create(int stream_id, + DevToolsUIBindings* bindings, + const network::ResourceRequest& resource_request, + const net::NetworkTrafficAnnotationTag& traffic_annotation, + URLLoaderFactoryHolder url_loader_factory, + const DevToolsUIBindings::DispatchCallback& callback, + base::TimeDelta retry_delay = base::TimeDelta()) { + auto resource_loader = + std::make_unique<DevToolsUIBindings::NetworkResourceLoader>( + stream_id, bindings, resource_request, traffic_annotation, + std::move(url_loader_factory), callback, retry_delay); + bindings->loaders_.insert(std::move(resource_loader)); + } + + NetworkResourceLoader( + int stream_id, + DevToolsUIBindings* bindings, + const network::ResourceRequest& resource_request, + const net::NetworkTrafficAnnotationTag& traffic_annotation, + URLLoaderFactoryHolder url_loader_factory, + const DispatchCallback& callback, + base::TimeDelta delay) : stream_id_(stream_id), bindings_(bindings), - loader_(std::move(loader)), - callback_(callback) { + resource_request_(resource_request), + traffic_annotation_(traffic_annotation), + loader_(network::SimpleURLLoader::Create( + std::make_unique<network::ResourceRequest>(resource_request), + traffic_annotation)), + url_loader_factory_(std::move(url_loader_factory)), + callback_(callback), + retry_delay_(delay) { loader_->SetOnResponseStartedCallback(base::BindOnce( &NetworkResourceLoader::OnResponseStarted, base::Unretained(this))); - loader_->DownloadAsStream(url_loader_factory, this); + timer_.Start(FROM_HERE, delay, + base::BindRepeating(&NetworkResourceLoader::DownloadAsStream, + base::Unretained(this))); } private: + void DownloadAsStream() { + loader_->DownloadAsStream(url_loader_factory_.get(), this); + } + + base::TimeDelta GetNextExponentialBackoffDelay(const base::TimeDelta& delta) { + if (delta.is_zero()) { + return kInitialBackoffDelay; + } else { + return delta * 1.3; + } + } + void OnResponseStarted(const GURL& final_url, - const network::ResourceResponseHead& response_head) { + const network::mojom::URLResponseHead& response_head) { response_headers_ = response_head.headers; } @@ -418,9 +485,21 @@ class DevToolsUIBindings::NetworkResourceLoader } void OnComplete(bool success) override { - auto response = BuildObjectForResponse(response_headers_.get()); - callback_.Run(response.get()); - + if (!success && loader_->NetError() == net::ERR_INSUFFICIENT_RESOURCES && + retry_delay_ < kMaxBackoffDelay) { + const base::TimeDelta delay = + GetNextExponentialBackoffDelay(retry_delay_); + LOG(WARNING) << "DevToolsUIBindings::NetworkResourceLoader id = " + << stream_id_ + << " failed with insufficient resources, retrying in " + << delay << "." << std::endl; + NetworkResourceLoader::Create( + stream_id_, bindings_, resource_request_, traffic_annotation_, + std::move(url_loader_factory_), callback_, delay); + } else { + auto response = BuildObjectForResponse(response_headers_.get(), success); + callback_.Run(response.get()); + } bindings_->loaders_.erase(bindings_->loaders_.find(this)); } @@ -428,9 +507,14 @@ class DevToolsUIBindings::NetworkResourceLoader const int stream_id_; DevToolsUIBindings* const bindings_; + const network::ResourceRequest resource_request_; + const net::NetworkTrafficAnnotationTag traffic_annotation_; std::unique_ptr<network::SimpleURLLoader> loader_; + URLLoaderFactoryHolder url_loader_factory_; DispatchCallback callback_; scoped_refptr<net::HttpResponseHeaders> response_headers_; + base::OneShotTimer timer_; + base::TimeDelta retry_delay_; DISALLOW_COPY_AND_ASSIGN(NetworkResourceLoader); }; @@ -738,22 +822,18 @@ void DevToolsUIBindings::LoadNetworkResource(const DispatchCallback& callback, } })"); - auto resource_request = std::make_unique<network::ResourceRequest>(); - resource_request->url = gurl; + network::ResourceRequest resource_request; + resource_request.url = gurl; // TODO(caseq): this preserves behavior of URLFetcher-based implementation. // We really need to pass proper first party origin from the front-end. - resource_request->site_for_cookies = gurl; - resource_request->headers.AddHeadersFromString(headers); + resource_request.site_for_cookies = gurl; + resource_request.headers.AddHeadersFromString(headers); - std::unique_ptr<network::mojom::URLLoaderFactory> file_url_loader_factory; - scoped_refptr<network::SharedURLLoaderFactory> network_url_loader_factory; - std::unique_ptr<network::mojom::URLLoaderFactory> webui_url_loader_factory; - network::mojom::URLLoaderFactory* url_loader_factory; + NetworkResourceLoader::URLLoaderFactoryHolder url_loader_factory; if (gurl.SchemeIsFile()) { - file_url_loader_factory = content::CreateFileURLLoaderFactory( + url_loader_factory = content::CreateFileURLLoaderFactory( base::FilePath() /* profile_path */, nullptr /* shared_cors_origin_access_list */); - url_loader_factory = file_url_loader_factory.get(); } else if (content::HasWebUIScheme(gurl)) { content::WebContents* target_tab; #ifndef NDEBUG @@ -769,10 +849,9 @@ void DevToolsUIBindings::LoadNetworkResource(const DispatchCallback& callback, if (allow_web_ui_scheme) { std::vector<std::string> allowed_webui_hosts; content::RenderFrameHost* frame_host = web_contents()->GetMainFrame(); - webui_url_loader_factory = content::CreateWebUIURLLoader( + url_loader_factory = content::CreateWebUIURLLoader( frame_host, target_tab->GetURL().scheme(), std::move(allowed_webui_hosts)); - url_loader_factory = webui_url_loader_factory.get(); } else { base::DictionaryValue response; response.SetInteger("statusCode", 403); @@ -782,17 +861,12 @@ void DevToolsUIBindings::LoadNetworkResource(const DispatchCallback& callback, } else { auto* partition = content::BrowserContext::GetStoragePartitionForSite( web_contents_->GetBrowserContext(), gurl); - network_url_loader_factory = - partition->GetURLLoaderFactoryForBrowserProcess(); - url_loader_factory = network_url_loader_factory.get(); + url_loader_factory = partition->GetURLLoaderFactoryForBrowserProcess(); } - auto simple_url_loader = network::SimpleURLLoader::Create( - std::move(resource_request), traffic_annotation); - auto resource_loader = std::make_unique<NetworkResourceLoader>( - stream_id, this, std::move(simple_url_loader), url_loader_factory, - callback); - loaders_.insert(std::move(resource_loader)); + NetworkResourceLoader::Create(stream_id, this, resource_request, + traffic_annotation, + std::move(url_loader_factory), callback); } void DevToolsUIBindings::OpenInNewTab(const std::string& url) { |