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 "base/command_line.h" | 7 #include "base/command_line.h" |
8 #include "base/message_loop.h" | 8 #include "base/message_loop.h" |
9 #include "base/time.h" | 9 #include "base/time.h" |
10 #include "content/browser/child_process_security_policy_impl.h" | 10 #include "content/browser/child_process_security_policy_impl.h" |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
63 ResourceLoaderDelegate* delegate) | 63 ResourceLoaderDelegate* delegate) |
64 : weak_ptr_factory_(this) { | 64 : weak_ptr_factory_(this) { |
65 scoped_ptr<net::ClientCertStore> client_cert_store; | 65 scoped_ptr<net::ClientCertStore> client_cert_store; |
66 #if !defined(USE_OPENSSL) | 66 #if !defined(USE_OPENSSL) |
67 client_cert_store.reset(new net::ClientCertStoreImpl()); | 67 client_cert_store.reset(new net::ClientCertStoreImpl()); |
68 #endif | 68 #endif |
69 Init(request.Pass(), handler.Pass(), delegate, client_cert_store.Pass()); | 69 Init(request.Pass(), handler.Pass(), delegate, client_cert_store.Pass()); |
70 } | 70 } |
71 | 71 |
72 ResourceLoader::~ResourceLoader() { | 72 ResourceLoader::~ResourceLoader() { |
73 if (login_delegate_) | 73 if (login_delegate_.get()) |
74 login_delegate_->OnRequestCancelled(); | 74 login_delegate_->OnRequestCancelled(); |
75 if (ssl_client_auth_handler_) | 75 if (ssl_client_auth_handler_.get()) |
76 ssl_client_auth_handler_->OnRequestCancelled(); | 76 ssl_client_auth_handler_->OnRequestCancelled(); |
77 | 77 |
78 // Run ResourceHandler destructor before we tear-down the rest of our state | 78 // Run ResourceHandler destructor before we tear-down the rest of our state |
79 // as the ResourceHandler may want to inspect the URLRequest and other state. | 79 // as the ResourceHandler may want to inspect the URLRequest and other state. |
80 handler_.reset(); | 80 handler_.reset(); |
81 } | 81 } |
82 | 82 |
83 void ResourceLoader::StartRequest() { | 83 void ResourceLoader::StartRequest() { |
84 if (delegate_->HandleExternalProtocol(this, request_->url())) { | 84 if (delegate_->HandleExternalProtocol(this, request_->url())) { |
85 CancelAndIgnore(); | 85 CancelAndIgnore(); |
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
243 | 243 |
244 delegate_->DidReceiveRedirect(this, new_url); | 244 delegate_->DidReceiveRedirect(this, new_url); |
245 | 245 |
246 if (delegate_->HandleExternalProtocol(this, new_url)) { | 246 if (delegate_->HandleExternalProtocol(this, new_url)) { |
247 // The request is complete so we can remove it. | 247 // The request is complete so we can remove it. |
248 CancelAndIgnore(); | 248 CancelAndIgnore(); |
249 return; | 249 return; |
250 } | 250 } |
251 | 251 |
252 scoped_refptr<ResourceResponse> response(new ResourceResponse()); | 252 scoped_refptr<ResourceResponse> response(new ResourceResponse()); |
253 PopulateResourceResponse(request_.get(), response); | 253 PopulateResourceResponse(request_.get(), response.get()); |
254 | 254 |
255 if (!handler_->OnRequestRedirected(info->GetRequestID(), new_url, response, | 255 if (!handler_->OnRequestRedirected( |
256 defer)) { | 256 info->GetRequestID(), new_url, response.get(), defer)) { |
257 Cancel(); | 257 Cancel(); |
258 } else if (*defer) { | 258 } else if (*defer) { |
259 deferred_stage_ = DEFERRED_REDIRECT; // Follow redirect when resumed. | 259 deferred_stage_ = DEFERRED_REDIRECT; // Follow redirect when resumed. |
260 } | 260 } |
261 } | 261 } |
262 | 262 |
263 void ResourceLoader::OnAuthRequired(net::URLRequest* unused, | 263 void ResourceLoader::OnAuthRequired(net::URLRequest* unused, |
264 net::AuthChallengeInfo* auth_info) { | 264 net::AuthChallengeInfo* auth_info) { |
265 DCHECK_EQ(request_.get(), unused); | 265 DCHECK_EQ(request_.get(), unused); |
266 | 266 |
267 if (request_->load_flags() & net::LOAD_DO_NOT_PROMPT_FOR_LOGIN) { | 267 if (request_->load_flags() & net::LOAD_DO_NOT_PROMPT_FOR_LOGIN) { |
268 request_->CancelAuth(); | 268 request_->CancelAuth(); |
269 return; | 269 return; |
270 } | 270 } |
271 | 271 |
272 if (!delegate_->AcceptAuthRequest(this, auth_info)) { | 272 if (!delegate_->AcceptAuthRequest(this, auth_info)) { |
273 request_->CancelAuth(); | 273 request_->CancelAuth(); |
274 return; | 274 return; |
275 } | 275 } |
276 | 276 |
277 // Create a login dialog on the UI thread to get authentication data, or pull | 277 // Create a login dialog on the UI thread to get authentication data, or pull |
278 // from cache and continue on the IO thread. | 278 // from cache and continue on the IO thread. |
279 | 279 |
280 DCHECK(!login_delegate_) << | 280 DCHECK(!login_delegate_.get()) |
281 "OnAuthRequired called with login_delegate pending"; | 281 << "OnAuthRequired called with login_delegate pending"; |
282 login_delegate_ = delegate_->CreateLoginDelegate(this, auth_info); | 282 login_delegate_ = delegate_->CreateLoginDelegate(this, auth_info); |
283 if (!login_delegate_) | 283 if (!login_delegate_.get()) |
284 request_->CancelAuth(); | 284 request_->CancelAuth(); |
285 } | 285 } |
286 | 286 |
287 void ResourceLoader::OnCertificateRequested( | 287 void ResourceLoader::OnCertificateRequested( |
288 net::URLRequest* unused, | 288 net::URLRequest* unused, |
289 net::SSLCertRequestInfo* cert_info) { | 289 net::SSLCertRequestInfo* cert_info) { |
290 DCHECK_EQ(request_.get(), unused); | 290 DCHECK_EQ(request_.get(), unused); |
291 | 291 |
292 if (!delegate_->AcceptSSLClientCertificateRequest(this, cert_info)) { | 292 if (!delegate_->AcceptSSLClientCertificateRequest(this, cert_info)) { |
293 request_->Cancel(); | 293 request_->Cancel(); |
294 return; | 294 return; |
295 } | 295 } |
296 | 296 |
297 #if !defined(USE_OPENSSL) | 297 #if !defined(USE_OPENSSL) |
298 client_cert_store_->GetClientCerts(*cert_info, &cert_info->client_certs); | 298 client_cert_store_->GetClientCerts(*cert_info, &cert_info->client_certs); |
299 if (cert_info->client_certs.empty()) { | 299 if (cert_info->client_certs.empty()) { |
300 // No need to query the user if there are no certs to choose from. | 300 // No need to query the user if there are no certs to choose from. |
301 request_->ContinueWithCertificate(NULL); | 301 request_->ContinueWithCertificate(NULL); |
302 return; | 302 return; |
303 } | 303 } |
304 #endif | 304 #endif |
305 | 305 |
306 DCHECK(!ssl_client_auth_handler_) << | 306 DCHECK(!ssl_client_auth_handler_.get()) |
307 "OnCertificateRequested called with ssl_client_auth_handler pending"; | 307 << "OnCertificateRequested called with ssl_client_auth_handler pending"; |
308 ssl_client_auth_handler_ = new SSLClientAuthHandler(request_.get(), | 308 ssl_client_auth_handler_ = new SSLClientAuthHandler(request_.get(), |
309 cert_info); | 309 cert_info); |
310 ssl_client_auth_handler_->SelectCertificate(); | 310 ssl_client_auth_handler_->SelectCertificate(); |
311 } | 311 } |
312 | 312 |
313 void ResourceLoader::OnSSLCertificateError(net::URLRequest* request, | 313 void ResourceLoader::OnSSLCertificateError(net::URLRequest* request, |
314 const net::SSLInfo& ssl_info, | 314 const net::SSLInfo& ssl_info, |
315 bool fatal) { | 315 bool fatal) { |
316 ResourceRequestInfoImpl* info = GetRequestInfo(); | 316 ResourceRequestInfoImpl* info = GetRequestInfo(); |
317 | 317 |
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
471 // WebKit will send us a cancel for downloads since it no longer handles | 471 // WebKit will send us a cancel for downloads since it no longer handles |
472 // them. In this case, ignore the cancel since we handle downloads in the | 472 // them. In this case, ignore the cancel since we handle downloads in the |
473 // browser. | 473 // browser. |
474 if (from_renderer && (info->is_download() || info->is_stream())) | 474 if (from_renderer && (info->is_download() || info->is_stream())) |
475 return; | 475 return; |
476 | 476 |
477 // TODO(darin): Perhaps we should really be looking to see if the status is | 477 // TODO(darin): Perhaps we should really be looking to see if the status is |
478 // IO_PENDING? | 478 // IO_PENDING? |
479 bool was_pending = request_->is_pending(); | 479 bool was_pending = request_->is_pending(); |
480 | 480 |
481 if (login_delegate_) { | 481 if (login_delegate_.get()) { |
482 login_delegate_->OnRequestCancelled(); | 482 login_delegate_->OnRequestCancelled(); |
483 login_delegate_ = NULL; | 483 login_delegate_ = NULL; |
484 } | 484 } |
485 if (ssl_client_auth_handler_) { | 485 if (ssl_client_auth_handler_.get()) { |
486 ssl_client_auth_handler_->OnRequestCancelled(); | 486 ssl_client_auth_handler_->OnRequestCancelled(); |
487 ssl_client_auth_handler_ = NULL; | 487 ssl_client_auth_handler_ = NULL; |
488 } | 488 } |
489 | 489 |
490 request_->CancelWithError(error); | 490 request_->CancelWithError(error); |
491 | 491 |
492 if (!was_pending) { | 492 if (!was_pending) { |
493 // If the request isn't in flight, then we won't get an asynchronous | 493 // If the request isn't in flight, then we won't get an asynchronous |
494 // notification from the request, so we have to signal ourselves to finish | 494 // notification from the request, so we have to signal ourselves to finish |
495 // this request. | 495 // this request. |
496 base::MessageLoop::current()->PostTask( | 496 base::MessageLoop::current()->PostTask( |
497 FROM_HERE, | 497 FROM_HERE, |
498 base::Bind(&ResourceLoader::ResponseCompleted, | 498 base::Bind(&ResourceLoader::ResponseCompleted, |
499 weak_ptr_factory_.GetWeakPtr())); | 499 weak_ptr_factory_.GetWeakPtr())); |
500 } | 500 } |
501 } | 501 } |
502 | 502 |
503 void ResourceLoader::CompleteResponseStarted() { | 503 void ResourceLoader::CompleteResponseStarted() { |
504 ResourceRequestInfoImpl* info = GetRequestInfo(); | 504 ResourceRequestInfoImpl* info = GetRequestInfo(); |
505 | 505 |
506 scoped_refptr<ResourceResponse> response(new ResourceResponse()); | 506 scoped_refptr<ResourceResponse> response(new ResourceResponse()); |
507 PopulateResourceResponse(request_.get(), response); | 507 PopulateResourceResponse(request_.get(), response.get()); |
508 | 508 |
509 // The --site-per-process flag enables an out-of-process iframes | 509 // The --site-per-process flag enables an out-of-process iframes |
510 // prototype. It works by changing the MIME type of cross-site subframe | 510 // prototype. It works by changing the MIME type of cross-site subframe |
511 // responses to a Chrome specific one. This new type causes the subframe | 511 // responses to a Chrome specific one. This new type causes the subframe |
512 // to be replaced by a <webview> tag with the same URL, which results in | 512 // to be replaced by a <webview> tag with the same URL, which results in |
513 // using a renderer in a different process. | 513 // using a renderer in a different process. |
514 // | 514 // |
515 // For prototyping purposes, we will use a small hack to ensure same site | 515 // For prototyping purposes, we will use a small hack to ensure same site |
516 // iframes are not changed. We can compare the URL for the subframe | 516 // iframes are not changed. We can compare the URL for the subframe |
517 // request with the referrer. If the two don't match, then it should be a | 517 // request with the referrer. If the two don't match, then it should be a |
518 // cross-site iframe. | 518 // cross-site iframe. |
519 // Also, we don't do the MIME type change for chrome:// URLs, as those | 519 // Also, we don't do the MIME type change for chrome:// URLs, as those |
520 // require different privileges and are not allowed in regular renderers. | 520 // require different privileges and are not allowed in regular renderers. |
521 // | 521 // |
522 // The usage of SiteInstance::IsSameWebSite is safe on the IO thread, | 522 // The usage of SiteInstance::IsSameWebSite is safe on the IO thread, |
523 // if the browser_context parameter is NULL. This does not work for hosted | 523 // if the browser_context parameter is NULL. This does not work for hosted |
524 // apps, but should be fine for prototyping. | 524 // apps, but should be fine for prototyping. |
525 // TODO(nasko): Once the SiteInstance check is fixed, ensure we do the | 525 // TODO(nasko): Once the SiteInstance check is fixed, ensure we do the |
526 // right thing here. http://crbug.com/160576 | 526 // right thing here. http://crbug.com/160576 |
527 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); | 527 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); |
528 if (command_line.HasSwitch(switches::kSitePerProcess) && | 528 if (command_line.HasSwitch(switches::kSitePerProcess) && |
529 GetRequestInfo()->GetResourceType() == ResourceType::SUB_FRAME && | 529 GetRequestInfo()->GetResourceType() == ResourceType::SUB_FRAME && |
530 response->head.mime_type == "text/html" && | 530 response->head.mime_type == "text/html" && |
531 !request_->url().SchemeIs(chrome::kChromeUIScheme) && | 531 !request_->url().SchemeIs(chrome::kChromeUIScheme) && |
532 !SiteInstance::IsSameWebSite(NULL, request_->url(), | 532 !SiteInstance::IsSameWebSite(NULL, request_->url(), |
533 GURL(request_->referrer()))) { | 533 GURL(request_->referrer()))) { |
534 response->head.mime_type = "application/browser-plugin"; | 534 response->head.mime_type = "application/browser-plugin"; |
535 } | 535 } |
536 | 536 |
537 if (request_->ssl_info().cert) { | 537 if (request_->ssl_info().cert.get()) { |
538 int cert_id = | 538 int cert_id = CertStore::GetInstance()->StoreCert( |
539 CertStore::GetInstance()->StoreCert(request_->ssl_info().cert, | 539 request_->ssl_info().cert.get(), info->GetChildID()); |
540 info->GetChildID()); | |
541 response->head.security_info = SerializeSecurityInfo( | 540 response->head.security_info = SerializeSecurityInfo( |
542 cert_id, | 541 cert_id, |
543 request_->ssl_info().cert_status, | 542 request_->ssl_info().cert_status, |
544 request_->ssl_info().security_bits, | 543 request_->ssl_info().security_bits, |
545 request_->ssl_info().connection_status); | 544 request_->ssl_info().connection_status); |
546 } else { | 545 } else { |
547 // We should not have any SSL state. | 546 // We should not have any SSL state. |
548 DCHECK(!request_->ssl_info().cert_status && | 547 DCHECK(!request_->ssl_info().cert_status && |
549 request_->ssl_info().security_bits == -1 && | 548 request_->ssl_info().security_bits == -1 && |
550 !request_->ssl_info().connection_status); | 549 !request_->ssl_info().connection_status); |
551 } | 550 } |
552 | 551 |
553 delegate_->DidReceiveResponse(this); | 552 delegate_->DidReceiveResponse(this); |
554 | 553 |
555 bool defer = false; | 554 bool defer = false; |
556 if (!handler_->OnResponseStarted(info->GetRequestID(), response, &defer)) { | 555 if (!handler_->OnResponseStarted( |
| 556 info->GetRequestID(), response.get(), &defer)) { |
557 Cancel(); | 557 Cancel(); |
558 } else if (defer) { | 558 } else if (defer) { |
559 deferred_stage_ = DEFERRED_READ; // Read first chunk when resumed. | 559 deferred_stage_ = DEFERRED_READ; // Read first chunk when resumed. |
560 } | 560 } |
561 } | 561 } |
562 | 562 |
563 void ResourceLoader::StartReading(bool is_continuation) { | 563 void ResourceLoader::StartReading(bool is_continuation) { |
564 int bytes_read = 0; | 564 int bytes_read = 0; |
565 ReadMore(&bytes_read); | 565 ReadMore(&bytes_read); |
566 | 566 |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
625 deferred_stage_ = DEFERRED_READ; // Read next chunk when resumed. | 625 deferred_stage_ = DEFERRED_READ; // Read next chunk when resumed. |
626 } | 626 } |
627 } | 627 } |
628 | 628 |
629 void ResourceLoader::ResponseCompleted() { | 629 void ResourceLoader::ResponseCompleted() { |
630 VLOG(1) << "ResponseCompleted: " << request_->url().spec(); | 630 VLOG(1) << "ResponseCompleted: " << request_->url().spec(); |
631 ResourceRequestInfoImpl* info = GetRequestInfo(); | 631 ResourceRequestInfoImpl* info = GetRequestInfo(); |
632 | 632 |
633 std::string security_info; | 633 std::string security_info; |
634 const net::SSLInfo& ssl_info = request_->ssl_info(); | 634 const net::SSLInfo& ssl_info = request_->ssl_info(); |
635 if (ssl_info.cert != NULL) { | 635 if (ssl_info.cert.get() != NULL) { |
636 int cert_id = CertStore::GetInstance()->StoreCert(ssl_info.cert, | 636 int cert_id = CertStore::GetInstance()->StoreCert(ssl_info.cert.get(), |
637 info->GetChildID()); | 637 info->GetChildID()); |
638 security_info = SerializeSecurityInfo( | 638 security_info = SerializeSecurityInfo( |
639 cert_id, ssl_info.cert_status, ssl_info.security_bits, | 639 cert_id, ssl_info.cert_status, ssl_info.security_bits, |
640 ssl_info.connection_status); | 640 ssl_info.connection_status); |
641 } | 641 } |
642 | 642 |
643 if (handler_->OnResponseCompleted(info->GetRequestID(), request_->status(), | 643 if (handler_->OnResponseCompleted(info->GetRequestID(), request_->status(), |
644 security_info)) { | 644 security_info)) { |
645 // This will result in our destruction. | 645 // This will result in our destruction. |
646 CallDidFinishLoading(); | 646 CallDidFinishLoading(); |
647 } else { | 647 } else { |
648 // The handler is not ready to die yet. We will call DidFinishLoading when | 648 // The handler is not ready to die yet. We will call DidFinishLoading when |
649 // we resume. | 649 // we resume. |
650 deferred_stage_ = DEFERRED_FINISH; | 650 deferred_stage_ = DEFERRED_FINISH; |
651 } | 651 } |
652 } | 652 } |
653 | 653 |
654 void ResourceLoader::CallDidFinishLoading() { | 654 void ResourceLoader::CallDidFinishLoading() { |
655 delegate_->DidFinishLoading(this); | 655 delegate_->DidFinishLoading(this); |
656 } | 656 } |
657 | 657 |
658 } // namespace content | 658 } // namespace content |
OLD | NEW |