| 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/renderer_host/resource_loader.h" | 5 #include "content/browser/renderer_host/resource_loader.h" |
| 6 | 6 |
| 7 #include "base/message_loop.h" | 7 #include "base/message_loop.h" |
| 8 #include "base/time.h" | 8 #include "base/time.h" |
| 9 #include "content/browser/child_process_security_policy_impl.h" | 9 #include "content/browser/child_process_security_policy_impl.h" |
| 10 #include "content/browser/renderer_host/doomed_resource_handler.h" | 10 #include "content/browser/renderer_host/doomed_resource_handler.h" |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 52 | 52 |
| 53 ResourceLoader::ResourceLoader(scoped_ptr<net::URLRequest> request, | 53 ResourceLoader::ResourceLoader(scoped_ptr<net::URLRequest> request, |
| 54 scoped_ptr<ResourceHandler> handler, | 54 scoped_ptr<ResourceHandler> handler, |
| 55 ResourceLoaderDelegate* delegate) | 55 ResourceLoaderDelegate* delegate) |
| 56 : deferred_stage_(DEFERRED_NONE), | 56 : deferred_stage_(DEFERRED_NONE), |
| 57 request_(request.Pass()), | 57 request_(request.Pass()), |
| 58 handler_(handler.Pass()), | 58 handler_(handler.Pass()), |
| 59 delegate_(delegate), | 59 delegate_(delegate), |
| 60 last_upload_position_(0), | 60 last_upload_position_(0), |
| 61 waiting_for_upload_progress_ack_(false), | 61 waiting_for_upload_progress_ack_(false), |
| 62 called_on_response_started_(false), | |
| 63 has_started_reading_(false), | |
| 64 is_paused_(false), | |
| 65 pause_count_(0), | |
| 66 paused_read_bytes_(0), | |
| 67 is_transferring_(false) { | 62 is_transferring_(false) { |
| 68 request_->set_delegate(this); | 63 request_->set_delegate(this); |
| 69 handler_->SetController(this); | 64 handler_->SetController(this); |
| 70 } | 65 } |
| 71 | 66 |
| 72 ResourceLoader::~ResourceLoader() { | 67 ResourceLoader::~ResourceLoader() { |
| 73 if (login_delegate_) | 68 if (login_delegate_) |
| 74 login_delegate_->OnRequestCancelled(); | 69 login_delegate_->OnRequestCancelled(); |
| 75 if (ssl_client_auth_handler_) | 70 if (ssl_client_auth_handler_) |
| 76 ssl_client_auth_handler_->OnRequestCancelled(); | 71 ssl_client_auth_handler_->OnRequestCancelled(); |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 206 CancelRequestInternal(net::ERR_UNKNOWN_URL_SCHEME, false); | 201 CancelRequestInternal(net::ERR_UNKNOWN_URL_SCHEME, false); |
| 207 return; | 202 return; |
| 208 } | 203 } |
| 209 | 204 |
| 210 scoped_refptr<ResourceResponse> response(new ResourceResponse()); | 205 scoped_refptr<ResourceResponse> response(new ResourceResponse()); |
| 211 PopulateResourceResponse(request_.get(), response); | 206 PopulateResourceResponse(request_.get(), response); |
| 212 | 207 |
| 213 if (!handler_->OnRequestRedirected(info->GetRequestID(), new_url, response, | 208 if (!handler_->OnRequestRedirected(info->GetRequestID(), new_url, response, |
| 214 defer)) { | 209 defer)) { |
| 215 Cancel(); | 210 Cancel(); |
| 211 } else if (*defer) { |
| 212 deferred_stage_ = DEFERRED_REDIRECT; // Follow redirect when resumed. |
| 216 } | 213 } |
| 217 | |
| 218 if (*defer) | |
| 219 deferred_stage_ = DEFERRED_REDIRECT; | |
| 220 } | 214 } |
| 221 | 215 |
| 222 void ResourceLoader::OnAuthRequired(net::URLRequest* unused, | 216 void ResourceLoader::OnAuthRequired(net::URLRequest* unused, |
| 223 net::AuthChallengeInfo* auth_info) { | 217 net::AuthChallengeInfo* auth_info) { |
| 224 DCHECK_EQ(request_.get(), unused); | 218 DCHECK_EQ(request_.get(), unused); |
| 225 | 219 |
| 226 if (request_->load_flags() & net::LOAD_DO_NOT_PROMPT_FOR_LOGIN) { | 220 if (request_->load_flags() & net::LOAD_DO_NOT_PROMPT_FOR_LOGIN) { |
| 227 request_->CancelAuth(); | 221 request_->CancelAuth(); |
| 228 return; | 222 return; |
| 229 } | 223 } |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 285 render_view_id, | 279 render_view_id, |
| 286 ssl_info, | 280 ssl_info, |
| 287 fatal); | 281 fatal); |
| 288 } | 282 } |
| 289 | 283 |
| 290 void ResourceLoader::OnResponseStarted(net::URLRequest* unused) { | 284 void ResourceLoader::OnResponseStarted(net::URLRequest* unused) { |
| 291 DCHECK_EQ(request_.get(), unused); | 285 DCHECK_EQ(request_.get(), unused); |
| 292 | 286 |
| 293 VLOG(1) << "OnResponseStarted: " << request_->url().spec(); | 287 VLOG(1) << "OnResponseStarted: " << request_->url().spec(); |
| 294 | 288 |
| 289 if (!request_->status().is_success()) { |
| 290 ResponseCompleted(); |
| 291 return; |
| 292 } |
| 293 |
| 294 // We want to send a final upload progress message prior to sending the |
| 295 // response complete message even if we're waiting for an ack to to a |
| 296 // previous upload progress message. |
| 297 waiting_for_upload_progress_ack_ = false; |
| 298 ReportUploadProgress(); |
| 299 |
| 300 CompleteResponseStarted(); |
| 301 |
| 302 if (is_deferred()) |
| 303 return; |
| 304 |
| 295 if (request_->status().is_success()) { | 305 if (request_->status().is_success()) { |
| 296 if (PauseRequestIfNeeded()) { | 306 StartReading(false); // Read the first chunk. |
| 297 VLOG(1) << "OnResponseStarted pausing: " << request_->url().spec(); | |
| 298 return; | |
| 299 } | |
| 300 | |
| 301 // We want to send a final upload progress message prior to sending the | |
| 302 // response complete message even if we're waiting for an ack to to a | |
| 303 // previous upload progress message. | |
| 304 waiting_for_upload_progress_ack_ = false; | |
| 305 ReportUploadProgress(); | |
| 306 | |
| 307 if (!CompleteResponseStarted()) { | |
| 308 Cancel(); | |
| 309 } else { | |
| 310 // Check if the handler paused the request in their OnResponseStarted. | |
| 311 if (PauseRequestIfNeeded()) { | |
| 312 VLOG(1) << "OnResponseStarted pausing2: " << request_->url().spec(); | |
| 313 return; | |
| 314 } | |
| 315 | |
| 316 StartReading(); | |
| 317 } | |
| 318 } else { | 307 } else { |
| 319 ResponseCompleted(); | 308 ResponseCompleted(); |
| 320 } | 309 } |
| 321 } | 310 } |
| 322 | 311 |
| 323 void ResourceLoader::OnReadCompleted(net::URLRequest* unused, int bytes_read) { | 312 void ResourceLoader::OnReadCompleted(net::URLRequest* unused, int bytes_read) { |
| 324 DCHECK_EQ(request_.get(), unused); | 313 DCHECK_EQ(request_.get(), unused); |
| 325 VLOG(1) << "OnReadCompleted: \"" << request_->url().spec() << "\"" | 314 VLOG(1) << "OnReadCompleted: \"" << request_->url().spec() << "\"" |
| 326 << " bytes_read = " << bytes_read; | 315 << " bytes_read = " << bytes_read; |
| 327 | 316 |
| 328 // bytes_read == -1 always implies an error, so we want to skip the pause | 317 // bytes_read == -1 always implies an error. |
| 329 // checks and just call ResponseCompleted. | 318 if (bytes_read == -1 || !request_->status().is_success()) { |
| 330 if (bytes_read == -1) { | |
| 331 DCHECK(!request_->status().is_success()); | |
| 332 | |
| 333 ResponseCompleted(); | 319 ResponseCompleted(); |
| 334 return; | 320 return; |
| 335 } | 321 } |
| 336 | 322 |
| 337 // OnReadCompleted can be called without Read (e.g., for chrome:// URLs). | 323 CompleteRead(bytes_read); |
| 338 // Make sure we know that a read has begun. | |
| 339 has_started_reading_ = true; | |
| 340 | 324 |
| 341 if (PauseRequestIfNeeded()) { | 325 if (is_deferred()) |
| 342 paused_read_bytes_ = bytes_read; | |
| 343 VLOG(1) << "OnReadCompleted pausing: \"" << request_->url().spec() << "\"" | |
| 344 << " bytes_read = " << bytes_read; | |
| 345 return; | 326 return; |
| 327 |
| 328 if (request_->status().is_success() && bytes_read > 0) { |
| 329 StartReading(true); // Read the next chunk. |
| 330 } else { |
| 331 ResponseCompleted(); |
| 346 } | 332 } |
| 347 | |
| 348 if (request_->status().is_success() && CompleteRead(&bytes_read)) { | |
| 349 // The request can be paused if we realize that the renderer is not | |
| 350 // servicing messages fast enough. | |
| 351 if (pause_count_ == 0 && ReadMore(&bytes_read) && | |
| 352 request_->status().is_success()) { | |
| 353 if (bytes_read == 0) { | |
| 354 CompleteRead(&bytes_read); | |
| 355 } else { | |
| 356 // Force the next CompleteRead / Read pair to run as a separate task. | |
| 357 // This avoids a fast, large network request from monopolizing the IO | |
| 358 // thread and starving other IO operations from running. | |
| 359 VLOG(1) << "OnReadCompleted postponing: \"" | |
| 360 << request_->url().spec() << "\"" | |
| 361 << " bytes_read = " << bytes_read; | |
| 362 | |
| 363 paused_read_bytes_ = bytes_read; | |
| 364 is_paused_ = true; | |
| 365 | |
| 366 MessageLoop::current()->PostTask( | |
| 367 FROM_HERE, base::Bind(&ResourceLoader::ResumeRequest, AsWeakPtr())); | |
| 368 return; | |
| 369 } | |
| 370 } | |
| 371 } | |
| 372 | |
| 373 if (PauseRequestIfNeeded()) { | |
| 374 paused_read_bytes_ = bytes_read; | |
| 375 VLOG(1) << "OnReadCompleted (CompleteRead) pausing: \"" | |
| 376 << request_->url().spec() << "\"" | |
| 377 << " bytes_read = " << bytes_read; | |
| 378 return; | |
| 379 } | |
| 380 | |
| 381 // If the status is not IO pending then we've either finished (success) or we | |
| 382 // had an error. Either way, we're done! | |
| 383 if (!request_->status().is_io_pending()) | |
| 384 ResponseCompleted(); | |
| 385 } | 333 } |
| 386 | 334 |
| 387 void ResourceLoader::CancelSSLRequest(const GlobalRequestID& id, | 335 void ResourceLoader::CancelSSLRequest(const GlobalRequestID& id, |
| 388 int error, | 336 int error, |
| 389 const net::SSLInfo* ssl_info) { | 337 const net::SSLInfo* ssl_info) { |
| 390 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 338 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 391 | 339 |
| 392 // The request can be NULL if it was cancelled by the renderer (as the | 340 // The request can be NULL if it was cancelled by the renderer (as the |
| 393 // request of the user navigating to a new page from the location bar). | 341 // request of the user navigating to a new page from the location bar). |
| 394 if (!request_->is_pending()) | 342 if (!request_->is_pending()) |
| (...skipping 23 matching lines...) Expand all Loading... |
| 418 switch (stage) { | 366 switch (stage) { |
| 419 case DEFERRED_NONE: | 367 case DEFERRED_NONE: |
| 420 NOTREACHED(); | 368 NOTREACHED(); |
| 421 break; | 369 break; |
| 422 case DEFERRED_START: | 370 case DEFERRED_START: |
| 423 StartRequestInternal(); | 371 StartRequestInternal(); |
| 424 break; | 372 break; |
| 425 case DEFERRED_REDIRECT: | 373 case DEFERRED_REDIRECT: |
| 426 request_->FollowDeferredRedirect(); | 374 request_->FollowDeferredRedirect(); |
| 427 break; | 375 break; |
| 428 case DEFERRED_RESPONSE: | |
| 429 case DEFERRED_READ: | 376 case DEFERRED_READ: |
| 430 PauseRequest(false); | 377 MessageLoop::current()->PostTask( |
| 378 FROM_HERE, |
| 379 base::Bind(&ResourceLoader::ResumeReading, AsWeakPtr())); |
| 431 break; | 380 break; |
| 432 case DEFERRED_FINISH: | 381 case DEFERRED_FINISH: |
| 433 // Delay self-destruction since we don't know how we were reached. | 382 // Delay self-destruction since we don't know how we were reached. |
| 434 MessageLoop::current()->PostTask( | 383 MessageLoop::current()->PostTask( |
| 435 FROM_HERE, | 384 FROM_HERE, |
| 436 base::Bind(&ResourceLoader::CallDidFinishLoading, AsWeakPtr())); | 385 base::Bind(&ResourceLoader::CallDidFinishLoading, AsWeakPtr())); |
| 437 break; | 386 break; |
| 438 } | 387 } |
| 439 } | 388 } |
| 440 | 389 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 453 VLOG(1) << "CancelRequestInternal: " << request_->url().spec(); | 402 VLOG(1) << "CancelRequestInternal: " << request_->url().spec(); |
| 454 | 403 |
| 455 ResourceRequestInfoImpl* info = GetRequestInfo(); | 404 ResourceRequestInfoImpl* info = GetRequestInfo(); |
| 456 | 405 |
| 457 // WebKit will send us a cancel for downloads since it no longer handles | 406 // WebKit will send us a cancel for downloads since it no longer handles |
| 458 // them. In this case, ignore the cancel since we handle downloads in the | 407 // them. In this case, ignore the cancel since we handle downloads in the |
| 459 // browser. | 408 // browser. |
| 460 if (from_renderer && info->is_download()) | 409 if (from_renderer && info->is_download()) |
| 461 return; | 410 return; |
| 462 | 411 |
| 412 // TODO(darin): Perhaps we should really be looking to see if the status is |
| 413 // IO_PENDING? |
| 463 bool was_pending = request_->is_pending(); | 414 bool was_pending = request_->is_pending(); |
| 464 | 415 |
| 465 if (login_delegate_) { | 416 if (login_delegate_) { |
| 466 login_delegate_->OnRequestCancelled(); | 417 login_delegate_->OnRequestCancelled(); |
| 467 login_delegate_ = NULL; | 418 login_delegate_ = NULL; |
| 468 } | 419 } |
| 469 if (ssl_client_auth_handler_) { | 420 if (ssl_client_auth_handler_) { |
| 470 ssl_client_auth_handler_->OnRequestCancelled(); | 421 ssl_client_auth_handler_->OnRequestCancelled(); |
| 471 ssl_client_auth_handler_ = NULL; | 422 ssl_client_auth_handler_ = NULL; |
| 472 } | 423 } |
| 473 | 424 |
| 474 request_->CancelWithError(error); | 425 request_->CancelWithError(error); |
| 475 | 426 |
| 476 if (!was_pending) { | 427 if (!was_pending) { |
| 477 // If the request isn't in flight, then we won't get an asynchronous | 428 // If the request isn't in flight, then we won't get an asynchronous |
| 478 // notification from the request, so we have to signal ourselves to finish | 429 // notification from the request, so we have to signal ourselves to finish |
| 479 // this request. | 430 // this request. |
| 480 MessageLoop::current()->PostTask( | 431 MessageLoop::current()->PostTask( |
| 481 FROM_HERE, base::Bind(&ResourceLoader::ResponseCompleted, AsWeakPtr())); | 432 FROM_HERE, base::Bind(&ResourceLoader::ResponseCompleted, AsWeakPtr())); |
| 482 } | 433 } |
| 483 } | 434 } |
| 484 | 435 |
| 485 bool ResourceLoader::CompleteResponseStarted() { | 436 void ResourceLoader::CompleteResponseStarted() { |
| 486 ResourceRequestInfoImpl* info = GetRequestInfo(); | 437 ResourceRequestInfoImpl* info = GetRequestInfo(); |
| 487 | 438 |
| 488 scoped_refptr<ResourceResponse> response(new ResourceResponse()); | 439 scoped_refptr<ResourceResponse> response(new ResourceResponse()); |
| 489 PopulateResourceResponse(request_.get(), response); | 440 PopulateResourceResponse(request_.get(), response); |
| 490 | 441 |
| 491 if (request_->ssl_info().cert) { | 442 if (request_->ssl_info().cert) { |
| 492 int cert_id = | 443 int cert_id = |
| 493 CertStore::GetInstance()->StoreCert(request_->ssl_info().cert, | 444 CertStore::GetInstance()->StoreCert(request_->ssl_info().cert, |
| 494 info->GetChildID()); | 445 info->GetChildID()); |
| 495 response->head.security_info = SerializeSecurityInfo( | 446 response->head.security_info = SerializeSecurityInfo( |
| 496 cert_id, | 447 cert_id, |
| 497 request_->ssl_info().cert_status, | 448 request_->ssl_info().cert_status, |
| 498 request_->ssl_info().security_bits, | 449 request_->ssl_info().security_bits, |
| 499 request_->ssl_info().connection_status); | 450 request_->ssl_info().connection_status); |
| 500 } else { | 451 } else { |
| 501 // We should not have any SSL state. | 452 // We should not have any SSL state. |
| 502 DCHECK(!request_->ssl_info().cert_status && | 453 DCHECK(!request_->ssl_info().cert_status && |
| 503 request_->ssl_info().security_bits == -1 && | 454 request_->ssl_info().security_bits == -1 && |
| 504 !request_->ssl_info().connection_status); | 455 !request_->ssl_info().connection_status); |
| 505 } | 456 } |
| 506 | 457 |
| 507 delegate_->DidReceiveResponse(this); | 458 delegate_->DidReceiveResponse(this); |
| 508 called_on_response_started_ = true; | |
| 509 | 459 |
| 510 bool defer = false; | 460 bool defer = false; |
| 511 if (!handler_->OnResponseStarted(info->GetRequestID(), response, &defer)) | 461 if (!handler_->OnResponseStarted(info->GetRequestID(), response, &defer)) { |
| 512 return false; | 462 Cancel(); |
| 513 | 463 } else if (defer) { |
| 514 if (defer) { | 464 deferred_stage_ = DEFERRED_READ; // Read first chunk when resumed. |
| 515 deferred_stage_ = DEFERRED_RESPONSE; | |
| 516 PauseRequest(true); | |
| 517 } | 465 } |
| 518 | |
| 519 return true; | |
| 520 } | 466 } |
| 521 | 467 |
| 522 void ResourceLoader::StartReading() { | 468 void ResourceLoader::StartReading(bool is_continuation) { |
| 523 int bytes_read = 0; | 469 int bytes_read = 0; |
| 524 if (ReadMore(&bytes_read)) { | 470 ReadMore(&bytes_read); |
| 471 |
| 472 // If IO is pending, wait for the URLRequest to call OnReadCompleted. |
| 473 if (request_->status().is_io_pending()) |
| 474 return; |
| 475 |
| 476 if (!is_continuation || bytes_read <= 0) { |
| 525 OnReadCompleted(request_.get(), bytes_read); | 477 OnReadCompleted(request_.get(), bytes_read); |
| 526 } else if (!request_->status().is_io_pending()) { | 478 } else { |
| 527 DCHECK(!is_paused_); | 479 // Else, trigger OnReadCompleted asynchronously to avoid starving the IO |
| 528 // If the error is not an IO pending, then we're done reading. | 480 // thread in case the URLRequest can provide data synchronously. |
| 481 MessageLoop::current()->PostTask( |
| 482 FROM_HERE, |
| 483 base::Bind(&ResourceLoader::OnReadCompleted, AsWeakPtr(), |
| 484 request_.get(), bytes_read)); |
| 485 } |
| 486 } |
| 487 |
| 488 void ResourceLoader::ResumeReading() { |
| 489 DCHECK(!is_deferred()); |
| 490 |
| 491 if (request_->status().is_success()) { |
| 492 StartReading(false); // Read the next chunk (OK to complete synchronously). |
| 493 } else { |
| 529 ResponseCompleted(); | 494 ResponseCompleted(); |
| 530 } | 495 } |
| 531 } | 496 } |
| 532 | 497 |
| 533 bool ResourceLoader::ReadMore(int* bytes_read) { | 498 void ResourceLoader::ReadMore(int* bytes_read) { |
| 534 ResourceRequestInfoImpl* info = GetRequestInfo(); | 499 ResourceRequestInfoImpl* info = GetRequestInfo(); |
| 535 DCHECK(!is_paused_); | 500 DCHECK(!is_deferred()); |
| 536 | 501 |
| 537 net::IOBuffer* buf; | 502 net::IOBuffer* buf; |
| 538 int buf_size; | 503 int buf_size; |
| 539 if (!handler_->OnWillRead(info->GetRequestID(), &buf, &buf_size, -1)) | 504 if (!handler_->OnWillRead(info->GetRequestID(), &buf, &buf_size, -1)) { |
| 540 return false; | 505 Cancel(); |
| 506 return; |
| 507 } |
| 541 | 508 |
| 542 DCHECK(buf); | 509 DCHECK(buf); |
| 543 DCHECK(buf_size > 0); | 510 DCHECK(buf_size > 0); |
| 544 | 511 |
| 545 has_started_reading_ = true; | 512 request_->Read(buf, buf_size, bytes_read); |
| 546 return request_->Read(buf, buf_size, bytes_read); | 513 |
| 514 // No need to check the return value here as we'll detect errors by |
| 515 // inspecting the URLRequest's status. |
| 547 } | 516 } |
| 548 | 517 |
| 549 bool ResourceLoader::CompleteRead(int* bytes_read) { | 518 void ResourceLoader::CompleteRead(int bytes_read) { |
| 550 if (!request_.get() || !request_->status().is_success()) { | 519 DCHECK(bytes_read >= 0); |
| 551 NOTREACHED(); | 520 DCHECK(request_->status().is_success()); |
| 552 return false; | |
| 553 } | |
| 554 | 521 |
| 555 ResourceRequestInfoImpl* info = GetRequestInfo(); | 522 ResourceRequestInfoImpl* info = GetRequestInfo(); |
| 556 | 523 |
| 557 bool defer = false; | 524 bool defer = false; |
| 558 if (!handler_->OnReadCompleted(info->GetRequestID(), bytes_read, &defer)) { | 525 if (!handler_->OnReadCompleted(info->GetRequestID(), bytes_read, &defer)) { |
| 559 Cancel(); | 526 Cancel(); |
| 560 return false; | 527 } else if (defer) { |
| 528 deferred_stage_ = DEFERRED_READ; // Read next chunk when resumed. |
| 561 } | 529 } |
| 562 | |
| 563 if (defer) { | |
| 564 deferred_stage_ = DEFERRED_READ; | |
| 565 PauseRequest(true); | |
| 566 } | |
| 567 | |
| 568 return *bytes_read != 0; | |
| 569 } | 530 } |
| 570 | 531 |
| 571 void ResourceLoader::ResponseCompleted() { | 532 void ResourceLoader::ResponseCompleted() { |
| 572 VLOG(1) << "ResponseCompleted: " << request_->url().spec(); | 533 VLOG(1) << "ResponseCompleted: " << request_->url().spec(); |
| 573 ResourceRequestInfoImpl* info = GetRequestInfo(); | 534 ResourceRequestInfoImpl* info = GetRequestInfo(); |
| 574 | 535 |
| 575 std::string security_info; | 536 std::string security_info; |
| 576 const net::SSLInfo& ssl_info = request_->ssl_info(); | 537 const net::SSLInfo& ssl_info = request_->ssl_info(); |
| 577 if (ssl_info.cert != NULL) { | 538 if (ssl_info.cert != NULL) { |
| 578 int cert_id = CertStore::GetInstance()->StoreCert(ssl_info.cert, | 539 int cert_id = CertStore::GetInstance()->StoreCert(ssl_info.cert, |
| 579 info->GetChildID()); | 540 info->GetChildID()); |
| 580 security_info = SerializeSecurityInfo( | 541 security_info = SerializeSecurityInfo( |
| 581 cert_id, ssl_info.cert_status, ssl_info.security_bits, | 542 cert_id, ssl_info.cert_status, ssl_info.security_bits, |
| 582 ssl_info.connection_status); | 543 ssl_info.connection_status); |
| 583 } | 544 } |
| 584 | 545 |
| 585 if (handler_->OnResponseCompleted(info->GetRequestID(), request_->status(), | 546 if (handler_->OnResponseCompleted(info->GetRequestID(), request_->status(), |
| 586 security_info)) { | 547 security_info)) { |
| 587 // This will result in our destruction. | 548 // This will result in our destruction. |
| 588 CallDidFinishLoading(); | 549 CallDidFinishLoading(); |
| 589 } else { | 550 } else { |
| 590 // The handler is not ready to die yet. We will call DidFinishLoading when | 551 // The handler is not ready to die yet. We will call DidFinishLoading when |
| 591 // we resume. | 552 // we resume. |
| 592 deferred_stage_ = DEFERRED_FINISH; | 553 deferred_stage_ = DEFERRED_FINISH; |
| 593 } | 554 } |
| 594 } | 555 } |
| 595 | 556 |
| 596 bool ResourceLoader::PauseRequestIfNeeded() { | |
| 597 if (pause_count_ > 0) | |
| 598 is_paused_ = true; | |
| 599 return is_paused_; | |
| 600 } | |
| 601 | |
| 602 void ResourceLoader::PauseRequest(bool pause) { | |
| 603 int pause_count = pause_count_ + (pause ? 1 : -1); | |
| 604 if (pause_count < 0) { | |
| 605 NOTREACHED(); // Unbalanced call to pause. | |
| 606 return; | |
| 607 } | |
| 608 pause_count_ = pause_count; | |
| 609 | |
| 610 VLOG(1) << "To pause (" << pause << "): " << request_->url().spec(); | |
| 611 | |
| 612 // If we're resuming, kick the request to start reading again. Run the read | |
| 613 // asynchronously to avoid recursion problems. | |
| 614 if (pause_count_ == 0) { | |
| 615 MessageLoop::current()->PostTask( | |
| 616 FROM_HERE, base::Bind(&ResourceLoader::ResumeRequest, AsWeakPtr())); | |
| 617 } | |
| 618 } | |
| 619 | |
| 620 void ResourceLoader::ResumeRequest() { | |
| 621 // We may already be unpaused, or the pause count may have increased since we | |
| 622 // posted the task to call ResumeRequest. | |
| 623 if (!is_paused_) | |
| 624 return; | |
| 625 is_paused_ = false; | |
| 626 if (PauseRequestIfNeeded()) | |
| 627 return; | |
| 628 | |
| 629 VLOG(1) << "Resuming: \"" << request_->url().spec() << "\"" | |
| 630 << " paused_read_bytes = " << paused_read_bytes_ | |
| 631 << " called response started = " << called_on_response_started_ | |
| 632 << " started reading = " << has_started_reading_; | |
| 633 | |
| 634 if (called_on_response_started_) { | |
| 635 if (has_started_reading_) { | |
| 636 OnReadCompleted(request_.get(), paused_read_bytes_); | |
| 637 } else { | |
| 638 StartReading(); | |
| 639 } | |
| 640 } else { | |
| 641 OnResponseStarted(request_.get()); | |
| 642 } | |
| 643 } | |
| 644 | |
| 645 void ResourceLoader::CallDidFinishLoading() { | 557 void ResourceLoader::CallDidFinishLoading() { |
| 646 delegate_->DidFinishLoading(this); | 558 delegate_->DidFinishLoading(this); |
| 647 } | 559 } |
| 648 | 560 |
| 649 } // namespace content | 561 } // namespace content |
| OLD | NEW |