OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/resource_loader.h" | 5 #include "content/browser/loader/resource_loader.h" |
6 | 6 |
7 #include <utility> | 7 #include <utility> |
8 | 8 |
9 #include "base/callback_helpers.h" | 9 #include "base/callback_helpers.h" |
10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
11 #include "base/location.h" | 11 #include "base/location.h" |
12 #include "base/memory/ptr_util.h" | |
12 #include "base/metrics/histogram_macros.h" | 13 #include "base/metrics/histogram_macros.h" |
13 #include "base/profiler/scoped_tracker.h" | 14 #include "base/profiler/scoped_tracker.h" |
14 #include "base/single_thread_task_runner.h" | 15 #include "base/single_thread_task_runner.h" |
15 #include "base/threading/thread_task_runner_handle.h" | 16 #include "base/threading/thread_task_runner_handle.h" |
16 #include "base/trace_event/trace_event.h" | 17 #include "base/trace_event/trace_event.h" |
17 #include "content/browser/appcache/appcache_interceptor.h" | 18 #include "content/browser/appcache/appcache_interceptor.h" |
18 #include "content/browser/child_process_security_policy_impl.h" | 19 #include "content/browser/child_process_security_policy_impl.h" |
19 #include "content/browser/loader/detachable_resource_handler.h" | 20 #include "content/browser/loader/detachable_resource_handler.h" |
21 #include "content/browser/loader/resource_controller.h" | |
20 #include "content/browser/loader/resource_handler.h" | 22 #include "content/browser/loader/resource_handler.h" |
21 #include "content/browser/loader/resource_loader_delegate.h" | 23 #include "content/browser/loader/resource_loader_delegate.h" |
22 #include "content/browser/loader/resource_request_info_impl.h" | 24 #include "content/browser/loader/resource_request_info_impl.h" |
23 #include "content/browser/service_worker/service_worker_request_handler.h" | 25 #include "content/browser/service_worker/service_worker_request_handler.h" |
24 #include "content/browser/service_worker/service_worker_response_info.h" | 26 #include "content/browser/service_worker/service_worker_response_info.h" |
25 #include "content/browser/ssl/ssl_client_auth_handler.h" | 27 #include "content/browser/ssl/ssl_client_auth_handler.h" |
26 #include "content/browser/ssl/ssl_manager.h" | 28 #include "content/browser/ssl/ssl_manager.h" |
27 #include "content/public/browser/resource_dispatcher_host_login_delegate.h" | 29 #include "content/public/browser/resource_dispatcher_host_login_delegate.h" |
28 #include "content/public/common/browser_side_navigation_policy.h" | 30 #include "content/public/common/browser_side_navigation_policy.h" |
29 #include "content/public/common/content_client.h" | 31 #include "content/public/common/content_client.h" |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
123 // We should not have any SSL state. | 125 // We should not have any SSL state. |
124 DCHECK(!request->ssl_info().cert_status); | 126 DCHECK(!request->ssl_info().cert_status); |
125 DCHECK_EQ(request->ssl_info().security_bits, -1); | 127 DCHECK_EQ(request->ssl_info().security_bits, -1); |
126 DCHECK_EQ(request->ssl_info().key_exchange_group, 0); | 128 DCHECK_EQ(request->ssl_info().key_exchange_group, 0); |
127 DCHECK(!request->ssl_info().connection_status); | 129 DCHECK(!request->ssl_info().connection_status); |
128 } | 130 } |
129 } | 131 } |
130 | 132 |
131 } // namespace | 133 } // namespace |
132 | 134 |
135 class ResourceLoader::Controller : public ResourceController { | |
136 public: | |
137 explicit Controller(ResourceLoader* resource_loader) | |
138 : resource_loader_(resource_loader){}; | |
139 | |
140 ~Controller() override {} | |
141 | |
142 // ResourceController implementation: | |
143 void Resume() override { | |
144 MarkAsUsed(); | |
145 resource_loader_->Resume(true /* called_from_resource_controller */); | |
146 } | |
147 | |
148 void Cancel() override { | |
149 MarkAsUsed(); | |
150 resource_loader_->Cancel(); | |
151 } | |
152 | |
153 void CancelAndIgnore() override { | |
154 MarkAsUsed(); | |
155 resource_loader_->CancelAndIgnore(); | |
156 } | |
157 | |
158 void CancelWithError(int error_code) override { | |
159 MarkAsUsed(); | |
160 resource_loader_->CancelWithError(error_code); | |
161 } | |
162 | |
163 private: | |
164 void MarkAsUsed() { | |
165 #if DCHECK_IS_ON() | |
166 DCHECK(!used_); | |
167 used_ = true; | |
168 #endif | |
169 } | |
170 | |
171 ResourceLoader* const resource_loader_; | |
172 | |
173 #if DCHECK_IS_ON() | |
174 // Set to true once one of the ResourceContoller methods has been invoked. | |
175 bool used_ = false; | |
176 #endif | |
177 | |
178 DISALLOW_COPY_AND_ASSIGN(Controller); | |
179 }; | |
180 | |
181 // Helper class. Sets the stage of a ResourceLoader to DEFERRED_SYNC on | |
182 // construction, and on destruction does one of the following: | |
183 // 1) If the ResourceLoader has a deferred stage of DEFERRED_NONE, sets the | |
184 // ResourceLoader's stage to the stage specified on construction and resumes it. | |
185 // 2) If the ResourceLoader still has a deferred stage of DEFERRED_SYNC, sets | |
186 // the ResourceLoader's stage to the stage specified on construction. The | |
187 // ResourceLoader will be resumed at some point in the future. | |
188 class ResourceLoader::ScopedDeferral { | |
189 public: | |
190 ScopedDeferral(ResourceLoader* resource_loader, | |
191 ResourceLoader::DeferredStage deferred_stage) | |
192 : resource_loader_(resource_loader), deferred_stage_(deferred_stage) { | |
193 resource_loader_->deferred_stage_ = DEFERRED_SYNC; | |
194 } | |
195 | |
196 ~ScopedDeferral() { | |
197 DeferredStage old_deferred_stage = resource_loader_->deferred_stage_; | |
198 // On destruction, either the stage is still DEFERRED_SYNC, or Resume() was | |
199 // called once, and it advanced to DEFERRED_NONE. | |
200 DCHECK(old_deferred_stage == DEFERRED_NONE || | |
201 old_deferred_stage == DEFERRED_SYNC); | |
Charlie Harrison
2017/01/27 22:48:04
nit: DCHECK(...) << old_deferred_stage so if this
mmenke
2017/01/27 23:02:15
Done.
| |
202 resource_loader_->deferred_stage_ = deferred_stage_; | |
203 // If Resume() was called, it just advanced the state without doing | |
204 // anything. Go ahead and resume the request now. | |
205 if (old_deferred_stage == DEFERRED_NONE) | |
206 resource_loader_->Resume(false /* called_from_resource_controller */); | |
207 } | |
208 | |
209 private: | |
210 ResourceLoader* const resource_loader_; | |
211 const DeferredStage deferred_stage_; | |
212 | |
213 DISALLOW_COPY_AND_ASSIGN(ScopedDeferral); | |
214 }; | |
215 | |
133 ResourceLoader::ResourceLoader(std::unique_ptr<net::URLRequest> request, | 216 ResourceLoader::ResourceLoader(std::unique_ptr<net::URLRequest> request, |
134 std::unique_ptr<ResourceHandler> handler, | 217 std::unique_ptr<ResourceHandler> handler, |
135 ResourceLoaderDelegate* delegate) | 218 ResourceLoaderDelegate* delegate) |
136 : deferred_stage_(DEFERRED_NONE), | 219 : deferred_stage_(DEFERRED_NONE), |
137 request_(std::move(request)), | 220 request_(std::move(request)), |
138 handler_(std::move(handler)), | 221 handler_(std::move(handler)), |
139 delegate_(delegate), | 222 delegate_(delegate), |
140 is_transferring_(false), | 223 is_transferring_(false), |
141 times_cancelled_before_request_start_(0), | 224 times_cancelled_before_request_start_(0), |
142 started_request_(false), | 225 started_request_(false), |
143 times_cancelled_after_request_start_(0), | 226 times_cancelled_after_request_start_(0), |
144 weak_ptr_factory_(this) { | 227 weak_ptr_factory_(this) { |
145 request_->set_delegate(this); | 228 request_->set_delegate(this); |
146 handler_->SetController(this); | 229 handler_->SetDelegate(this); |
147 } | 230 } |
148 | 231 |
149 ResourceLoader::~ResourceLoader() { | 232 ResourceLoader::~ResourceLoader() { |
150 if (login_delegate_.get()) | 233 if (login_delegate_.get()) |
151 login_delegate_->OnRequestCancelled(); | 234 login_delegate_->OnRequestCancelled(); |
152 ssl_client_auth_handler_.reset(); | 235 ssl_client_auth_handler_.reset(); |
153 | 236 |
154 // Run ResourceHandler destructor before we tear-down the rest of our state | 237 // Run ResourceHandler destructor before we tear-down the rest of our state |
155 // as the ResourceHandler may want to inspect the URLRequest and other state. | 238 // as the ResourceHandler may want to inspect the URLRequest and other state. |
156 handler_.reset(); | 239 handler_.reset(); |
157 } | 240 } |
158 | 241 |
159 void ResourceLoader::StartRequest() { | 242 void ResourceLoader::StartRequest() { |
160 // Give the handler a chance to delay the URLRequest from being started. | |
161 bool defer_start = false; | |
162 if (!handler_->OnWillStart(request_->url(), &defer_start)) { | |
163 Cancel(); | |
164 return; | |
165 } | |
166 | |
167 TRACE_EVENT_WITH_FLOW0("loading", "ResourceLoader::StartRequest", this, | 243 TRACE_EVENT_WITH_FLOW0("loading", "ResourceLoader::StartRequest", this, |
168 TRACE_EVENT_FLAG_FLOW_OUT); | 244 TRACE_EVENT_FLAG_FLOW_OUT); |
169 if (defer_start) { | 245 |
170 deferred_stage_ = DEFERRED_START; | 246 ScopedDeferral scoped_deferral(this, DEFERRED_START); |
171 } else { | 247 handler_->OnWillStart(request_->url(), base::MakeUnique<Controller>(this)); |
172 StartRequestInternal(); | |
173 } | |
174 } | 248 } |
175 | 249 |
176 void ResourceLoader::CancelRequest(bool from_renderer) { | 250 void ResourceLoader::CancelRequest(bool from_renderer) { |
177 TRACE_EVENT_WITH_FLOW0("loading", "ResourceLoader::CancelRequest", this, | 251 TRACE_EVENT_WITH_FLOW0("loading", "ResourceLoader::CancelRequest", this, |
178 TRACE_EVENT_FLAG_FLOW_IN); | 252 TRACE_EVENT_FLAG_FLOW_IN); |
179 CancelRequestInternal(net::ERR_ABORTED, from_renderer); | 253 CancelRequestInternal(net::ERR_ABORTED, from_renderer); |
180 } | 254 } |
181 | 255 |
182 void ResourceLoader::CancelAndIgnore() { | 256 void ResourceLoader::CancelAndIgnore() { |
183 ResourceRequestInfoImpl* info = GetRequestInfo(); | 257 ResourceRequestInfoImpl* info = GetRequestInfo(); |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
232 } | 306 } |
233 | 307 |
234 ResourceRequestInfoImpl* ResourceLoader::GetRequestInfo() { | 308 ResourceRequestInfoImpl* ResourceLoader::GetRequestInfo() { |
235 return ResourceRequestInfoImpl::ForRequest(request_.get()); | 309 return ResourceRequestInfoImpl::ForRequest(request_.get()); |
236 } | 310 } |
237 | 311 |
238 void ResourceLoader::ClearLoginDelegate() { | 312 void ResourceLoader::ClearLoginDelegate() { |
239 login_delegate_ = NULL; | 313 login_delegate_ = NULL; |
240 } | 314 } |
241 | 315 |
316 void ResourceLoader::OutOfBandCancel(int error_code, bool tell_renderer) { | |
317 CancelRequestInternal(error_code, !tell_renderer); | |
318 } | |
319 | |
242 void ResourceLoader::OnReceivedRedirect(net::URLRequest* unused, | 320 void ResourceLoader::OnReceivedRedirect(net::URLRequest* unused, |
243 const net::RedirectInfo& redirect_info, | 321 const net::RedirectInfo& redirect_info, |
244 bool* defer) { | 322 bool* defer) { |
245 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("loading"), | 323 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("loading"), |
246 "ResourceLoader::OnReceivedRedirect"); | 324 "ResourceLoader::OnReceivedRedirect"); |
247 DCHECK_EQ(request_.get(), unused); | 325 DCHECK_EQ(request_.get(), unused); |
248 | 326 |
249 DVLOG(1) << "OnReceivedRedirect: " << request_->url().spec(); | 327 DVLOG(1) << "OnReceivedRedirect: " << request_->url().spec(); |
250 DCHECK(request_->status().is_success()); | 328 DCHECK(request_->status().is_success()); |
251 | 329 |
(...skipping 12 matching lines...) Expand all Loading... | |
264 | 342 |
265 // Tell the renderer that this request was disallowed. | 343 // Tell the renderer that this request was disallowed. |
266 Cancel(); | 344 Cancel(); |
267 return; | 345 return; |
268 } | 346 } |
269 } | 347 } |
270 | 348 |
271 scoped_refptr<ResourceResponse> response = new ResourceResponse(); | 349 scoped_refptr<ResourceResponse> response = new ResourceResponse(); |
272 PopulateResourceResponse(info, request_.get(), response.get()); | 350 PopulateResourceResponse(info, request_.get(), response.get()); |
273 delegate_->DidReceiveRedirect(this, redirect_info.new_url, response.get()); | 351 delegate_->DidReceiveRedirect(this, redirect_info.new_url, response.get()); |
274 if (!handler_->OnRequestRedirected(redirect_info, response.get(), defer)) { | 352 |
275 Cancel(); | 353 // Can't used ScopedDeferral here, because on sync completion, need to set |
276 } else if (*defer) { | 354 // |defer| to false instead of calling back into the URLRequest. |
277 deferred_stage_ = DEFERRED_REDIRECT; // Follow redirect when resumed. | 355 deferred_stage_ = DEFERRED_SYNC; |
278 DCHECK(deferred_redirect_url_.is_empty()); | 356 handler_->OnRequestRedirected(redirect_info, response.get(), |
357 base::MakeUnique<Controller>(this)); | |
358 if (is_deferred()) { | |
359 *defer = true; | |
279 deferred_redirect_url_ = redirect_info.new_url; | 360 deferred_redirect_url_ = redirect_info.new_url; |
280 } else if (delegate_->HandleExternalProtocol(this, redirect_info.new_url)) { | 361 deferred_stage_ = DEFERRED_REDIRECT; |
281 // The request is complete so we can remove it. | 362 } else { |
282 CancelAndIgnore(); | 363 *defer = false; |
283 return; | 364 if (delegate_->HandleExternalProtocol(this, redirect_info.new_url)) |
365 CancelAndIgnore(); | |
284 } | 366 } |
285 } | 367 } |
286 | 368 |
287 void ResourceLoader::OnAuthRequired(net::URLRequest* unused, | 369 void ResourceLoader::OnAuthRequired(net::URLRequest* unused, |
288 net::AuthChallengeInfo* auth_info) { | 370 net::AuthChallengeInfo* auth_info) { |
289 DCHECK_EQ(request_.get(), unused); | 371 DCHECK_EQ(request_.get(), unused); |
290 | 372 |
291 ResourceRequestInfoImpl* info = GetRequestInfo(); | 373 ResourceRequestInfoImpl* info = GetRequestInfo(); |
292 if (info->do_not_prompt_for_login()) { | 374 if (info->do_not_prompt_for_login()) { |
293 request_->CancelAuth(); | 375 request_->CancelAuth(); |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
337 DCHECK_EQ(request_.get(), unused); | 419 DCHECK_EQ(request_.get(), unused); |
338 | 420 |
339 DVLOG(1) << "OnResponseStarted: " << request_->url().spec(); | 421 DVLOG(1) << "OnResponseStarted: " << request_->url().spec(); |
340 | 422 |
341 if (!request_->status().is_success()) { | 423 if (!request_->status().is_success()) { |
342 ResponseCompleted(); | 424 ResponseCompleted(); |
343 return; | 425 return; |
344 } | 426 } |
345 | 427 |
346 CompleteResponseStarted(); | 428 CompleteResponseStarted(); |
347 | |
348 // If the handler deferred the request, it will resume the request later. If | |
349 // the request was cancelled, the request will call back into |this| with a | |
350 // bogus read completed error. | |
351 if (is_deferred() || !request_->status().is_success()) | |
352 return; | |
353 | |
354 ReadMore(false); // Read the first chunk. | |
355 } | 429 } |
356 | 430 |
357 void ResourceLoader::OnReadCompleted(net::URLRequest* unused, int bytes_read) { | 431 void ResourceLoader::OnReadCompleted(net::URLRequest* unused, int bytes_read) { |
358 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("loading"), | 432 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("loading"), |
359 "ResourceLoader::OnReadCompleted"); | 433 "ResourceLoader::OnReadCompleted"); |
360 DCHECK_EQ(request_.get(), unused); | 434 DCHECK_EQ(request_.get(), unused); |
361 DVLOG(1) << "OnReadCompleted: \"" << request_->url().spec() << "\"" | 435 DVLOG(1) << "OnReadCompleted: \"" << request_->url().spec() << "\"" |
362 << " bytes_read = " << bytes_read; | 436 << " bytes_read = " << bytes_read; |
363 | 437 |
364 // bytes_read == -1 always implies an error. | 438 // bytes_read == -1 always implies an error. |
365 if (bytes_read == -1 || !request_->status().is_success()) { | 439 if (bytes_read == -1 || !request_->status().is_success()) { |
366 ResponseCompleted(); | 440 ResponseCompleted(); |
367 return; | 441 return; |
368 } | 442 } |
369 | 443 |
370 CompleteRead(bytes_read); | 444 CompleteRead(bytes_read); |
371 | |
372 // If the handler cancelled or deferred the request, do not continue | |
373 // processing the read. If canceled, either the request will call into |this| | |
374 // with a bogus read error, or, if the request was completed, a task posted | |
375 // from ResourceLoader::CancelREquestInternal will run OnResponseCompleted. | |
376 if (is_deferred() || !request_->status().is_success()) | |
377 return; | |
378 | |
379 if (bytes_read > 0) { | |
380 ReadMore(true); // Read the next chunk. | |
381 } else { | |
382 // TODO(darin): Remove ScopedTracker below once crbug.com/475761 is fixed. | |
383 tracked_objects::ScopedTracker tracking_profile( | |
384 FROM_HERE_WITH_EXPLICIT_FUNCTION("475761 ResponseCompleted()")); | |
385 | |
386 // URLRequest reported an EOF. Call ResponseCompleted. | |
387 DCHECK_EQ(0, bytes_read); | |
388 ResponseCompleted(); | |
389 } | |
390 } | 445 } |
391 | 446 |
392 void ResourceLoader::CancelSSLRequest(int error, | 447 void ResourceLoader::CancelSSLRequest(int error, |
393 const net::SSLInfo* ssl_info) { | 448 const net::SSLInfo* ssl_info) { |
394 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 449 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
395 | 450 |
396 // The request can be NULL if it was cancelled by the renderer (as the | 451 // The request can be NULL if it was cancelled by the renderer (as the |
397 // request of the user navigating to a new page from the location bar). | 452 // request of the user navigating to a new page from the location bar). |
398 if (!request_->is_pending()) | 453 if (!request_->is_pending()) |
399 return; | 454 return; |
(...skipping 25 matching lines...) Expand all Loading... | |
425 net::FetchClientCertPrivateKey(cert); | 480 net::FetchClientCertPrivateKey(cert); |
426 request_->ContinueWithCertificate(cert, private_key.get()); | 481 request_->ContinueWithCertificate(cert, private_key.get()); |
427 } | 482 } |
428 | 483 |
429 void ResourceLoader::CancelCertificateSelection() { | 484 void ResourceLoader::CancelCertificateSelection() { |
430 DCHECK(ssl_client_auth_handler_); | 485 DCHECK(ssl_client_auth_handler_); |
431 ssl_client_auth_handler_.reset(); | 486 ssl_client_auth_handler_.reset(); |
432 request_->CancelWithError(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED); | 487 request_->CancelWithError(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED); |
433 } | 488 } |
434 | 489 |
435 void ResourceLoader::Resume() { | 490 void ResourceLoader::Resume(bool called_from_resource_controller) { |
436 DCHECK(!is_transferring_); | 491 DCHECK(!is_transferring_); |
437 | 492 |
438 DeferredStage stage = deferred_stage_; | 493 DeferredStage stage = deferred_stage_; |
439 deferred_stage_ = DEFERRED_NONE; | 494 deferred_stage_ = DEFERRED_NONE; |
440 switch (stage) { | 495 switch (stage) { |
441 case DEFERRED_NONE: | 496 case DEFERRED_NONE: |
442 NOTREACHED(); | 497 NOTREACHED(); |
443 break; | 498 break; |
499 case DEFERRED_SYNC: | |
500 DCHECK(called_from_resource_controller); | |
501 // Request will be resumed when the stack unwinds. | |
502 break; | |
444 case DEFERRED_START: | 503 case DEFERRED_START: |
504 // URLRequest::Start completes asynchronously, so starting the request now | |
505 // won't result in synchronously calling into a ResourceHandler, if this | |
506 // was called from Resume(). | |
445 StartRequestInternal(); | 507 StartRequestInternal(); |
446 break; | 508 break; |
447 case DEFERRED_REDIRECT: | 509 case DEFERRED_REDIRECT: |
510 // URLRequest::Start completes asynchronously, so starting the request now | |
511 // won't result in synchronously calling into a ResourceHandler, if this | |
512 // was called from Resume(). | |
448 FollowDeferredRedirectInternal(); | 513 FollowDeferredRedirectInternal(); |
449 break; | 514 break; |
450 case DEFERRED_READ: | 515 case DEFERRED_READ: |
451 base::ThreadTaskRunnerHandle::Get()->PostTask( | 516 if (called_from_resource_controller) { |
452 FROM_HERE, base::Bind(&ResourceLoader::ResumeReading, | 517 base::ThreadTaskRunnerHandle::Get()->PostTask( |
453 weak_ptr_factory_.GetWeakPtr())); | 518 FROM_HERE, base::Bind(&ResourceLoader::ResumeReading, |
519 weak_ptr_factory_.GetWeakPtr())); | |
520 } else { | |
521 ReadMore(called_from_resource_controller); | |
522 } | |
454 break; | 523 break; |
455 case DEFERRED_RESPONSE_COMPLETE: | 524 case DEFERRED_RESPONSE_COMPLETE: |
456 base::ThreadTaskRunnerHandle::Get()->PostTask( | 525 if (called_from_resource_controller) { |
457 FROM_HERE, base::Bind(&ResourceLoader::ResponseCompleted, | 526 base::ThreadTaskRunnerHandle::Get()->PostTask( |
458 weak_ptr_factory_.GetWeakPtr())); | 527 FROM_HERE, base::Bind(&ResourceLoader::ResponseCompleted, |
528 weak_ptr_factory_.GetWeakPtr())); | |
529 } else { | |
530 ResponseCompleted(); | |
531 } | |
459 break; | 532 break; |
460 case DEFERRED_FINISH: | 533 case DEFERRED_FINISH: |
461 // Delay self-destruction since we don't know how we were reached. | 534 if (called_from_resource_controller) { |
462 base::ThreadTaskRunnerHandle::Get()->PostTask( | 535 // Delay self-destruction since we don't know how we were reached. |
463 FROM_HERE, base::Bind(&ResourceLoader::CallDidFinishLoading, | 536 base::ThreadTaskRunnerHandle::Get()->PostTask( |
464 weak_ptr_factory_.GetWeakPtr())); | 537 FROM_HERE, base::Bind(&ResourceLoader::CallDidFinishLoading, |
538 weak_ptr_factory_.GetWeakPtr())); | |
539 } else { | |
540 CallDidFinishLoading(); | |
541 } | |
465 break; | 542 break; |
466 } | 543 } |
467 } | 544 } |
468 | 545 |
469 void ResourceLoader::Cancel() { | 546 void ResourceLoader::Cancel() { |
470 CancelRequest(false); | 547 CancelRequest(false); |
471 } | 548 } |
472 | 549 |
473 void ResourceLoader::StartRequestInternal() { | 550 void ResourceLoader::StartRequestInternal() { |
474 DCHECK(!request_->is_pending()); | 551 DCHECK(!request_->is_pending()); |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
551 ResourceRequestInfoImpl* info = GetRequestInfo(); | 628 ResourceRequestInfoImpl* info = GetRequestInfo(); |
552 scoped_refptr<ResourceResponse> response = new ResourceResponse(); | 629 scoped_refptr<ResourceResponse> response = new ResourceResponse(); |
553 PopulateResourceResponse(info, request_.get(), response.get()); | 630 PopulateResourceResponse(info, request_.get(), response.get()); |
554 | 631 |
555 delegate_->DidReceiveResponse(this); | 632 delegate_->DidReceiveResponse(this); |
556 | 633 |
557 // TODO(darin): Remove ScopedTracker below once crbug.com/475761 is fixed. | 634 // TODO(darin): Remove ScopedTracker below once crbug.com/475761 is fixed. |
558 tracked_objects::ScopedTracker tracking_profile( | 635 tracked_objects::ScopedTracker tracking_profile( |
559 FROM_HERE_WITH_EXPLICIT_FUNCTION("475761 OnResponseStarted()")); | 636 FROM_HERE_WITH_EXPLICIT_FUNCTION("475761 OnResponseStarted()")); |
560 | 637 |
561 bool defer = false; | 638 read_deferral_start_time_ = base::TimeTicks::Now(); |
562 if (!handler_->OnResponseStarted(response.get(), &defer)) { | 639 ScopedDeferral scoped_deferral(this, DEFERRED_READ); |
563 Cancel(); | 640 handler_->OnResponseStarted(response.get(), |
564 } else if (defer) { | 641 base::MakeUnique<Controller>(this)); |
565 read_deferral_start_time_ = base::TimeTicks::Now(); | |
566 deferred_stage_ = DEFERRED_READ; // Read first chunk when resumed. | |
567 } | |
568 } | 642 } |
569 | 643 |
570 void ResourceLoader::ReadMore(bool is_continuation) { | 644 void ResourceLoader::ReadMore(bool called_from_resource_controller) { |
571 TRACE_EVENT_WITH_FLOW0("loading", "ResourceLoader::ReadMore", this, | 645 TRACE_EVENT_WITH_FLOW0("loading", "ResourceLoader::ReadMore", this, |
572 TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT); | 646 TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT); |
573 DCHECK(!is_deferred()); | 647 DCHECK(!is_deferred()); |
574 | 648 |
575 // Make sure we track the buffer in at least one place. This ensures it gets | 649 // Make sure we track the buffer in at least one place. This ensures it gets |
576 // deleted even in the case the request has already finished its job and | 650 // deleted even in the case the request has already finished its job and |
577 // doesn't use the buffer. | 651 // doesn't use the buffer. |
578 scoped_refptr<net::IOBuffer> buf; | 652 scoped_refptr<net::IOBuffer> buf; |
579 int buf_size; | 653 int buf_size; |
580 { | 654 { |
(...skipping 10 matching lines...) Expand all Loading... | |
591 } | 665 } |
592 | 666 |
593 DCHECK(buf.get()); | 667 DCHECK(buf.get()); |
594 DCHECK(buf_size > 0); | 668 DCHECK(buf_size > 0); |
595 | 669 |
596 int result = request_->Read(buf.get(), buf_size); | 670 int result = request_->Read(buf.get(), buf_size); |
597 | 671 |
598 if (result == net::ERR_IO_PENDING) | 672 if (result == net::ERR_IO_PENDING) |
599 return; | 673 return; |
600 | 674 |
601 if (!is_continuation || result <= 0) { | 675 if (!called_from_resource_controller || result <= 0) { |
602 OnReadCompleted(request_.get(), result); | 676 OnReadCompleted(request_.get(), result); |
603 } else { | 677 } else { |
604 // Else, trigger OnReadCompleted asynchronously to avoid starving the IO | 678 // Else, trigger OnReadCompleted asynchronously to avoid starving the IO |
605 // thread in case the URLRequest can provide data synchronously. | 679 // thread in case the URLRequest can provide data synchronously. |
606 base::ThreadTaskRunnerHandle::Get()->PostTask( | 680 base::ThreadTaskRunnerHandle::Get()->PostTask( |
607 FROM_HERE, | 681 FROM_HERE, |
608 base::Bind(&ResourceLoader::OnReadCompleted, | 682 base::Bind(&ResourceLoader::OnReadCompleted, |
609 weak_ptr_factory_.GetWeakPtr(), request_.get(), result)); | 683 weak_ptr_factory_.GetWeakPtr(), request_.get(), result)); |
610 } | 684 } |
611 } | 685 } |
(...skipping 17 matching lines...) Expand all Loading... | |
629 TRACE_EVENT_WITH_FLOW0("loading", "ResourceLoader::CompleteRead", this, | 703 TRACE_EVENT_WITH_FLOW0("loading", "ResourceLoader::CompleteRead", this, |
630 TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT); | 704 TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT); |
631 | 705 |
632 DCHECK(bytes_read >= 0); | 706 DCHECK(bytes_read >= 0); |
633 DCHECK(request_->status().is_success()); | 707 DCHECK(request_->status().is_success()); |
634 | 708 |
635 // TODO(darin): Remove ScopedTracker below once crbug.com/475761 is fixed. | 709 // TODO(darin): Remove ScopedTracker below once crbug.com/475761 is fixed. |
636 tracked_objects::ScopedTracker tracking_profile( | 710 tracked_objects::ScopedTracker tracking_profile( |
637 FROM_HERE_WITH_EXPLICIT_FUNCTION("475761 OnReadCompleted()")); | 711 FROM_HERE_WITH_EXPLICIT_FUNCTION("475761 OnReadCompleted()")); |
638 | 712 |
639 bool defer = false; | 713 ScopedDeferral scoped_deferral( |
640 if (!handler_->OnReadCompleted(bytes_read, &defer)) { | 714 this, bytes_read > 0 ? DEFERRED_READ : DEFERRED_RESPONSE_COMPLETE); |
641 Cancel(); | 715 handler_->OnReadCompleted(bytes_read, base::MakeUnique<Controller>(this)); |
642 } else if (defer) { | |
643 deferred_stage_ = | |
644 bytes_read > 0 ? DEFERRED_READ : DEFERRED_RESPONSE_COMPLETE; | |
645 } | |
646 | |
647 // Note: the request may still have been cancelled while OnReadCompleted | |
648 // returns true if OnReadCompleted caused request to get cancelled | |
649 // out-of-band. (In AwResourceDispatcherHostDelegate::DownloadStarting, for | |
650 // instance.) | |
651 } | 716 } |
652 | 717 |
653 void ResourceLoader::ResponseCompleted() { | 718 void ResourceLoader::ResponseCompleted() { |
654 TRACE_EVENT_WITH_FLOW0("loading", "ResourceLoader::ResponseCompleted", this, | 719 TRACE_EVENT_WITH_FLOW0("loading", "ResourceLoader::ResponseCompleted", this, |
655 TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT); | 720 TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT); |
656 | 721 |
657 DVLOG(1) << "ResponseCompleted: " << request_->url().spec(); | 722 DVLOG(1) << "ResponseCompleted: " << request_->url().spec(); |
658 RecordHistograms(); | 723 RecordHistograms(); |
659 | 724 |
660 bool defer = false; | 725 // TODO(darin): Remove ScopedTracker below once crbug.com/475761 is fixed. |
661 { | 726 tracked_objects::ScopedTracker tracking_profile( |
662 // TODO(darin): Remove ScopedTracker below once crbug.com/475761 is fixed. | 727 FROM_HERE_WITH_EXPLICIT_FUNCTION("475761 OnResponseCompleted()")); |
663 tracked_objects::ScopedTracker tracking_profile( | |
664 FROM_HERE_WITH_EXPLICIT_FUNCTION("475761 OnResponseCompleted()")); | |
665 | 728 |
666 handler_->OnResponseCompleted(request_->status(), &defer); | 729 ScopedDeferral scoped_deferral(this, DEFERRED_FINISH); |
667 } | 730 handler_->OnResponseCompleted(request_->status(), |
668 if (defer) { | 731 base::MakeUnique<Controller>(this)); |
669 // The handler is not ready to die yet. We will call DidFinishLoading when | |
670 // we resume. | |
671 deferred_stage_ = DEFERRED_FINISH; | |
672 } else { | |
673 // This will result in our destruction. | |
674 CallDidFinishLoading(); | |
675 } | |
676 } | 732 } |
677 | 733 |
678 void ResourceLoader::CallDidFinishLoading() { | 734 void ResourceLoader::CallDidFinishLoading() { |
679 TRACE_EVENT_WITH_FLOW0("loading", "ResourceLoader::CallDidFinishLoading", | 735 TRACE_EVENT_WITH_FLOW0("loading", "ResourceLoader::CallDidFinishLoading", |
680 this, TRACE_EVENT_FLAG_FLOW_IN); | 736 this, TRACE_EVENT_FLAG_FLOW_IN); |
681 delegate_->DidFinishLoading(this); | 737 delegate_->DidFinishLoading(this); |
682 } | 738 } |
683 | 739 |
684 void ResourceLoader::RecordHistograms() { | 740 void ResourceLoader::RecordHistograms() { |
685 ResourceRequestInfoImpl* info = GetRequestInfo(); | 741 ResourceRequestInfoImpl* info = GetRequestInfo(); |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
740 UMA_HISTOGRAM_ENUMERATION("Net.Prefetch.Pattern", prefetch_status, | 796 UMA_HISTOGRAM_ENUMERATION("Net.Prefetch.Pattern", prefetch_status, |
741 STATUS_MAX); | 797 STATUS_MAX); |
742 } | 798 } |
743 } else if (request_->response_info().unused_since_prefetch) { | 799 } else if (request_->response_info().unused_since_prefetch) { |
744 TimeDelta total_time = base::TimeTicks::Now() - request_->creation_time(); | 800 TimeDelta total_time = base::TimeTicks::Now() - request_->creation_time(); |
745 UMA_HISTOGRAM_TIMES("Net.Prefetch.TimeSpentOnPrefetchHit", total_time); | 801 UMA_HISTOGRAM_TIMES("Net.Prefetch.TimeSpentOnPrefetchHit", total_time); |
746 } | 802 } |
747 } | 803 } |
748 | 804 |
749 } // namespace content | 805 } // namespace content |
OLD | NEW |