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 DCHECK(!done_); |
| 145 done_ = true; |
| 146 resource_loader_->Resume(true); |
| 147 } |
| 148 |
| 149 void Cancel() override { |
| 150 DCHECK(!done_); |
| 151 done_ = true; |
| 152 resource_loader_->Cancel(); |
| 153 } |
| 154 |
| 155 void CancelAndIgnore() override { |
| 156 DCHECK(!done_); |
| 157 done_ = true; |
| 158 resource_loader_->CancelAndIgnore(); |
| 159 } |
| 160 |
| 161 void CancelWithError(int error_code) override { |
| 162 DCHECK(!done_); |
| 163 done_ = true; |
| 164 resource_loader_->CancelWithError(error_code); |
| 165 } |
| 166 |
| 167 private: |
| 168 ResourceLoader* const resource_loader_; |
| 169 |
| 170 // Set to true once one of the ResourceContoller methods has been invoked. |
| 171 bool done_ = false; |
| 172 |
| 173 DISALLOW_COPY_AND_ASSIGN(Controller); |
| 174 }; |
| 175 |
| 176 // Helper class. Sets the stage of a ResourceLoader to DEFERRED_SYNC on |
| 177 // construction, and on destruction does one of the following: |
| 178 // 1) If the ResourceLoader has a deferred stage of DEFERRED_NONE, sets the |
| 179 // ResourceLoader's stage to the stage specified on construction and resumes it. |
| 180 // 2) If the ResourceLoader still has a deferred stage of DEFERRED_SYNC, sets |
| 181 // the ResourceLoader's stage to the stage specified on construction. The |
| 182 // ResourceLoader will be resumed at some point in the future. |
| 183 class ResourceLoader::ScopedDeferral { |
| 184 public: |
| 185 ScopedDeferral(ResourceLoader* resource_loader, |
| 186 ResourceLoader::DeferredStage deferred_stage) |
| 187 : resource_loader_(resource_loader), deferred_stage_(deferred_stage) { |
| 188 resource_loader_->deferred_stage_ = DEFERRED_SYNC; |
| 189 } |
| 190 |
| 191 ~ScopedDeferral() { |
| 192 DeferredStage old_deferred_stage = resource_loader_->deferred_stage_; |
| 193 resource_loader_->deferred_stage_ = deferred_stage_; |
| 194 if (old_deferred_stage == DEFERRED_NONE) |
| 195 resource_loader_->Resume(false); |
| 196 } |
| 197 |
| 198 private: |
| 199 ResourceLoader* const resource_loader_; |
| 200 const DeferredStage deferred_stage_; |
| 201 |
| 202 DISALLOW_COPY_AND_ASSIGN(ScopedDeferral); |
| 203 }; |
| 204 |
133 ResourceLoader::ResourceLoader(std::unique_ptr<net::URLRequest> request, | 205 ResourceLoader::ResourceLoader(std::unique_ptr<net::URLRequest> request, |
134 std::unique_ptr<ResourceHandler> handler, | 206 std::unique_ptr<ResourceHandler> handler, |
135 ResourceLoaderDelegate* delegate) | 207 ResourceLoaderDelegate* delegate) |
136 : deferred_stage_(DEFERRED_NONE), | 208 : deferred_stage_(DEFERRED_NONE), |
137 request_(std::move(request)), | 209 request_(std::move(request)), |
138 handler_(std::move(handler)), | 210 handler_(std::move(handler)), |
139 delegate_(delegate), | 211 delegate_(delegate), |
140 is_transferring_(false), | 212 is_transferring_(false), |
141 times_cancelled_before_request_start_(0), | 213 times_cancelled_before_request_start_(0), |
142 started_request_(false), | 214 started_request_(false), |
143 times_cancelled_after_request_start_(0), | 215 times_cancelled_after_request_start_(0), |
144 weak_ptr_factory_(this) { | 216 weak_ptr_factory_(this) { |
145 request_->set_delegate(this); | 217 request_->set_delegate(this); |
146 handler_->SetController(this); | 218 handler_->SetDelegate(this); |
147 } | 219 } |
148 | 220 |
149 ResourceLoader::~ResourceLoader() { | 221 ResourceLoader::~ResourceLoader() { |
150 if (login_delegate_.get()) | 222 if (login_delegate_.get()) |
151 login_delegate_->OnRequestCancelled(); | 223 login_delegate_->OnRequestCancelled(); |
152 ssl_client_auth_handler_.reset(); | 224 ssl_client_auth_handler_.reset(); |
153 | 225 |
154 // Run ResourceHandler destructor before we tear-down the rest of our state | 226 // 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. | 227 // as the ResourceHandler may want to inspect the URLRequest and other state. |
156 handler_.reset(); | 228 handler_.reset(); |
157 } | 229 } |
158 | 230 |
159 void ResourceLoader::StartRequest() { | 231 void ResourceLoader::StartRequest() { |
160 if (delegate_->HandleExternalProtocol(this, request_->url())) { | 232 if (delegate_->HandleExternalProtocol(this, request_->url())) { |
161 CancelAndIgnore(); | 233 CancelAndIgnore(); |
162 return; | 234 return; |
163 } | 235 } |
164 | 236 |
165 // Give the handler a chance to delay the URLRequest from being started. | 237 ScopedDeferral scoped_deferral(this, DEFERRED_START); |
166 bool defer_start = false; | 238 handler_->OnWillStart(request_->url(), base::MakeUnique<Controller>(this)); |
167 if (!handler_->OnWillStart(request_->url(), &defer_start)) { | |
168 Cancel(); | |
169 return; | |
170 } | |
171 | |
172 TRACE_EVENT_WITH_FLOW0("loading", "ResourceLoader::StartRequest", this, | |
173 TRACE_EVENT_FLAG_FLOW_OUT); | |
174 if (defer_start) { | |
175 deferred_stage_ = DEFERRED_START; | |
176 } else { | |
177 StartRequestInternal(); | |
178 } | |
179 } | 239 } |
180 | 240 |
181 void ResourceLoader::CancelRequest(bool from_renderer) { | 241 void ResourceLoader::CancelRequest(bool from_renderer) { |
182 TRACE_EVENT_WITH_FLOW0("loading", "ResourceLoader::CancelRequest", this, | 242 TRACE_EVENT_WITH_FLOW0("loading", "ResourceLoader::CancelRequest", this, |
183 TRACE_EVENT_FLAG_FLOW_IN); | 243 TRACE_EVENT_FLAG_FLOW_IN); |
184 CancelRequestInternal(net::ERR_ABORTED, from_renderer); | 244 CancelRequestInternal(net::ERR_ABORTED, from_renderer); |
185 } | 245 } |
186 | 246 |
187 void ResourceLoader::CancelAndIgnore() { | 247 void ResourceLoader::CancelAndIgnore() { |
188 ResourceRequestInfoImpl* info = GetRequestInfo(); | 248 ResourceRequestInfoImpl* info = GetRequestInfo(); |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
237 } | 297 } |
238 | 298 |
239 ResourceRequestInfoImpl* ResourceLoader::GetRequestInfo() { | 299 ResourceRequestInfoImpl* ResourceLoader::GetRequestInfo() { |
240 return ResourceRequestInfoImpl::ForRequest(request_.get()); | 300 return ResourceRequestInfoImpl::ForRequest(request_.get()); |
241 } | 301 } |
242 | 302 |
243 void ResourceLoader::ClearLoginDelegate() { | 303 void ResourceLoader::ClearLoginDelegate() { |
244 login_delegate_ = NULL; | 304 login_delegate_ = NULL; |
245 } | 305 } |
246 | 306 |
| 307 void ResourceLoader::OutOfBandCancel(int error_code, bool tell_renderer) { |
| 308 CancelRequestInternal(error_code, !tell_renderer); |
| 309 } |
| 310 |
247 void ResourceLoader::OnReceivedRedirect(net::URLRequest* unused, | 311 void ResourceLoader::OnReceivedRedirect(net::URLRequest* unused, |
248 const net::RedirectInfo& redirect_info, | 312 const net::RedirectInfo& redirect_info, |
249 bool* defer) { | 313 bool* defer) { |
250 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("loading"), | 314 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("loading"), |
251 "ResourceLoader::OnReceivedRedirect"); | 315 "ResourceLoader::OnReceivedRedirect"); |
252 DCHECK_EQ(request_.get(), unused); | 316 DCHECK_EQ(request_.get(), unused); |
253 | 317 |
254 DVLOG(1) << "OnReceivedRedirect: " << request_->url().spec(); | 318 DVLOG(1) << "OnReceivedRedirect: " << request_->url().spec(); |
255 DCHECK(request_->status().is_success()); | 319 DCHECK(request_->status().is_success()); |
256 | 320 |
(...skipping 18 matching lines...) Expand all Loading... |
275 | 339 |
276 if (delegate_->HandleExternalProtocol(this, redirect_info.new_url)) { | 340 if (delegate_->HandleExternalProtocol(this, redirect_info.new_url)) { |
277 // The request is complete so we can remove it. | 341 // The request is complete so we can remove it. |
278 CancelAndIgnore(); | 342 CancelAndIgnore(); |
279 return; | 343 return; |
280 } | 344 } |
281 | 345 |
282 scoped_refptr<ResourceResponse> response = new ResourceResponse(); | 346 scoped_refptr<ResourceResponse> response = new ResourceResponse(); |
283 PopulateResourceResponse(info, request_.get(), response.get()); | 347 PopulateResourceResponse(info, request_.get(), response.get()); |
284 delegate_->DidReceiveRedirect(this, redirect_info.new_url, response.get()); | 348 delegate_->DidReceiveRedirect(this, redirect_info.new_url, response.get()); |
285 if (!handler_->OnRequestRedirected(redirect_info, response.get(), defer)) { | 349 |
286 Cancel(); | 350 // Can't used ScopedDeferral here, because on sync completion, need to set |
287 } else if (*defer) { | 351 // |defer| to false instead of calling back into the URLRequest. |
288 deferred_stage_ = DEFERRED_REDIRECT; // Follow redirect when resumed. | 352 deferred_stage_ = DEFERRED_SYNC; |
| 353 handler_->OnRequestRedirected(redirect_info, response.get(), |
| 354 base::MakeUnique<Controller>(this)); |
| 355 if (!is_deferred()) { |
| 356 *defer = false; |
| 357 return; |
289 } | 358 } |
| 359 |
| 360 *defer = true; |
| 361 deferred_stage_ = DEFERRED_REDIRECT; |
290 } | 362 } |
291 | 363 |
292 void ResourceLoader::OnAuthRequired(net::URLRequest* unused, | 364 void ResourceLoader::OnAuthRequired(net::URLRequest* unused, |
293 net::AuthChallengeInfo* auth_info) { | 365 net::AuthChallengeInfo* auth_info) { |
294 DCHECK_EQ(request_.get(), unused); | 366 DCHECK_EQ(request_.get(), unused); |
295 | 367 |
296 ResourceRequestInfoImpl* info = GetRequestInfo(); | 368 ResourceRequestInfoImpl* info = GetRequestInfo(); |
297 if (info->do_not_prompt_for_login()) { | 369 if (info->do_not_prompt_for_login()) { |
298 request_->CancelAuth(); | 370 request_->CancelAuth(); |
299 return; | 371 return; |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
342 DCHECK_EQ(request_.get(), unused); | 414 DCHECK_EQ(request_.get(), unused); |
343 | 415 |
344 DVLOG(1) << "OnResponseStarted: " << request_->url().spec(); | 416 DVLOG(1) << "OnResponseStarted: " << request_->url().spec(); |
345 | 417 |
346 if (!request_->status().is_success()) { | 418 if (!request_->status().is_success()) { |
347 ResponseCompleted(); | 419 ResponseCompleted(); |
348 return; | 420 return; |
349 } | 421 } |
350 | 422 |
351 CompleteResponseStarted(); | 423 CompleteResponseStarted(); |
352 | |
353 // If the handler deferred the request, it will resume the request later. If | |
354 // the request was cancelled, the request will call back into |this| with a | |
355 // bogus read completed error. | |
356 if (is_deferred() || !request_->status().is_success()) | |
357 return; | |
358 | |
359 ReadMore(false); // Read the first chunk. | |
360 } | 424 } |
361 | 425 |
362 void ResourceLoader::OnReadCompleted(net::URLRequest* unused, int bytes_read) { | 426 void ResourceLoader::OnReadCompleted(net::URLRequest* unused, int bytes_read) { |
363 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("loading"), | 427 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("loading"), |
364 "ResourceLoader::OnReadCompleted"); | 428 "ResourceLoader::OnReadCompleted"); |
365 DCHECK_EQ(request_.get(), unused); | 429 DCHECK_EQ(request_.get(), unused); |
366 DVLOG(1) << "OnReadCompleted: \"" << request_->url().spec() << "\"" | 430 DVLOG(1) << "OnReadCompleted: \"" << request_->url().spec() << "\"" |
367 << " bytes_read = " << bytes_read; | 431 << " bytes_read = " << bytes_read; |
368 | 432 |
369 // bytes_read == -1 always implies an error. | 433 // bytes_read == -1 always implies an error. |
370 if (bytes_read == -1 || !request_->status().is_success()) { | 434 if (bytes_read == -1 || !request_->status().is_success()) { |
371 ResponseCompleted(); | 435 ResponseCompleted(); |
372 return; | 436 return; |
373 } | 437 } |
374 | 438 |
375 CompleteRead(bytes_read); | 439 CompleteRead(bytes_read); |
376 | |
377 // If the handler cancelled or deferred the request, do not continue | |
378 // processing the read. If canceled, either the request will call into |this| | |
379 // with a bogus read error, or, if the request was completed, a task posted | |
380 // from ResourceLoader::CancelREquestInternal will run OnResponseCompleted. | |
381 if (is_deferred() || !request_->status().is_success()) | |
382 return; | |
383 | |
384 if (bytes_read > 0) { | |
385 ReadMore(true); // Read the next chunk. | |
386 } else { | |
387 // TODO(darin): Remove ScopedTracker below once crbug.com/475761 is fixed. | |
388 tracked_objects::ScopedTracker tracking_profile( | |
389 FROM_HERE_WITH_EXPLICIT_FUNCTION("475761 ResponseCompleted()")); | |
390 | |
391 // URLRequest reported an EOF. Call ResponseCompleted. | |
392 DCHECK_EQ(0, bytes_read); | |
393 ResponseCompleted(); | |
394 } | |
395 } | 440 } |
396 | 441 |
397 void ResourceLoader::CancelSSLRequest(int error, | 442 void ResourceLoader::CancelSSLRequest(int error, |
398 const net::SSLInfo* ssl_info) { | 443 const net::SSLInfo* ssl_info) { |
399 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 444 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
400 | 445 |
401 // The request can be NULL if it was cancelled by the renderer (as the | 446 // The request can be NULL if it was cancelled by the renderer (as the |
402 // request of the user navigating to a new page from the location bar). | 447 // request of the user navigating to a new page from the location bar). |
403 if (!request_->is_pending()) | 448 if (!request_->is_pending()) |
404 return; | 449 return; |
(...skipping 25 matching lines...) Expand all Loading... |
430 net::FetchClientCertPrivateKey(cert); | 475 net::FetchClientCertPrivateKey(cert); |
431 request_->ContinueWithCertificate(cert, private_key.get()); | 476 request_->ContinueWithCertificate(cert, private_key.get()); |
432 } | 477 } |
433 | 478 |
434 void ResourceLoader::CancelCertificateSelection() { | 479 void ResourceLoader::CancelCertificateSelection() { |
435 DCHECK(ssl_client_auth_handler_); | 480 DCHECK(ssl_client_auth_handler_); |
436 ssl_client_auth_handler_.reset(); | 481 ssl_client_auth_handler_.reset(); |
437 request_->CancelWithError(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED); | 482 request_->CancelWithError(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED); |
438 } | 483 } |
439 | 484 |
440 void ResourceLoader::Resume() { | 485 void ResourceLoader::Resume(bool called_from_resource_controller) { |
441 DCHECK(!is_transferring_); | 486 DCHECK(!is_transferring_); |
442 | 487 |
443 DeferredStage stage = deferred_stage_; | 488 DeferredStage stage = deferred_stage_; |
444 deferred_stage_ = DEFERRED_NONE; | 489 deferred_stage_ = DEFERRED_NONE; |
445 switch (stage) { | 490 switch (stage) { |
446 case DEFERRED_NONE: | 491 case DEFERRED_NONE: |
447 NOTREACHED(); | 492 NOTREACHED(); |
448 break; | 493 break; |
| 494 case DEFERRED_SYNC: |
| 495 DCHECK(called_from_resource_controller); |
| 496 // Request will be resumed when the stack unwinds. |
| 497 break; |
449 case DEFERRED_START: | 498 case DEFERRED_START: |
| 499 // Starting requests completes asynchronously, so starting the request now |
450 StartRequestInternal(); | 500 StartRequestInternal(); |
451 break; | 501 break; |
452 case DEFERRED_REDIRECT: | 502 case DEFERRED_REDIRECT: |
453 request_->FollowDeferredRedirect(); | 503 request_->FollowDeferredRedirect(); |
454 break; | 504 break; |
455 case DEFERRED_READ: | 505 case DEFERRED_READ: |
456 base::ThreadTaskRunnerHandle::Get()->PostTask( | 506 if (!called_from_resource_controller) { |
457 FROM_HERE, base::Bind(&ResourceLoader::ResumeReading, | 507 ReadMore(called_from_resource_controller); |
458 weak_ptr_factory_.GetWeakPtr())); | 508 } else { |
| 509 base::ThreadTaskRunnerHandle::Get()->PostTask( |
| 510 FROM_HERE, base::Bind(&ResourceLoader::ResumeReading, |
| 511 weak_ptr_factory_.GetWeakPtr())); |
| 512 } |
459 break; | 513 break; |
460 case DEFERRED_RESPONSE_COMPLETE: | 514 case DEFERRED_RESPONSE_COMPLETE: |
461 base::ThreadTaskRunnerHandle::Get()->PostTask( | 515 if (!called_from_resource_controller) { |
462 FROM_HERE, base::Bind(&ResourceLoader::ResponseCompleted, | 516 ResponseCompleted(); |
463 weak_ptr_factory_.GetWeakPtr())); | 517 } else { |
| 518 base::ThreadTaskRunnerHandle::Get()->PostTask( |
| 519 FROM_HERE, base::Bind(&ResourceLoader::ResponseCompleted, |
| 520 weak_ptr_factory_.GetWeakPtr())); |
| 521 } |
464 break; | 522 break; |
465 case DEFERRED_FINISH: | 523 case DEFERRED_FINISH: |
466 // Delay self-destruction since we don't know how we were reached. | 524 if (!called_from_resource_controller) { |
467 base::ThreadTaskRunnerHandle::Get()->PostTask( | 525 CallDidFinishLoading(); |
468 FROM_HERE, base::Bind(&ResourceLoader::CallDidFinishLoading, | 526 } else { |
469 weak_ptr_factory_.GetWeakPtr())); | 527 // Delay self-destruction since we don't know how we were reached. |
| 528 base::ThreadTaskRunnerHandle::Get()->PostTask( |
| 529 FROM_HERE, base::Bind(&ResourceLoader::CallDidFinishLoading, |
| 530 weak_ptr_factory_.GetWeakPtr())); |
| 531 } |
470 break; | 532 break; |
471 } | 533 } |
472 } | 534 } |
473 | 535 |
474 void ResourceLoader::Cancel() { | 536 void ResourceLoader::Cancel() { |
475 CancelRequest(false); | 537 CancelRequest(false); |
476 } | 538 } |
477 | 539 |
478 void ResourceLoader::StartRequestInternal() { | 540 void ResourceLoader::StartRequestInternal() { |
479 DCHECK(!request_->is_pending()); | 541 DCHECK(!request_->is_pending()); |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
538 ResourceRequestInfoImpl* info = GetRequestInfo(); | 600 ResourceRequestInfoImpl* info = GetRequestInfo(); |
539 scoped_refptr<ResourceResponse> response = new ResourceResponse(); | 601 scoped_refptr<ResourceResponse> response = new ResourceResponse(); |
540 PopulateResourceResponse(info, request_.get(), response.get()); | 602 PopulateResourceResponse(info, request_.get(), response.get()); |
541 | 603 |
542 delegate_->DidReceiveResponse(this); | 604 delegate_->DidReceiveResponse(this); |
543 | 605 |
544 // TODO(darin): Remove ScopedTracker below once crbug.com/475761 is fixed. | 606 // TODO(darin): Remove ScopedTracker below once crbug.com/475761 is fixed. |
545 tracked_objects::ScopedTracker tracking_profile( | 607 tracked_objects::ScopedTracker tracking_profile( |
546 FROM_HERE_WITH_EXPLICIT_FUNCTION("475761 OnResponseStarted()")); | 608 FROM_HERE_WITH_EXPLICIT_FUNCTION("475761 OnResponseStarted()")); |
547 | 609 |
548 bool defer = false; | 610 read_deferral_start_time_ = base::TimeTicks::Now(); |
549 if (!handler_->OnResponseStarted(response.get(), &defer)) { | 611 ScopedDeferral scoped_deferral(this, DEFERRED_READ); |
550 Cancel(); | 612 handler_->OnResponseStarted(response.get(), |
551 } else if (defer) { | 613 base::MakeUnique<Controller>(this)); |
552 read_deferral_start_time_ = base::TimeTicks::Now(); | |
553 deferred_stage_ = DEFERRED_READ; // Read first chunk when resumed. | |
554 } | |
555 } | 614 } |
556 | 615 |
557 void ResourceLoader::ReadMore(bool is_continuation) { | 616 void ResourceLoader::ReadMore(bool called_from_resource_controller) { |
558 TRACE_EVENT_WITH_FLOW0("loading", "ResourceLoader::ReadMore", this, | 617 TRACE_EVENT_WITH_FLOW0("loading", "ResourceLoader::ReadMore", this, |
559 TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT); | 618 TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT); |
560 DCHECK(!is_deferred()); | 619 DCHECK(!is_deferred()); |
561 | 620 |
562 // Make sure we track the buffer in at least one place. This ensures it gets | 621 // Make sure we track the buffer in at least one place. This ensures it gets |
563 // deleted even in the case the request has already finished its job and | 622 // deleted even in the case the request has already finished its job and |
564 // doesn't use the buffer. | 623 // doesn't use the buffer. |
565 scoped_refptr<net::IOBuffer> buf; | 624 scoped_refptr<net::IOBuffer> buf; |
566 int buf_size; | 625 int buf_size; |
567 { | 626 { |
(...skipping 10 matching lines...) Expand all Loading... |
578 } | 637 } |
579 | 638 |
580 DCHECK(buf.get()); | 639 DCHECK(buf.get()); |
581 DCHECK(buf_size > 0); | 640 DCHECK(buf_size > 0); |
582 | 641 |
583 int result = request_->Read(buf.get(), buf_size); | 642 int result = request_->Read(buf.get(), buf_size); |
584 | 643 |
585 if (result == net::ERR_IO_PENDING) | 644 if (result == net::ERR_IO_PENDING) |
586 return; | 645 return; |
587 | 646 |
588 if (!is_continuation || result <= 0) { | 647 if (!called_from_resource_controller || result <= 0) { |
589 OnReadCompleted(request_.get(), result); | 648 OnReadCompleted(request_.get(), result); |
590 } else { | 649 } else { |
591 // Else, trigger OnReadCompleted asynchronously to avoid starving the IO | 650 // Else, trigger OnReadCompleted asynchronously to avoid starving the IO |
592 // thread in case the URLRequest can provide data synchronously. | 651 // thread in case the URLRequest can provide data synchronously. |
593 base::ThreadTaskRunnerHandle::Get()->PostTask( | 652 base::ThreadTaskRunnerHandle::Get()->PostTask( |
594 FROM_HERE, | 653 FROM_HERE, |
595 base::Bind(&ResourceLoader::OnReadCompleted, | 654 base::Bind(&ResourceLoader::OnReadCompleted, |
596 weak_ptr_factory_.GetWeakPtr(), request_.get(), result)); | 655 weak_ptr_factory_.GetWeakPtr(), request_.get(), result)); |
597 } | 656 } |
598 } | 657 } |
(...skipping 17 matching lines...) Expand all Loading... |
616 TRACE_EVENT_WITH_FLOW0("loading", "ResourceLoader::CompleteRead", this, | 675 TRACE_EVENT_WITH_FLOW0("loading", "ResourceLoader::CompleteRead", this, |
617 TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT); | 676 TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT); |
618 | 677 |
619 DCHECK(bytes_read >= 0); | 678 DCHECK(bytes_read >= 0); |
620 DCHECK(request_->status().is_success()); | 679 DCHECK(request_->status().is_success()); |
621 | 680 |
622 // TODO(darin): Remove ScopedTracker below once crbug.com/475761 is fixed. | 681 // TODO(darin): Remove ScopedTracker below once crbug.com/475761 is fixed. |
623 tracked_objects::ScopedTracker tracking_profile( | 682 tracked_objects::ScopedTracker tracking_profile( |
624 FROM_HERE_WITH_EXPLICIT_FUNCTION("475761 OnReadCompleted()")); | 683 FROM_HERE_WITH_EXPLICIT_FUNCTION("475761 OnReadCompleted()")); |
625 | 684 |
626 bool defer = false; | 685 ScopedDeferral scoped_deferral( |
627 if (!handler_->OnReadCompleted(bytes_read, &defer)) { | 686 this, bytes_read > 0 ? DEFERRED_READ : DEFERRED_RESPONSE_COMPLETE); |
628 Cancel(); | 687 handler_->OnReadCompleted(bytes_read, base::MakeUnique<Controller>(this)); |
629 } else if (defer) { | |
630 deferred_stage_ = | |
631 bytes_read > 0 ? DEFERRED_READ : DEFERRED_RESPONSE_COMPLETE; | |
632 } | |
633 | |
634 // Note: the request may still have been cancelled while OnReadCompleted | |
635 // returns true if OnReadCompleted caused request to get cancelled | |
636 // out-of-band. (In AwResourceDispatcherHostDelegate::DownloadStarting, for | |
637 // instance.) | |
638 } | 688 } |
639 | 689 |
640 void ResourceLoader::ResponseCompleted() { | 690 void ResourceLoader::ResponseCompleted() { |
641 TRACE_EVENT_WITH_FLOW0("loading", "ResourceLoader::ResponseCompleted", this, | 691 TRACE_EVENT_WITH_FLOW0("loading", "ResourceLoader::ResponseCompleted", this, |
642 TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT); | 692 TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT); |
643 | 693 |
644 DVLOG(1) << "ResponseCompleted: " << request_->url().spec(); | 694 DVLOG(1) << "ResponseCompleted: " << request_->url().spec(); |
645 RecordHistograms(); | 695 RecordHistograms(); |
646 | 696 |
647 bool defer = false; | 697 // TODO(darin): Remove ScopedTracker below once crbug.com/475761 is fixed. |
648 { | 698 tracked_objects::ScopedTracker tracking_profile( |
649 // TODO(darin): Remove ScopedTracker below once crbug.com/475761 is fixed. | 699 FROM_HERE_WITH_EXPLICIT_FUNCTION("475761 OnResponseCompleted()")); |
650 tracked_objects::ScopedTracker tracking_profile( | |
651 FROM_HERE_WITH_EXPLICIT_FUNCTION("475761 OnResponseCompleted()")); | |
652 | 700 |
653 handler_->OnResponseCompleted(request_->status(), &defer); | 701 ScopedDeferral scoped_deferral(this, DEFERRED_FINISH); |
654 } | 702 handler_->OnResponseCompleted(request_->status(), |
655 if (defer) { | 703 base::MakeUnique<Controller>(this)); |
656 // The handler is not ready to die yet. We will call DidFinishLoading when | |
657 // we resume. | |
658 deferred_stage_ = DEFERRED_FINISH; | |
659 } else { | |
660 // This will result in our destruction. | |
661 CallDidFinishLoading(); | |
662 } | |
663 } | 704 } |
664 | 705 |
665 void ResourceLoader::CallDidFinishLoading() { | 706 void ResourceLoader::CallDidFinishLoading() { |
666 TRACE_EVENT_WITH_FLOW0("loading", "ResourceLoader::CallDidFinishLoading", | 707 TRACE_EVENT_WITH_FLOW0("loading", "ResourceLoader::CallDidFinishLoading", |
667 this, TRACE_EVENT_FLAG_FLOW_IN); | 708 this, TRACE_EVENT_FLAG_FLOW_IN); |
668 delegate_->DidFinishLoading(this); | 709 delegate_->DidFinishLoading(this); |
669 } | 710 } |
670 | 711 |
671 void ResourceLoader::RecordHistograms() { | 712 void ResourceLoader::RecordHistograms() { |
672 ResourceRequestInfoImpl* info = GetRequestInfo(); | 713 ResourceRequestInfoImpl* info = GetRequestInfo(); |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
727 UMA_HISTOGRAM_ENUMERATION("Net.Prefetch.Pattern", prefetch_status, | 768 UMA_HISTOGRAM_ENUMERATION("Net.Prefetch.Pattern", prefetch_status, |
728 STATUS_MAX); | 769 STATUS_MAX); |
729 } | 770 } |
730 } else if (request_->response_info().unused_since_prefetch) { | 771 } else if (request_->response_info().unused_since_prefetch) { |
731 TimeDelta total_time = base::TimeTicks::Now() - request_->creation_time(); | 772 TimeDelta total_time = base::TimeTicks::Now() - request_->creation_time(); |
732 UMA_HISTOGRAM_TIMES("Net.Prefetch.TimeSpentOnPrefetchHit", total_time); | 773 UMA_HISTOGRAM_TIMES("Net.Prefetch.TimeSpentOnPrefetchHit", total_time); |
733 } | 774 } |
734 } | 775 } |
735 | 776 |
736 } // namespace content | 777 } // namespace content |
OLD | NEW |