Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(235)

Side by Side Diff: content/browser/loader/navigation_url_loader_network_service.cc

Issue 2982363002: Add support for fallback content for the frame. This includes main and subframes. (Closed)
Patch Set: Address review comments. Created 3 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2017 The Chromium Authors. All rights reserved. 1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/browser/loader/navigation_url_loader_network_service.h" 5 #include "content/browser/loader/navigation_url_loader_network_service.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/bind_helpers.h" 8 #include "base/bind_helpers.h"
9 #include "base/memory/ptr_util.h" 9 #include "base/memory/ptr_util.h"
10 #include "base/trace_event/trace_event.h" 10 #include "base/trace_event/trace_event.h"
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
98 : public mojom::URLLoaderClient { 98 : public mojom::URLLoaderClient {
99 public: 99 public:
100 URLLoaderRequestController( 100 URLLoaderRequestController(
101 std::unique_ptr<ResourceRequest> resource_request, 101 std::unique_ptr<ResourceRequest> resource_request,
102 ResourceContext* resource_context, 102 ResourceContext* resource_context,
103 scoped_refptr<URLLoaderFactoryGetter> default_url_loader_factory_getter, 103 scoped_refptr<URLLoaderFactoryGetter> default_url_loader_factory_getter,
104 const base::WeakPtr<NavigationURLLoaderNetworkService>& owner) 104 const base::WeakPtr<NavigationURLLoaderNetworkService>& owner)
105 : resource_request_(std::move(resource_request)), 105 : resource_request_(std::move(resource_request)),
106 resource_context_(resource_context), 106 resource_context_(resource_context),
107 default_url_loader_factory_getter_(default_url_loader_factory_getter), 107 default_url_loader_factory_getter_(default_url_loader_factory_getter),
108 owner_(owner) {} 108 owner_(owner),
109 fallback_response_binding_(this) {}
109 110
110 ~URLLoaderRequestController() override { 111 ~URLLoaderRequestController() override {
111 DCHECK_CURRENTLY_ON(BrowserThread::IO); 112 DCHECK_CURRENTLY_ON(BrowserThread::IO);
112 } 113 }
113 114
114 void Start( 115 void Start(
115 ServiceWorkerNavigationHandleCore* service_worker_navigation_handle_core, 116 ServiceWorkerNavigationHandleCore* service_worker_navigation_handle_core,
116 AppCacheNavigationHandleCore* appcache_handle_core, 117 AppCacheNavigationHandleCore* appcache_handle_core,
117 std::unique_ptr<NavigationRequestInfo> request_info, 118 std::unique_ptr<NavigationRequestInfo> request_info,
118 mojom::URLLoaderFactoryPtrInfo factory_for_webui, 119 mojom::URLLoaderFactoryPtrInfo factory_for_webui,
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
207 base::Unretained(this))); 208 base::Unretained(this)));
208 return; 209 return;
209 } 210 }
210 211
211 mojom::URLLoaderFactory* factory = nullptr; 212 mojom::URLLoaderFactory* factory = nullptr;
212 DCHECK_EQ(handlers_.size(), handler_index_); 213 DCHECK_EQ(handlers_.size(), handler_index_);
213 if (resource_request_->url.SchemeIs(url::kBlobScheme)) { 214 if (resource_request_->url.SchemeIs(url::kBlobScheme)) {
214 factory = default_url_loader_factory_getter_->GetBlobFactory()->get(); 215 factory = default_url_loader_factory_getter_->GetBlobFactory()->get();
215 } else { 216 } else {
216 factory = default_url_loader_factory_getter_->GetNetworkFactory()->get(); 217 factory = default_url_loader_factory_getter_->GetNetworkFactory()->get();
218 default_loader_used_ = true;
217 } 219 }
218 url_loader_ = ThrottlingURLLoader::CreateLoaderAndStart( 220 url_loader_ = ThrottlingURLLoader::CreateLoaderAndStart(
219 factory, 221 factory,
220 GetContentClient()->browser()->CreateURLLoaderThrottles( 222 GetContentClient()->browser()->CreateURLLoaderThrottles(
221 web_contents_getter_), 223 web_contents_getter_),
222 0 /* routing_id? */, 0 /* request_id? */, 224 0 /* routing_id? */, 0 /* request_id? */,
223 mojom::kURLLoadOptionSendSSLInfo, *resource_request_, this, 225 mojom::kURLLoadOptionSendSSLInfo, *resource_request_, this,
224 kTrafficAnnotation); 226 kTrafficAnnotation);
225 } 227 }
226 228
227 void FollowRedirect() { 229 void FollowRedirect() {
228 DCHECK_CURRENTLY_ON(BrowserThread::IO); 230 DCHECK_CURRENTLY_ON(BrowserThread::IO);
229 DCHECK(url_loader_); 231 DCHECK(url_loader_);
230 232
231 url_loader_->FollowRedirect(); 233 url_loader_->FollowRedirect();
232 } 234 }
233 235
234 // Ownership of the URLLoaderFactoryPtrInfo instance is transferred to the 236 // Ownership of the URLLoaderFactoryPtrInfo instance is transferred to the
235 // caller. 237 // caller.
236 mojom::URLLoaderFactoryPtrInfo GetSubresourceURLLoaderFactory() { 238 mojom::URLLoaderFactoryPtrInfo GetSubresourceURLLoaderFactory() {
237 return std::move(subresource_url_loader_factory_ptr_info_); 239 return std::move(subresource_url_loader_factory_ptr_info_);
238 } 240 }
239 241
240 private: 242 private:
241 // mojom::URLLoaderClient implementation: 243 // mojom::URLLoaderClient implementation:
242 void OnReceiveResponse( 244 void OnReceiveResponse(
243 const ResourceResponseHead& head, 245 const ResourceResponseHead& head,
244 const base::Optional<net::SSLInfo>& ssl_info, 246 const base::Optional<net::SSLInfo>& ssl_info,
245 mojom::DownloadedTempFilePtr downloaded_file) override { 247 mojom::DownloadedTempFilePtr downloaded_file) override {
248 response_ = head;
249 // If the default loader (network) was used to handle the URL load request
250 // we need to see if the handlers want to load a fallback for the response.
251 if (MaybeLoadFallbackForResponse(head))
252 return;
253
246 BrowserThread::PostTask( 254 BrowserThread::PostTask(
247 BrowserThread::UI, FROM_HERE, 255 BrowserThread::UI, FROM_HERE,
248 base::Bind(&NavigationURLLoaderNetworkService::OnReceiveResponse, 256 base::Bind(&NavigationURLLoaderNetworkService::OnReceiveResponse,
249 owner_, head, ssl_info, base::Passed(&downloaded_file))); 257 owner_, head, ssl_info, base::Passed(&downloaded_file)));
250 } 258 }
251 259
252 void OnReceiveRedirect(const net::RedirectInfo& redirect_info, 260 void OnReceiveRedirect(const net::RedirectInfo& redirect_info,
253 const ResourceResponseHead& head) override { 261 const ResourceResponseHead& head) override {
262 response_ = head;
263
264 // If the default loader (network) was used to handle the URL load request
265 // we need to see if the handlers want to load a fallback for the response.
266 if (MaybeLoadFallbackForRedirect(head, redirect_info))
267 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
268
254 BrowserThread::PostTask( 269 BrowserThread::PostTask(
255 BrowserThread::UI, FROM_HERE, 270 BrowserThread::UI, FROM_HERE,
256 base::Bind(&NavigationURLLoaderNetworkService::OnReceiveRedirect, 271 base::Bind(&NavigationURLLoaderNetworkService::OnReceiveRedirect,
257 owner_, redirect_info, head)); 272 owner_, redirect_info, head));
258 } 273 }
259 274
260 void OnDataDownloaded(int64_t data_length, int64_t encoded_length) override {} 275 void OnDataDownloaded(int64_t data_length, int64_t encoded_length) override {}
261 276
262 void OnUploadProgress(int64_t current_position, 277 void OnUploadProgress(int64_t current_position,
263 int64_t total_size, 278 int64_t total_size,
264 OnUploadProgressCallback callback) override {} 279 OnUploadProgressCallback callback) override {}
265 280
266 void OnReceiveCachedMetadata(const std::vector<uint8_t>& data) override {} 281 void OnReceiveCachedMetadata(const std::vector<uint8_t>& data) override {}
267 282
268 void OnTransferSizeUpdated(int32_t transfer_size_diff) override {} 283 void OnTransferSizeUpdated(int32_t transfer_size_diff) override {}
269 284
270 void OnStartLoadingResponseBody( 285 void OnStartLoadingResponseBody(
271 mojo::ScopedDataPipeConsumerHandle body) override { 286 mojo::ScopedDataPipeConsumerHandle body) override {
272 BrowserThread::PostTask( 287 BrowserThread::PostTask(
273 BrowserThread::UI, FROM_HERE, 288 BrowserThread::UI, FROM_HERE,
274 base::Bind( 289 base::Bind(
275 &NavigationURLLoaderNetworkService::OnStartLoadingResponseBody, 290 &NavigationURLLoaderNetworkService::OnStartLoadingResponseBody,
276 owner_, base::Passed(&body))); 291 owner_, base::Passed(&body)));
277 } 292 }
278 293
279 void OnComplete( 294 void OnComplete(
280 const ResourceRequestCompletionStatus& completion_status) override { 295 const ResourceRequestCompletionStatus& completion_status) override {
296 // If the default loader (network) was used to handle the URL load request
297 // we need to see if the handlers want to load a fallback for the response.
298 if (MaybeLoadFallbackForResponse(response_))
299 return;
300
281 BrowserThread::PostTask( 301 BrowserThread::PostTask(
282 BrowserThread::UI, FROM_HERE, 302 BrowserThread::UI, FROM_HERE,
283 base::Bind(&NavigationURLLoaderNetworkService::OnComplete, owner_, 303 base::Bind(&NavigationURLLoaderNetworkService::OnComplete, owner_,
284 completion_status)); 304 completion_status));
285 } 305 }
286 306
307 // Returns true if a handler returns a fallback response.
308 bool MaybeLoadFallbackForResponse(const ResourceResponseHead& response) {
309 mojom::URLLoaderClientPtr fallback_client;
310 mojom::URLLoaderRequest fallback_request;
311 if (!CreateFallbackClientAndRequest(&fallback_client, &fallback_request))
312 return false;
313
314 for (size_t index = 0; index < handlers_.size(); ++index) {
315 if (handlers_[index]->MaybeGetFallbackForResponse(
316 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
317 OnFallbackHandlerFound();
318 return true;
319 }
320 }
321 return false;
322 }
323
324 // Returns true if a handler returns a fallback response for the redirect.
325 bool MaybeLoadFallbackForRedirect(const ResourceResponseHead& response,
326 const net::RedirectInfo& redirect_info) {
327 mojom::URLLoaderClientPtr fallback_client;
328 mojom::URLLoaderRequest fallback_request;
329 if (!CreateFallbackClientAndRequest(&fallback_client, &fallback_request))
330 return false;
331
332 for (size_t index = 0; index < handlers_.size(); ++index) {
333 if (handlers_[index]->MaybeGetFallbackForRedirect(
334 response, redirect_info, &fallback_client, &fallback_request)) {
335 OnFallbackHandlerFound();
336 return true;
337 }
338 }
339 return false;
340 }
341
342 // Creates an instance of the URLLoaderClient interface which can be bound
343 // to a handler for receiving fallback responses.
344 // Returns true on success.
345 bool CreateFallbackClientAndRequest(mojom::URLLoaderClientPtr* client,
346 mojom::URLLoaderRequest* request) {
347 // Ignore requests which were not sent to the network loader.
348 if (!default_loader_used_)
349 return false;
350 fallback_response_binding_.Bind(mojo::MakeRequest(client));
351 *request = mojo::MakeRequest(&fallback_url_loader_);
352 return true;
353 }
354
355 // Called if we find a handler who delivers fallback content for the URL.
356 void OnFallbackHandlerFound() {
357 // We reset this flag as we expect a response from the fallback handler.
358 default_loader_used_ = false;
359 // Disconnect from the network loader to stop receiving further data
360 // or notifications for the URL.
361 url_loader_->DisconnectClient();
362 }
363
287 std::vector<std::unique_ptr<URLLoaderRequestHandler>> handlers_; 364 std::vector<std::unique_ptr<URLLoaderRequestHandler>> handlers_;
288 size_t handler_index_ = 0; 365 size_t handler_index_ = 0;
289 366
290 std::unique_ptr<ResourceRequest> resource_request_; 367 std::unique_ptr<ResourceRequest> resource_request_;
291 ResourceContext* resource_context_; 368 ResourceContext* resource_context_;
292 base::Callback<WebContents*()> web_contents_getter_; 369 base::Callback<WebContents*()> web_contents_getter_;
293 370
294 scoped_refptr<URLLoaderFactoryGetter> default_url_loader_factory_getter_; 371 scoped_refptr<URLLoaderFactoryGetter> default_url_loader_factory_getter_;
295 372
296 mojom::URLLoaderFactoryPtr webui_factory_ptr_; 373 mojom::URLLoaderFactoryPtr webui_factory_ptr_;
297 374
298 std::unique_ptr<ThrottlingURLLoader> url_loader_; 375 std::unique_ptr<ThrottlingURLLoader> url_loader_;
299 376
300 BlobHandles blob_handles_; 377 BlobHandles blob_handles_;
301 378
302 // Currently used by the AppCache loader to pass its factory to the 379 // Currently used by the AppCache loader to pass its factory to the
303 // renderer which enables it to handle subresources. 380 // renderer which enables it to handle subresources.
304 mojom::URLLoaderFactoryPtrInfo subresource_url_loader_factory_ptr_info_; 381 mojom::URLLoaderFactoryPtrInfo subresource_url_loader_factory_ptr_info_;
305 382
306 // This is referenced only on the UI thread. 383 // This is referenced only on the UI thread.
307 base::WeakPtr<NavigationURLLoaderNetworkService> owner_; 384 base::WeakPtr<NavigationURLLoaderNetworkService> owner_;
308 385
386 // Set to true if the default URLLoader (network service) was used for the
387 // current navigation.
388 bool default_loader_used_ = false;
389
390 // Contains a copy of the response.
391 ResourceResponseHead response_;
392
393 // URLLoaderClient binding for handling fallback responses.
394 mojo::Binding<mojom::URLLoaderClient> fallback_response_binding_;
395
396 // URLLoader instance for fallback responses.
397 mojom::URLLoaderPtr fallback_url_loader_;
398
309 DISALLOW_COPY_AND_ASSIGN(URLLoaderRequestController); 399 DISALLOW_COPY_AND_ASSIGN(URLLoaderRequestController);
310 }; 400 };
311 401
312 NavigationURLLoaderNetworkService::NavigationURLLoaderNetworkService( 402 NavigationURLLoaderNetworkService::NavigationURLLoaderNetworkService(
313 ResourceContext* resource_context, 403 ResourceContext* resource_context,
314 StoragePartition* storage_partition, 404 StoragePartition* storage_partition,
315 std::unique_ptr<NavigationRequestInfo> request_info, 405 std::unique_ptr<NavigationRequestInfo> request_info,
316 std::unique_ptr<NavigationUIData> navigation_ui_data, 406 std::unique_ptr<NavigationUIData> navigation_ui_data,
317 ServiceWorkerNavigationHandle* service_worker_navigation_handle, 407 ServiceWorkerNavigationHandle* service_worker_navigation_handle,
318 AppCacheNavigationHandle* appcache_handle, 408 AppCacheNavigationHandle* appcache_handle,
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after
454 TRACE_EVENT_ASYNC_END2("navigation", "Navigation timeToResponseStarted", 544 TRACE_EVENT_ASYNC_END2("navigation", "Navigation timeToResponseStarted",
455 this, "&NavigationURLLoaderNetworkService", this, 545 this, "&NavigationURLLoaderNetworkService", this,
456 "success", false); 546 "success", false);
457 547
458 delegate_->OnRequestFailed(completion_status.exists_in_cache, 548 delegate_->OnRequestFailed(completion_status.exists_in_cache,
459 completion_status.error_code); 549 completion_status.error_code);
460 } 550 }
461 } 551 }
462 552
463 } // namespace content 553 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698