Chromium Code Reviews| 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) | |
| 202 << old_deferred_stage; | |
| 203 resource_loader_->deferred_stage_ = deferred_stage_; | |
| 204 // If Resume() was called, it just advanced the state without doing | |
| 205 // anything. Go ahead and resume the request now. | |
| 206 if (old_deferred_stage == DEFERRED_NONE) | |
| 207 resource_loader_->Resume(false /* called_from_resource_controller */); | |
| 208 } | |
| 209 | |
| 210 private: | |
| 211 ResourceLoader* const resource_loader_; | |
| 212 const DeferredStage deferred_stage_; | |
| 213 | |
| 214 DISALLOW_COPY_AND_ASSIGN(ScopedDeferral); | |
| 215 }; | |
| 216 | |
| 133 ResourceLoader::ResourceLoader(std::unique_ptr<net::URLRequest> request, | 217 ResourceLoader::ResourceLoader(std::unique_ptr<net::URLRequest> request, |
| 134 std::unique_ptr<ResourceHandler> handler, | 218 std::unique_ptr<ResourceHandler> handler, |
| 135 ResourceLoaderDelegate* delegate) | 219 ResourceLoaderDelegate* delegate) |
| 136 : deferred_stage_(DEFERRED_NONE), | 220 : deferred_stage_(DEFERRED_NONE), |
| 137 request_(std::move(request)), | 221 request_(std::move(request)), |
| 138 handler_(std::move(handler)), | 222 handler_(std::move(handler)), |
| 139 delegate_(delegate), | 223 delegate_(delegate), |
| 140 is_transferring_(false), | 224 is_transferring_(false), |
| 141 times_cancelled_before_request_start_(0), | 225 times_cancelled_before_request_start_(0), |
| 142 started_request_(false), | 226 started_request_(false), |
| 143 times_cancelled_after_request_start_(0), | 227 times_cancelled_after_request_start_(0), |
| 144 weak_ptr_factory_(this) { | 228 weak_ptr_factory_(this) { |
| 145 request_->set_delegate(this); | 229 request_->set_delegate(this); |
| 146 handler_->SetController(this); | 230 handler_->SetDelegate(this); |
| 147 } | 231 } |
| 148 | 232 |
| 149 ResourceLoader::~ResourceLoader() { | 233 ResourceLoader::~ResourceLoader() { |
| 150 if (login_delegate_.get()) | 234 if (login_delegate_.get()) |
| 151 login_delegate_->OnRequestCancelled(); | 235 login_delegate_->OnRequestCancelled(); |
| 152 ssl_client_auth_handler_.reset(); | 236 ssl_client_auth_handler_.reset(); |
| 153 | 237 |
| 154 // Run ResourceHandler destructor before we tear-down the rest of our state | 238 // 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. | 239 // as the ResourceHandler may want to inspect the URLRequest and other state. |
| 156 handler_.reset(); | 240 handler_.reset(); |
| 157 } | 241 } |
| 158 | 242 |
| 159 void ResourceLoader::StartRequest() { | 243 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, | 244 TRACE_EVENT_WITH_FLOW0("loading", "ResourceLoader::StartRequest", this, |
| 168 TRACE_EVENT_FLAG_FLOW_OUT); | 245 TRACE_EVENT_FLAG_FLOW_OUT); |
| 169 if (defer_start) { | 246 |
| 170 deferred_stage_ = DEFERRED_START; | 247 ScopedDeferral scoped_deferral(this, DEFERRED_START); |
| 171 } else { | 248 handler_->OnWillStart(request_->url(), base::MakeUnique<Controller>(this)); |
| 172 StartRequestInternal(); | |
| 173 } | |
| 174 } | 249 } |
| 175 | 250 |
| 176 void ResourceLoader::CancelRequest(bool from_renderer) { | 251 void ResourceLoader::CancelRequest(bool from_renderer) { |
| 177 TRACE_EVENT_WITH_FLOW0("loading", "ResourceLoader::CancelRequest", this, | 252 TRACE_EVENT_WITH_FLOW0("loading", "ResourceLoader::CancelRequest", this, |
| 178 TRACE_EVENT_FLAG_FLOW_IN); | 253 TRACE_EVENT_FLAG_FLOW_IN); |
| 179 CancelRequestInternal(net::ERR_ABORTED, from_renderer); | 254 CancelRequestInternal(net::ERR_ABORTED, from_renderer); |
| 180 } | 255 } |
| 181 | 256 |
| 182 void ResourceLoader::CancelAndIgnore() { | 257 void ResourceLoader::CancelAndIgnore() { |
| 183 ResourceRequestInfoImpl* info = GetRequestInfo(); | 258 ResourceRequestInfoImpl* info = GetRequestInfo(); |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 232 } | 307 } |
| 233 | 308 |
| 234 ResourceRequestInfoImpl* ResourceLoader::GetRequestInfo() { | 309 ResourceRequestInfoImpl* ResourceLoader::GetRequestInfo() { |
| 235 return ResourceRequestInfoImpl::ForRequest(request_.get()); | 310 return ResourceRequestInfoImpl::ForRequest(request_.get()); |
| 236 } | 311 } |
| 237 | 312 |
| 238 void ResourceLoader::ClearLoginDelegate() { | 313 void ResourceLoader::ClearLoginDelegate() { |
| 239 login_delegate_ = NULL; | 314 login_delegate_ = NULL; |
| 240 } | 315 } |
| 241 | 316 |
| 317 void ResourceLoader::OutOfBandCancel(int error_code, bool tell_renderer) { | |
| 318 CancelRequestInternal(error_code, !tell_renderer); | |
| 319 } | |
| 320 | |
| 242 void ResourceLoader::OnReceivedRedirect(net::URLRequest* unused, | 321 void ResourceLoader::OnReceivedRedirect(net::URLRequest* unused, |
| 243 const net::RedirectInfo& redirect_info, | 322 const net::RedirectInfo& redirect_info, |
| 244 bool* defer) { | 323 bool* defer) { |
| 245 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("loading"), | 324 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("loading"), |
| 246 "ResourceLoader::OnReceivedRedirect"); | 325 "ResourceLoader::OnReceivedRedirect"); |
| 247 DCHECK_EQ(request_.get(), unused); | 326 DCHECK_EQ(request_.get(), unused); |
| 248 | 327 |
| 249 DVLOG(1) << "OnReceivedRedirect: " << request_->url().spec(); | 328 DVLOG(1) << "OnReceivedRedirect: " << request_->url().spec(); |
| 250 DCHECK(request_->status().is_success()); | 329 DCHECK(request_->status().is_success()); |
| 251 | 330 |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 264 | 343 |
| 265 // Tell the renderer that this request was disallowed. | 344 // Tell the renderer that this request was disallowed. |
| 266 Cancel(); | 345 Cancel(); |
| 267 return; | 346 return; |
| 268 } | 347 } |
| 269 } | 348 } |
| 270 | 349 |
| 271 scoped_refptr<ResourceResponse> response = new ResourceResponse(); | 350 scoped_refptr<ResourceResponse> response = new ResourceResponse(); |
| 272 PopulateResourceResponse(info, request_.get(), response.get()); | 351 PopulateResourceResponse(info, request_.get(), response.get()); |
| 273 delegate_->DidReceiveRedirect(this, redirect_info.new_url, response.get()); | 352 delegate_->DidReceiveRedirect(this, redirect_info.new_url, response.get()); |
| 274 if (!handler_->OnRequestRedirected(redirect_info, response.get(), defer)) { | 353 |
| 275 Cancel(); | 354 // Can't used ScopedDeferral here, because on sync completion, need to set |
| 276 } else if (*defer) { | 355 // |defer| to false instead of calling back into the URLRequest. |
| 277 deferred_stage_ = DEFERRED_REDIRECT; // Follow redirect when resumed. | 356 deferred_stage_ = DEFERRED_SYNC; |
| 278 DCHECK(deferred_redirect_url_.is_empty()); | 357 handler_->OnRequestRedirected(redirect_info, response.get(), |
| 358 base::MakeUnique<Controller>(this)); | |
| 359 if (is_deferred()) { | |
| 360 *defer = true; | |
| 279 deferred_redirect_url_ = redirect_info.new_url; | 361 deferred_redirect_url_ = redirect_info.new_url; |
| 280 } else if (delegate_->HandleExternalProtocol(this, redirect_info.new_url)) { | 362 deferred_stage_ = DEFERRED_REDIRECT; |
| 281 // The request is complete so we can remove it. | 363 } else { |
| 282 CancelAndIgnore(); | 364 *defer = false; |
| 283 return; | 365 if (delegate_->HandleExternalProtocol(this, redirect_info.new_url)) |
| 366 CancelAndIgnore(); | |
| 284 } | 367 } |
| 285 } | 368 } |
| 286 | 369 |
| 287 void ResourceLoader::OnAuthRequired(net::URLRequest* unused, | 370 void ResourceLoader::OnAuthRequired(net::URLRequest* unused, |
| 288 net::AuthChallengeInfo* auth_info) { | 371 net::AuthChallengeInfo* auth_info) { |
| 289 DCHECK_EQ(request_.get(), unused); | 372 DCHECK_EQ(request_.get(), unused); |
| 290 | 373 |
| 291 ResourceRequestInfoImpl* info = GetRequestInfo(); | 374 ResourceRequestInfoImpl* info = GetRequestInfo(); |
| 292 if (info->do_not_prompt_for_login()) { | 375 if (info->do_not_prompt_for_login()) { |
| 293 request_->CancelAuth(); | 376 request_->CancelAuth(); |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 337 DCHECK_EQ(request_.get(), unused); | 420 DCHECK_EQ(request_.get(), unused); |
| 338 | 421 |
| 339 DVLOG(1) << "OnResponseStarted: " << request_->url().spec(); | 422 DVLOG(1) << "OnResponseStarted: " << request_->url().spec(); |
| 340 | 423 |
| 341 if (!request_->status().is_success()) { | 424 if (!request_->status().is_success()) { |
| 342 ResponseCompleted(); | 425 ResponseCompleted(); |
| 343 return; | 426 return; |
| 344 } | 427 } |
| 345 | 428 |
| 346 CompleteResponseStarted(); | 429 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 } | 430 } |
| 356 | 431 |
| 357 void ResourceLoader::OnReadCompleted(net::URLRequest* unused, int bytes_read) { | 432 void ResourceLoader::OnReadCompleted(net::URLRequest* unused, int bytes_read) { |
| 358 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("loading"), | 433 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("loading"), |
| 359 "ResourceLoader::OnReadCompleted"); | 434 "ResourceLoader::OnReadCompleted"); |
| 360 DCHECK_EQ(request_.get(), unused); | 435 DCHECK_EQ(request_.get(), unused); |
| 361 DVLOG(1) << "OnReadCompleted: \"" << request_->url().spec() << "\"" | 436 DVLOG(1) << "OnReadCompleted: \"" << request_->url().spec() << "\"" |
| 362 << " bytes_read = " << bytes_read; | 437 << " bytes_read = " << bytes_read; |
| 363 | 438 |
| 364 // bytes_read == -1 always implies an error. | 439 // bytes_read == -1 always implies an error. |
| 365 if (bytes_read == -1 || !request_->status().is_success()) { | 440 if (bytes_read == -1 || !request_->status().is_success()) { |
| 366 ResponseCompleted(); | 441 ResponseCompleted(); |
| 367 return; | 442 return; |
| 368 } | 443 } |
| 369 | 444 |
| 370 CompleteRead(bytes_read); | 445 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 } | 446 } |
| 391 | 447 |
| 392 void ResourceLoader::CancelSSLRequest(int error, | 448 void ResourceLoader::CancelSSLRequest(int error, |
| 393 const net::SSLInfo* ssl_info) { | 449 const net::SSLInfo* ssl_info) { |
| 394 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 450 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 395 | 451 |
| 396 // The request can be NULL if it was cancelled by the renderer (as the | 452 // 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). | 453 // request of the user navigating to a new page from the location bar). |
| 398 if (!request_->is_pending()) | 454 if (!request_->is_pending()) |
| 399 return; | 455 return; |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 425 net::FetchClientCertPrivateKey(cert); | 481 net::FetchClientCertPrivateKey(cert); |
| 426 request_->ContinueWithCertificate(cert, private_key.get()); | 482 request_->ContinueWithCertificate(cert, private_key.get()); |
| 427 } | 483 } |
| 428 | 484 |
| 429 void ResourceLoader::CancelCertificateSelection() { | 485 void ResourceLoader::CancelCertificateSelection() { |
| 430 DCHECK(ssl_client_auth_handler_); | 486 DCHECK(ssl_client_auth_handler_); |
| 431 ssl_client_auth_handler_.reset(); | 487 ssl_client_auth_handler_.reset(); |
| 432 request_->CancelWithError(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED); | 488 request_->CancelWithError(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED); |
| 433 } | 489 } |
| 434 | 490 |
| 435 void ResourceLoader::Resume() { | 491 void ResourceLoader::Resume(bool called_from_resource_controller) { |
| 436 DCHECK(!is_transferring_); | 492 DCHECK(!is_transferring_); |
| 437 | 493 |
| 438 DeferredStage stage = deferred_stage_; | 494 DeferredStage stage = deferred_stage_; |
| 439 deferred_stage_ = DEFERRED_NONE; | 495 deferred_stage_ = DEFERRED_NONE; |
| 440 switch (stage) { | 496 switch (stage) { |
| 441 case DEFERRED_NONE: | 497 case DEFERRED_NONE: |
| 442 NOTREACHED(); | 498 NOTREACHED(); |
| 443 break; | 499 break; |
| 500 case DEFERRED_SYNC: | |
| 501 DCHECK(called_from_resource_controller); | |
| 502 // Request will be resumed when the stack unwinds. | |
| 503 break; | |
| 444 case DEFERRED_START: | 504 case DEFERRED_START: |
| 505 // URLRequest::Start completes asynchronously, so starting the request now | |
| 506 // won't result in synchronously calling into a ResourceHandler, if this | |
| 507 // was called from Resume(). | |
| 445 StartRequestInternal(); | 508 StartRequestInternal(); |
| 446 break; | 509 break; |
| 447 case DEFERRED_REDIRECT: | 510 case DEFERRED_REDIRECT: |
| 511 // URLRequest::Start completes asynchronously, so starting the request now | |
| 512 // won't result in synchronously calling into a ResourceHandler, if this | |
| 513 // was called from Resume(). | |
| 448 FollowDeferredRedirectInternal(); | 514 FollowDeferredRedirectInternal(); |
| 449 break; | 515 break; |
| 450 case DEFERRED_READ: | 516 case DEFERRED_READ: |
| 451 base::ThreadTaskRunnerHandle::Get()->PostTask( | 517 if (called_from_resource_controller) { |
| 452 FROM_HERE, base::Bind(&ResourceLoader::ResumeReading, | 518 // TODO(mmenke): Call ReadMore instead? Strange that this is the only |
| 453 weak_ptr_factory_.GetWeakPtr())); | 519 // path which calls different methods, depending on the path. |
| 520 base::ThreadTaskRunnerHandle::Get()->PostTask( | |
| 521 FROM_HERE, base::Bind(&ResourceLoader::ResumeReading, | |
| 522 weak_ptr_factory_.GetWeakPtr())); | |
| 523 } else { | |
| 524 // If this was called as a result of a handler succeeding synchronously, | |
| 525 // force the result of the next read to be handled asynchronously, to | |
| 526 // avoid blocking the IO thread. | |
| 527 ReadMore(true /* handle_result_asynchronously */); | |
| 528 } | |
| 454 break; | 529 break; |
| 455 case DEFERRED_RESPONSE_COMPLETE: | 530 case DEFERRED_RESPONSE_COMPLETE: |
| 456 base::ThreadTaskRunnerHandle::Get()->PostTask( | 531 if (called_from_resource_controller) { |
| 457 FROM_HERE, base::Bind(&ResourceLoader::ResponseCompleted, | 532 base::ThreadTaskRunnerHandle::Get()->PostTask( |
| 458 weak_ptr_factory_.GetWeakPtr())); | 533 FROM_HERE, base::Bind(&ResourceLoader::ResponseCompleted, |
| 534 weak_ptr_factory_.GetWeakPtr())); | |
| 535 } else { | |
| 536 ResponseCompleted(); | |
| 537 } | |
| 459 break; | 538 break; |
| 460 case DEFERRED_FINISH: | 539 case DEFERRED_FINISH: |
| 461 // Delay self-destruction since we don't know how we were reached. | 540 if (called_from_resource_controller) { |
| 462 base::ThreadTaskRunnerHandle::Get()->PostTask( | 541 // Delay self-destruction since we don't know how we were reached. |
| 463 FROM_HERE, base::Bind(&ResourceLoader::CallDidFinishLoading, | 542 base::ThreadTaskRunnerHandle::Get()->PostTask( |
| 464 weak_ptr_factory_.GetWeakPtr())); | 543 FROM_HERE, base::Bind(&ResourceLoader::CallDidFinishLoading, |
| 544 weak_ptr_factory_.GetWeakPtr())); | |
| 545 } else { | |
| 546 CallDidFinishLoading(); | |
| 547 } | |
| 465 break; | 548 break; |
| 466 } | 549 } |
| 467 } | 550 } |
| 468 | 551 |
| 469 void ResourceLoader::Cancel() { | 552 void ResourceLoader::Cancel() { |
| 470 CancelRequest(false); | 553 CancelRequest(false); |
| 471 } | 554 } |
| 472 | 555 |
| 473 void ResourceLoader::StartRequestInternal() { | 556 void ResourceLoader::StartRequestInternal() { |
| 474 DCHECK(!request_->is_pending()); | 557 DCHECK(!request_->is_pending()); |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 551 ResourceRequestInfoImpl* info = GetRequestInfo(); | 634 ResourceRequestInfoImpl* info = GetRequestInfo(); |
| 552 scoped_refptr<ResourceResponse> response = new ResourceResponse(); | 635 scoped_refptr<ResourceResponse> response = new ResourceResponse(); |
| 553 PopulateResourceResponse(info, request_.get(), response.get()); | 636 PopulateResourceResponse(info, request_.get(), response.get()); |
| 554 | 637 |
| 555 delegate_->DidReceiveResponse(this); | 638 delegate_->DidReceiveResponse(this); |
| 556 | 639 |
| 557 // TODO(darin): Remove ScopedTracker below once crbug.com/475761 is fixed. | 640 // TODO(darin): Remove ScopedTracker below once crbug.com/475761 is fixed. |
| 558 tracked_objects::ScopedTracker tracking_profile( | 641 tracked_objects::ScopedTracker tracking_profile( |
| 559 FROM_HERE_WITH_EXPLICIT_FUNCTION("475761 OnResponseStarted()")); | 642 FROM_HERE_WITH_EXPLICIT_FUNCTION("475761 OnResponseStarted()")); |
| 560 | 643 |
| 561 bool defer = false; | 644 read_deferral_start_time_ = base::TimeTicks::Now(); |
| 562 if (!handler_->OnResponseStarted(response.get(), &defer)) { | 645 ScopedDeferral scoped_deferral(this, DEFERRED_READ); |
| 563 Cancel(); | 646 handler_->OnResponseStarted(response.get(), |
| 564 } else if (defer) { | 647 base::MakeUnique<Controller>(this)); |
| 565 read_deferral_start_time_ = base::TimeTicks::Now(); | |
| 566 deferred_stage_ = DEFERRED_READ; // Read first chunk when resumed. | |
| 567 } | |
| 568 } | 648 } |
| 569 | 649 |
| 570 void ResourceLoader::ReadMore(bool is_continuation) { | 650 void ResourceLoader::ReadMore(bool handle_result_asyncronously) { |
|
Charlie Harrison
2017/01/27 23:15:27
nit: s/asyncronously/asynchronously and ditto belo
mmenke
2017/01/28 04:49:35
Think I'll go with async. :)
| |
| 571 TRACE_EVENT_WITH_FLOW0("loading", "ResourceLoader::ReadMore", this, | 651 TRACE_EVENT_WITH_FLOW0("loading", "ResourceLoader::ReadMore", this, |
| 572 TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT); | 652 TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT); |
| 573 DCHECK(!is_deferred()); | 653 DCHECK(!is_deferred()); |
| 574 | 654 |
| 575 // Make sure we track the buffer in at least one place. This ensures it gets | 655 // 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 | 656 // deleted even in the case the request has already finished its job and |
| 577 // doesn't use the buffer. | 657 // doesn't use the buffer. |
| 578 scoped_refptr<net::IOBuffer> buf; | 658 scoped_refptr<net::IOBuffer> buf; |
| 579 int buf_size; | 659 int buf_size; |
| 580 { | 660 { |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 591 } | 671 } |
| 592 | 672 |
| 593 DCHECK(buf.get()); | 673 DCHECK(buf.get()); |
| 594 DCHECK(buf_size > 0); | 674 DCHECK(buf_size > 0); |
| 595 | 675 |
| 596 int result = request_->Read(buf.get(), buf_size); | 676 int result = request_->Read(buf.get(), buf_size); |
| 597 | 677 |
| 598 if (result == net::ERR_IO_PENDING) | 678 if (result == net::ERR_IO_PENDING) |
| 599 return; | 679 return; |
| 600 | 680 |
| 601 if (!is_continuation || result <= 0) { | 681 if (!handle_result_asyncronously || result <= 0) { |
| 602 OnReadCompleted(request_.get(), result); | 682 OnReadCompleted(request_.get(), result); |
| 603 } else { | 683 } else { |
| 604 // Else, trigger OnReadCompleted asynchronously to avoid starving the IO | 684 // Else, trigger OnReadCompleted asynchronously to avoid starving the IO |
| 605 // thread in case the URLRequest can provide data synchronously. | 685 // thread in case the URLRequest can provide data synchronously. |
| 606 base::ThreadTaskRunnerHandle::Get()->PostTask( | 686 base::ThreadTaskRunnerHandle::Get()->PostTask( |
| 607 FROM_HERE, | 687 FROM_HERE, |
| 608 base::Bind(&ResourceLoader::OnReadCompleted, | 688 base::Bind(&ResourceLoader::OnReadCompleted, |
| 609 weak_ptr_factory_.GetWeakPtr(), request_.get(), result)); | 689 weak_ptr_factory_.GetWeakPtr(), request_.get(), result)); |
| 610 } | 690 } |
| 611 } | 691 } |
| 612 | 692 |
| 613 void ResourceLoader::ResumeReading() { | 693 void ResourceLoader::ResumeReading() { |
| 614 DCHECK(!is_deferred()); | 694 DCHECK(!is_deferred()); |
| 615 | 695 |
| 616 if (!read_deferral_start_time_.is_null()) { | 696 if (!read_deferral_start_time_.is_null()) { |
| 617 UMA_HISTOGRAM_TIMES("Net.ResourceLoader.ReadDeferral", | 697 UMA_HISTOGRAM_TIMES("Net.ResourceLoader.ReadDeferral", |
| 618 base::TimeTicks::Now() - read_deferral_start_time_); | 698 base::TimeTicks::Now() - read_deferral_start_time_); |
| 619 read_deferral_start_time_ = base::TimeTicks(); | 699 read_deferral_start_time_ = base::TimeTicks(); |
| 620 } | 700 } |
| 621 if (request_->status().is_success()) { | 701 if (request_->status().is_success()) { |
| 622 ReadMore(false); // Read the next chunk (OK to complete synchronously). | 702 ReadMore(false /* handle_result_asynchronously */); |
| 623 } else { | 703 } else { |
| 624 ResponseCompleted(); | 704 ResponseCompleted(); |
| 625 } | 705 } |
| 626 } | 706 } |
| 627 | 707 |
| 628 void ResourceLoader::CompleteRead(int bytes_read) { | 708 void ResourceLoader::CompleteRead(int bytes_read) { |
| 629 TRACE_EVENT_WITH_FLOW0("loading", "ResourceLoader::CompleteRead", this, | 709 TRACE_EVENT_WITH_FLOW0("loading", "ResourceLoader::CompleteRead", this, |
| 630 TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT); | 710 TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT); |
| 631 | 711 |
| 632 DCHECK(bytes_read >= 0); | 712 DCHECK(bytes_read >= 0); |
| 633 DCHECK(request_->status().is_success()); | 713 DCHECK(request_->status().is_success()); |
| 634 | 714 |
| 635 // TODO(darin): Remove ScopedTracker below once crbug.com/475761 is fixed. | 715 // TODO(darin): Remove ScopedTracker below once crbug.com/475761 is fixed. |
| 636 tracked_objects::ScopedTracker tracking_profile( | 716 tracked_objects::ScopedTracker tracking_profile( |
| 637 FROM_HERE_WITH_EXPLICIT_FUNCTION("475761 OnReadCompleted()")); | 717 FROM_HERE_WITH_EXPLICIT_FUNCTION("475761 OnReadCompleted()")); |
| 638 | 718 |
| 639 bool defer = false; | 719 ScopedDeferral scoped_deferral( |
| 640 if (!handler_->OnReadCompleted(bytes_read, &defer)) { | 720 this, bytes_read > 0 ? DEFERRED_READ : DEFERRED_RESPONSE_COMPLETE); |
| 641 Cancel(); | 721 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 } | 722 } |
| 652 | 723 |
| 653 void ResourceLoader::ResponseCompleted() { | 724 void ResourceLoader::ResponseCompleted() { |
| 654 TRACE_EVENT_WITH_FLOW0("loading", "ResourceLoader::ResponseCompleted", this, | 725 TRACE_EVENT_WITH_FLOW0("loading", "ResourceLoader::ResponseCompleted", this, |
| 655 TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT); | 726 TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT); |
| 656 | 727 |
| 657 DVLOG(1) << "ResponseCompleted: " << request_->url().spec(); | 728 DVLOG(1) << "ResponseCompleted: " << request_->url().spec(); |
| 658 RecordHistograms(); | 729 RecordHistograms(); |
| 659 | 730 |
| 660 bool defer = false; | 731 // TODO(darin): Remove ScopedTracker below once crbug.com/475761 is fixed. |
| 661 { | 732 tracked_objects::ScopedTracker tracking_profile( |
| 662 // TODO(darin): Remove ScopedTracker below once crbug.com/475761 is fixed. | 733 FROM_HERE_WITH_EXPLICIT_FUNCTION("475761 OnResponseCompleted()")); |
| 663 tracked_objects::ScopedTracker tracking_profile( | |
| 664 FROM_HERE_WITH_EXPLICIT_FUNCTION("475761 OnResponseCompleted()")); | |
| 665 | 734 |
| 666 handler_->OnResponseCompleted(request_->status(), &defer); | 735 ScopedDeferral scoped_deferral(this, DEFERRED_FINISH); |
| 667 } | 736 handler_->OnResponseCompleted(request_->status(), |
| 668 if (defer) { | 737 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 } | 738 } |
| 677 | 739 |
| 678 void ResourceLoader::CallDidFinishLoading() { | 740 void ResourceLoader::CallDidFinishLoading() { |
| 679 TRACE_EVENT_WITH_FLOW0("loading", "ResourceLoader::CallDidFinishLoading", | 741 TRACE_EVENT_WITH_FLOW0("loading", "ResourceLoader::CallDidFinishLoading", |
| 680 this, TRACE_EVENT_FLAG_FLOW_IN); | 742 this, TRACE_EVENT_FLAG_FLOW_IN); |
| 681 delegate_->DidFinishLoading(this); | 743 delegate_->DidFinishLoading(this); |
| 682 } | 744 } |
| 683 | 745 |
| 684 void ResourceLoader::RecordHistograms() { | 746 void ResourceLoader::RecordHistograms() { |
| 685 ResourceRequestInfoImpl* info = GetRequestInfo(); | 747 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, | 802 UMA_HISTOGRAM_ENUMERATION("Net.Prefetch.Pattern", prefetch_status, |
| 741 STATUS_MAX); | 803 STATUS_MAX); |
| 742 } | 804 } |
| 743 } else if (request_->response_info().unused_since_prefetch) { | 805 } else if (request_->response_info().unused_since_prefetch) { |
| 744 TimeDelta total_time = base::TimeTicks::Now() - request_->creation_time(); | 806 TimeDelta total_time = base::TimeTicks::Now() - request_->creation_time(); |
| 745 UMA_HISTOGRAM_TIMES("Net.Prefetch.TimeSpentOnPrefetchHit", total_time); | 807 UMA_HISTOGRAM_TIMES("Net.Prefetch.TimeSpentOnPrefetchHit", total_time); |
| 746 } | 808 } |
| 747 } | 809 } |
| 748 | 810 |
| 749 } // namespace content | 811 } // namespace content |
| OLD | NEW |