| 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;
|
| +
|
| 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)) {
|
| + 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);
|
| };
|
|
|
|
|