Chromium Code Reviews| Index: content/browser/loader/navigation_url_loader_network_service.cc |
| diff --git a/content/browser/loader/navigation_url_loader_network_service.cc b/content/browser/loader/navigation_url_loader_network_service.cc |
| index b821082ae37eb74b98d72706a042a7e8d621aaab..f5d43615aa91984bdcb4ae2b08adb7f1023398e3 100644 |
| --- a/content/browser/loader/navigation_url_loader_network_service.cc |
| +++ b/content/browser/loader/navigation_url_loader_network_service.cc |
| @@ -105,7 +105,8 @@ class NavigationURLLoaderNetworkService::URLLoaderRequestController |
| : resource_request_(std::move(resource_request)), |
| resource_context_(resource_context), |
| default_url_loader_factory_getter_(default_url_loader_factory_getter), |
| - owner_(owner) {} |
| + owner_(owner), |
| + response_loader_binding_(this) {} |
| ~URLLoaderRequestController() override { |
| DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| @@ -213,6 +214,7 @@ class NavigationURLLoaderNetworkService::URLLoaderRequestController |
| factory = default_url_loader_factory_getter_->GetBlobFactory()->get(); |
| } else { |
| factory = default_url_loader_factory_getter_->GetNetworkFactory()->get(); |
| + default_loader_used_ = true; |
| } |
| url_loader_ = ThrottlingURLLoader::CreateLoaderAndStart( |
| factory, |
| @@ -242,6 +244,13 @@ class NavigationURLLoaderNetworkService::URLLoaderRequestController |
| const ResourceResponseHead& head, |
| const base::Optional<net::SSLInfo>& ssl_info, |
| mojom::DownloadedTempFilePtr downloaded_file) override { |
| + response_ = head; |
| + // If the default loader (network) was used to handle the URL load request |
| + // we need to see if the handlers want to potentially create a new loader |
| + // for the response. e.g. AppCache. |
| + if (MaybeCreateLoaderForResponse(head)) |
| + return; |
| + |
| BrowserThread::PostTask( |
| BrowserThread::UI, FROM_HERE, |
| base::Bind(&NavigationURLLoaderNetworkService::OnReceiveResponse, |
| @@ -250,6 +259,8 @@ class NavigationURLLoaderNetworkService::URLLoaderRequestController |
| void OnReceiveRedirect(const net::RedirectInfo& redirect_info, |
| const ResourceResponseHead& head) override { |
| + response_ = head; |
| + |
| BrowserThread::PostTask( |
| BrowserThread::UI, FROM_HERE, |
| base::Bind(&NavigationURLLoaderNetworkService::OnReceiveRedirect, |
| @@ -277,12 +288,45 @@ class NavigationURLLoaderNetworkService::URLLoaderRequestController |
| void OnComplete( |
| const ResourceRequestCompletionStatus& completion_status) override { |
| + // If the default loader (network) was used to handle the URL load request |
| + // we need to see if the handlers want to potentially create a new loader |
| + // for the response. e.g. AppCache. |
| + if (MaybeCreateLoaderForResponse(response_)) |
| + return; |
| + |
| BrowserThread::PostTask( |
| BrowserThread::UI, FROM_HERE, |
| base::Bind(&NavigationURLLoaderNetworkService::OnComplete, owner_, |
| completion_status)); |
| } |
| + // Returns true if a handler wants to handle the response, i.e. return a |
| + // different response. For e.g. AppCache may have fallback content to be |
| + // returned for a TLD. |
| + bool MaybeCreateLoaderForResponse(const ResourceResponseHead& response) { |
| + if (!default_loader_used_) |
| + return false; |
|
kinuko
2017/07/28 03:34:51
One question- do we need to keep this here or can
ananta
2017/07/28 22:59:21
I always assumed that fallback was for network req
ananta
2017/07/29 01:21:45
We had talked about it couple weeks back. AppCache
|
| + |
| + for (size_t index = 0; index < handlers_.size(); ++index) { |
| + if (handlers_[index]->MaybeCreateLoaderForResponse( |
| + response, &response_url_loader_, &response_client_request_)) { |
| + OnResponseHandlerFound(); |
| + return true; |
| + } |
| + } |
| + return false; |
| + } |
| + |
| + // Called if we find a handler who delivers different content for the URL. |
| + void OnResponseHandlerFound() { |
| + response_loader_binding_.Bind(std::move(response_client_request_)); |
| + // We reset this flag as we expect a new response from the handler. |
| + default_loader_used_ = false; |
| + // Disconnect from the network loader to stop receiving further data |
| + // or notifications for the URL. |
| + url_loader_->DisconnectClient(); |
| + } |
| + |
| std::vector<std::unique_ptr<URLLoaderRequestHandler>> handlers_; |
| size_t handler_index_ = 0; |
| @@ -305,6 +349,25 @@ class NavigationURLLoaderNetworkService::URLLoaderRequestController |
| // This is referenced only on the UI thread. |
| base::WeakPtr<NavigationURLLoaderNetworkService> owner_; |
| + // Set to true if the default URLLoader (network service) was used for the |
| + // current navigation. |
| + bool default_loader_used_ = false; |
| + |
| + // Contains a copy of the response. |
| + ResourceResponseHead response_; |
| + |
| + // URLLoaderClient binding for loaders created for responses received from the |
| + // network loader. |
| + mojo::Binding<mojom::URLLoaderClient> response_loader_binding_; |
| + |
| + // URLLoader instance for response loaders, i.e loaders created for handing |
| + // responses received from the network URLLoader. |
| + mojom::URLLoaderPtr response_url_loader_; |
| + |
| + // URLLoaderClient request pointer for response loaders, i.e loaders created |
| + // for handing responses received from the network URLLoader. |
| + mojom::URLLoaderClientRequest response_client_request_; |
| + |
| DISALLOW_COPY_AND_ASSIGN(URLLoaderRequestController); |
| }; |