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

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. Add the fallback function as a parameter to LoaderCallback 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 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
170 if (appcache_handler) 171 if (appcache_handler)
171 handlers_.push_back(std::move(appcache_handler)); 172 handlers_.push_back(std::move(appcache_handler));
172 } 173 }
173 174
174 Restart(); 175 Restart();
175 } 176 }
176 177
177 // This could be called multiple times. 178 // This could be called multiple times.
178 void Restart() { 179 void Restart() {
179 handler_index_ = 0; 180 handler_index_ = 0;
180 MaybeStartLoader(StartLoaderCallback()); 181 MaybeStartLoader(StartLoaderCallback(), ResponseFallback());
181 } 182 }
182 183
183 void MaybeStartLoader(StartLoaderCallback start_loader_callback) { 184 void MaybeStartLoader(StartLoaderCallback start_loader_callback,
185 ResponseFallback fallback) {
184 if (start_loader_callback) { 186 if (start_loader_callback) {
187 DCHECK(!fallback);
185 url_loader_ = ThrottlingURLLoader::CreateLoaderAndStart( 188 url_loader_ = ThrottlingURLLoader::CreateLoaderAndStart(
186 std::move(start_loader_callback), 189 std::move(start_loader_callback),
187 GetContentClient()->browser()->CreateURLLoaderThrottles( 190 GetContentClient()->browser()->CreateURLLoaderThrottles(
188 web_contents_getter_), 191 web_contents_getter_),
189 *resource_request_, this, kTrafficAnnotation); 192 *resource_request_, this, kTrafficAnnotation);
190 193
191 DCHECK_GT(handler_index_, 0U); 194 DCHECK_GT(handler_index_, 0U);
192 195
193 mojom::URLLoaderFactoryPtr subresource_loader_factory = 196 mojom::URLLoaderFactoryPtr subresource_loader_factory =
194 handlers_[handler_index_ - 1]->MaybeCreateSubresourceFactory(); 197 handlers_[handler_index_ - 1]->MaybeCreateSubresourceFactory();
195 if (subresource_loader_factory.get()) { 198 if (subresource_loader_factory.get()) {
196 subresource_url_loader_factory_ptr_info_ = 199 subresource_url_loader_factory_ptr_info_ =
197 subresource_loader_factory.PassInterface(); 200 subresource_loader_factory.PassInterface();
198 } 201 }
199 return; 202 return;
203 } else {
204 // We only support one fallback handler at any given point. AppCache is
205 // the only handler which supports fallback responses.
206 DCHECK(!fallback_handler_);
207 fallback_handler_ = std::move(fallback);
200 } 208 }
201 209
202 if (handler_index_ < handlers_.size()) { 210 if (handler_index_ < handlers_.size()) {
203 handlers_[handler_index_++]->MaybeCreateLoader( 211 handlers_[handler_index_++]->MaybeCreateLoader(
204 *resource_request_, resource_context_, 212 *resource_request_, resource_context_,
205 base::BindOnce(&URLLoaderRequestController::MaybeStartLoader, 213 base::BindOnce(&URLLoaderRequestController::MaybeStartLoader,
206 base::Unretained(this))); 214 base::Unretained(this)));
207 return; 215 return;
208 } 216 }
209 217
210 mojom::URLLoaderFactory* factory = nullptr; 218 mojom::URLLoaderFactory* factory = nullptr;
211 DCHECK_EQ(handlers_.size(), handler_index_); 219 DCHECK_EQ(handlers_.size(), handler_index_);
212 if (resource_request_->url.SchemeIs(url::kBlobScheme)) { 220 if (resource_request_->url.SchemeIs(url::kBlobScheme)) {
213 factory = default_url_loader_factory_getter_->GetBlobFactory()->get(); 221 factory = default_url_loader_factory_getter_->GetBlobFactory()->get();
214 } else { 222 } else {
215 factory = default_url_loader_factory_getter_->GetNetworkFactory()->get(); 223 factory = default_url_loader_factory_getter_->GetNetworkFactory()->get();
224 default_loader_used_ = true;
216 } 225 }
217 url_loader_ = ThrottlingURLLoader::CreateLoaderAndStart( 226 url_loader_ = ThrottlingURLLoader::CreateLoaderAndStart(
218 factory, 227 factory,
219 GetContentClient()->browser()->CreateURLLoaderThrottles( 228 GetContentClient()->browser()->CreateURLLoaderThrottles(
220 web_contents_getter_), 229 web_contents_getter_),
221 0 /* routing_id? */, 0 /* request_id? */, 230 0 /* routing_id? */, 0 /* request_id? */,
222 mojom::kURLLoadOptionSendSSLInfo | mojom::kURLLoadOptionSniffMimeType, 231 mojom::kURLLoadOptionSendSSLInfo | mojom::kURLLoadOptionSniffMimeType,
223 *resource_request_, this, kTrafficAnnotation); 232 *resource_request_, this, kTrafficAnnotation);
224 } 233 }
225 234
226 void FollowRedirect() { 235 void FollowRedirect() {
227 DCHECK_CURRENTLY_ON(BrowserThread::IO); 236 DCHECK_CURRENTLY_ON(BrowserThread::IO);
228 DCHECK(url_loader_); 237 DCHECK(url_loader_);
229 238
230 url_loader_->FollowRedirect(); 239 url_loader_->FollowRedirect();
231 } 240 }
232 241
233 // Ownership of the URLLoaderFactoryPtrInfo instance is transferred to the 242 // Ownership of the URLLoaderFactoryPtrInfo instance is transferred to the
234 // caller. 243 // caller.
235 mojom::URLLoaderFactoryPtrInfo GetSubresourceURLLoaderFactory() { 244 mojom::URLLoaderFactoryPtrInfo GetSubresourceURLLoaderFactory() {
236 return std::move(subresource_url_loader_factory_ptr_info_); 245 return std::move(subresource_url_loader_factory_ptr_info_);
237 } 246 }
238 247
239 private: 248 private:
240 // mojom::URLLoaderClient implementation: 249 // mojom::URLLoaderClient implementation:
241 void OnReceiveResponse( 250 void OnReceiveResponse(
242 const ResourceResponseHead& head, 251 const ResourceResponseHead& head,
243 const base::Optional<net::SSLInfo>& ssl_info, 252 const base::Optional<net::SSLInfo>& ssl_info,
244 mojom::DownloadedTempFilePtr downloaded_file) override { 253 mojom::DownloadedTempFilePtr downloaded_file) override {
254 response_ = head;
255 // If the default loader (network) was used to handle the URL load request
256 // we need to see if the handlers want to load a fallback for the response.
257 if (MaybeLoadFallbackForResponse(head))
258 return;
259
245 BrowserThread::PostTask( 260 BrowserThread::PostTask(
246 BrowserThread::UI, FROM_HERE, 261 BrowserThread::UI, FROM_HERE,
247 base::Bind(&NavigationURLLoaderNetworkService::OnReceiveResponse, 262 base::Bind(&NavigationURLLoaderNetworkService::OnReceiveResponse,
248 owner_, head, ssl_info, base::Passed(&downloaded_file))); 263 owner_, head, ssl_info, base::Passed(&downloaded_file)));
249 } 264 }
250 265
251 void OnReceiveRedirect(const net::RedirectInfo& redirect_info, 266 void OnReceiveRedirect(const net::RedirectInfo& redirect_info,
252 const ResourceResponseHead& head) override { 267 const ResourceResponseHead& head) override {
268 response_ = head;
269
253 BrowserThread::PostTask( 270 BrowserThread::PostTask(
254 BrowserThread::UI, FROM_HERE, 271 BrowserThread::UI, FROM_HERE,
255 base::Bind(&NavigationURLLoaderNetworkService::OnReceiveRedirect, 272 base::Bind(&NavigationURLLoaderNetworkService::OnReceiveRedirect,
256 owner_, redirect_info, head)); 273 owner_, redirect_info, head));
257 } 274 }
258 275
259 void OnDataDownloaded(int64_t data_length, int64_t encoded_length) override {} 276 void OnDataDownloaded(int64_t data_length, int64_t encoded_length) override {}
260 277
261 void OnUploadProgress(int64_t current_position, 278 void OnUploadProgress(int64_t current_position,
262 int64_t total_size, 279 int64_t total_size,
263 OnUploadProgressCallback callback) override {} 280 OnUploadProgressCallback callback) override {}
264 281
265 void OnReceiveCachedMetadata(const std::vector<uint8_t>& data) override {} 282 void OnReceiveCachedMetadata(const std::vector<uint8_t>& data) override {}
266 283
267 void OnTransferSizeUpdated(int32_t transfer_size_diff) override {} 284 void OnTransferSizeUpdated(int32_t transfer_size_diff) override {}
268 285
269 void OnStartLoadingResponseBody( 286 void OnStartLoadingResponseBody(
270 mojo::ScopedDataPipeConsumerHandle body) override { 287 mojo::ScopedDataPipeConsumerHandle body) override {
271 BrowserThread::PostTask( 288 BrowserThread::PostTask(
272 BrowserThread::UI, FROM_HERE, 289 BrowserThread::UI, FROM_HERE,
273 base::Bind( 290 base::Bind(
274 &NavigationURLLoaderNetworkService::OnStartLoadingResponseBody, 291 &NavigationURLLoaderNetworkService::OnStartLoadingResponseBody,
275 owner_, base::Passed(&body))); 292 owner_, base::Passed(&body)));
276 } 293 }
277 294
278 void OnComplete( 295 void OnComplete(
279 const ResourceRequestCompletionStatus& completion_status) override { 296 const ResourceRequestCompletionStatus& completion_status) override {
297 // If the default loader (network) was used to handle the URL load request
298 // we need to see if the handlers want to load a fallback for the response.
299 if (MaybeLoadFallbackForResponse(response_))
300 return;
301
280 BrowserThread::PostTask( 302 BrowserThread::PostTask(
281 BrowserThread::UI, FROM_HERE, 303 BrowserThread::UI, FROM_HERE,
282 base::Bind(&NavigationURLLoaderNetworkService::OnComplete, owner_, 304 base::Bind(&NavigationURLLoaderNetworkService::OnComplete, owner_,
283 completion_status)); 305 completion_status));
284 } 306 }
285 307
308 // Returns true if a handler returns a fallback response.
309 bool MaybeLoadFallbackForResponse(const ResourceResponseHead& response) {
310 mojom::URLLoaderClientPtr fallback_client;
311 mojom::URLLoaderRequest fallback_request;
312 if (!CreateFallbackClientAndRequest(&fallback_client, &fallback_request))
313 return false;
314
315 // We reset this flag as we expect a response from the fallback handler.
316 default_loader_used_ = false;
317 // Disconnect from the network loader to stop receiving further data
318 // or notifications for the URL.
319 url_loader_->DisconnectClient();
320
321 return std::move(fallback_handler_)
322 .Run(response, std::move(fallback_client), std::move(fallback_request));
kinuko 2017/07/27 13:46:26 This fallback code works in a very specific way, w
ananta 2017/07/27 22:07:14 It seems like the method name you suggested in an
323 }
324
325 // Creates an instance of the URLLoaderClient interface which can be bound
326 // to a handler for receiving fallback responses.
327 // Returns true on success.
328 bool CreateFallbackClientAndRequest(mojom::URLLoaderClientPtr* client,
329 mojom::URLLoaderRequest* request) {
330 // Ignore if we don't have a fallback handler or if the request never went
331 // to the network loader.
332 if (!default_loader_used_ || !fallback_handler_)
333 return false;
334 fallback_response_binding_.Bind(mojo::MakeRequest(client));
335 *request = mojo::MakeRequest(&fallback_url_loader_);
336 return true;
337 }
338
286 std::vector<std::unique_ptr<URLLoaderRequestHandler>> handlers_; 339 std::vector<std::unique_ptr<URLLoaderRequestHandler>> handlers_;
287 size_t handler_index_ = 0; 340 size_t handler_index_ = 0;
288 341
289 std::unique_ptr<ResourceRequest> resource_request_; 342 std::unique_ptr<ResourceRequest> resource_request_;
290 ResourceContext* resource_context_; 343 ResourceContext* resource_context_;
291 base::Callback<WebContents*()> web_contents_getter_; 344 base::Callback<WebContents*()> web_contents_getter_;
292 345
293 scoped_refptr<URLLoaderFactoryGetter> default_url_loader_factory_getter_; 346 scoped_refptr<URLLoaderFactoryGetter> default_url_loader_factory_getter_;
294 347
295 mojom::URLLoaderFactoryPtr webui_factory_ptr_; 348 mojom::URLLoaderFactoryPtr webui_factory_ptr_;
296 349
297 std::unique_ptr<ThrottlingURLLoader> url_loader_; 350 std::unique_ptr<ThrottlingURLLoader> url_loader_;
298 351
299 BlobHandles blob_handles_; 352 BlobHandles blob_handles_;
300 353
301 // Currently used by the AppCache loader to pass its factory to the 354 // Currently used by the AppCache loader to pass its factory to the
302 // renderer which enables it to handle subresources. 355 // renderer which enables it to handle subresources.
303 mojom::URLLoaderFactoryPtrInfo subresource_url_loader_factory_ptr_info_; 356 mojom::URLLoaderFactoryPtrInfo subresource_url_loader_factory_ptr_info_;
304 357
305 // This is referenced only on the UI thread. 358 // This is referenced only on the UI thread.
306 base::WeakPtr<NavigationURLLoaderNetworkService> owner_; 359 base::WeakPtr<NavigationURLLoaderNetworkService> owner_;
307 360
361 // Set to true if the default URLLoader (network service) was used for the
362 // current navigation.
363 bool default_loader_used_ = false;
364
365 // Contains a copy of the response.
366 ResourceResponseHead response_;
367
368 // URLLoaderClient binding for handling fallback responses.
369 mojo::Binding<mojom::URLLoaderClient> fallback_response_binding_;
370
371 // URLLoader instance for fallback responses.
372 mojom::URLLoaderPtr fallback_url_loader_;
373
374 // Fallback response handler.
375 ResponseFallback fallback_handler_;
376
308 DISALLOW_COPY_AND_ASSIGN(URLLoaderRequestController); 377 DISALLOW_COPY_AND_ASSIGN(URLLoaderRequestController);
309 }; 378 };
310 379
311 NavigationURLLoaderNetworkService::NavigationURLLoaderNetworkService( 380 NavigationURLLoaderNetworkService::NavigationURLLoaderNetworkService(
312 ResourceContext* resource_context, 381 ResourceContext* resource_context,
313 StoragePartition* storage_partition, 382 StoragePartition* storage_partition,
314 std::unique_ptr<NavigationRequestInfo> request_info, 383 std::unique_ptr<NavigationRequestInfo> request_info,
315 std::unique_ptr<NavigationUIData> navigation_ui_data, 384 std::unique_ptr<NavigationUIData> navigation_ui_data,
316 ServiceWorkerNavigationHandle* service_worker_navigation_handle, 385 ServiceWorkerNavigationHandle* service_worker_navigation_handle,
317 AppCacheNavigationHandle* appcache_handle, 386 AppCacheNavigationHandle* appcache_handle,
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after
453 TRACE_EVENT_ASYNC_END2("navigation", "Navigation timeToResponseStarted", 522 TRACE_EVENT_ASYNC_END2("navigation", "Navigation timeToResponseStarted",
454 this, "&NavigationURLLoaderNetworkService", this, 523 this, "&NavigationURLLoaderNetworkService", this,
455 "success", false); 524 "success", false);
456 525
457 delegate_->OnRequestFailed(completion_status.exists_in_cache, 526 delegate_->OnRequestFailed(completion_status.exists_in_cache,
458 completion_status.error_code); 527 completion_status.error_code);
459 } 528 }
460 } 529 }
461 530
462 } // namespace content 531 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698