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 d55894595e17accb1220a5630c4ad2b6f119843a..3cd6a4da42751bcabd188988012fbb2277d76ab0 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), |
| + fallback_response_binding_(this) {} |
| ~URLLoaderRequestController() override { |
| DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| @@ -214,6 +215,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, |
| @@ -243,6 +245,12 @@ 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 load a fallback for the response. |
| + if (MaybeLoadFallbackForResponse(head)) |
| + return; |
| + |
| BrowserThread::PostTask( |
| BrowserThread::UI, FROM_HERE, |
| base::Bind(&NavigationURLLoaderNetworkService::OnReceiveResponse, |
| @@ -251,6 +259,13 @@ class NavigationURLLoaderNetworkService::URLLoaderRequestController |
| void OnReceiveRedirect(const net::RedirectInfo& redirect_info, |
| const ResourceResponseHead& head) 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 load a fallback for the response. |
| + if (MaybeLoadFallbackForRedirect(head, redirect_info)) |
| + return; |
|
kinuko
2017/07/25 07:12:05
In my understanding we don't need this code at lea
ananta
2017/07/25 22:33:00
I think we need this code for same origin redirect
kinuko
2017/07/25 23:23:14
I was looking into this code where it seems we're
michaeln
2017/07/26 23:08:41
Right! We don't need redirect fallback handling fo
|
| + |
| BrowserThread::PostTask( |
| BrowserThread::UI, FROM_HERE, |
| base::Bind(&NavigationURLLoaderNetworkService::OnReceiveRedirect, |
| @@ -278,12 +293,74 @@ 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 load a fallback for the response. |
| + if (MaybeLoadFallbackForResponse(response_)) |
| + return; |
| + |
| BrowserThread::PostTask( |
| BrowserThread::UI, FROM_HERE, |
| base::Bind(&NavigationURLLoaderNetworkService::OnComplete, owner_, |
| completion_status)); |
| } |
| + // Returns true if a handler returns a fallback response. |
| + bool MaybeLoadFallbackForResponse(const ResourceResponseHead& response) { |
| + mojom::URLLoaderClientPtr fallback_client; |
| + mojom::URLLoaderRequest fallback_request; |
| + if (!CreateFallbackClientAndRequest(&fallback_client, &fallback_request)) |
| + return false; |
| + |
| + for (size_t index = 0; index < handlers_.size(); ++index) { |
| + if (handlers_[index]->MaybeGetFallbackForResponse( |
| + response, &fallback_client, &fallback_request)) { |
|
kinuko
2017/07/25 07:12:05
Hmm. Sorry I think I'm repeating the same comment
kinuko
2017/07/25 07:28:42
Or we could probably make MaybeCreateLoader take a
jam
2017/07/25 18:14:15
Yep this is what I meant :) it's a change from the
ananta
2017/07/25 22:33:00
I am not sure if transparently proxying to the n/w
ananta
2017/07/25 22:33:00
Perhaps I am missing something here. Seems like it
kinuko
2017/07/25 23:23:13
Hm, it sounds like a good point.
jam
2017/07/26 01:40:51
Can you expand on why it's desirable that the appc
kinuko
2017/07/26 01:59:14
One of the cases that come to my mind is like:
- a
michaeln
2017/07/26 23:08:41
I think its easier to reason about too if the appc
|
| + OnFallbackHandlerFound(); |
| + return true; |
| + } |
| + } |
| + return false; |
| + } |
| + |
| + // Returns true if a handler returns a fallback response for the redirect. |
| + bool MaybeLoadFallbackForRedirect(const ResourceResponseHead& response, |
| + const net::RedirectInfo& redirect_info) { |
| + mojom::URLLoaderClientPtr fallback_client; |
| + mojom::URLLoaderRequest fallback_request; |
| + if (!CreateFallbackClientAndRequest(&fallback_client, &fallback_request)) |
| + return false; |
| + |
| + for (size_t index = 0; index < handlers_.size(); ++index) { |
| + if (handlers_[index]->MaybeGetFallbackForRedirect( |
| + response, redirect_info, &fallback_client, &fallback_request)) { |
| + OnFallbackHandlerFound(); |
| + return true; |
| + } |
| + } |
| + return false; |
| + } |
| + |
| + // Creates an instance of the URLLoaderClient interface which can be bound |
| + // to a handler for receiving fallback responses. |
| + // Returns true on success. |
| + bool CreateFallbackClientAndRequest(mojom::URLLoaderClientPtr* client, |
| + mojom::URLLoaderRequest* request) { |
| + // Ignore requests which were not sent to the network loader. |
| + if (!default_loader_used_) |
| + return false; |
| + fallback_response_binding_.Bind(mojo::MakeRequest(client)); |
| + *request = mojo::MakeRequest(&fallback_url_loader_); |
| + return true; |
| + } |
| + |
| + // Called if we find a handler who delivers fallback content for the URL. |
| + void OnFallbackHandlerFound() { |
| + // We reset this flag as we expect a response from the fallback 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; |
| @@ -306,6 +383,19 @@ 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 handling fallback responses. |
| + mojo::Binding<mojom::URLLoaderClient> fallback_response_binding_; |
| + |
| + // URLLoader instance for fallback responses. |
| + mojom::URLLoaderPtr fallback_url_loader_; |
| + |
| DISALLOW_COPY_AND_ASSIGN(URLLoaderRequestController); |
| }; |