preconnect.cc revision 3345a6884c488ff3a535c2c9acdd33d74b37e311
1c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Copyright (c) 2010 The Chromium Authors. All rights reserved. 2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file. 4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/net/preconnect.h" 6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/histogram.h" 8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/logging.h" 93345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/string_util.h" 10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/profile.h" 11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/chrome_thread.h" 12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/net/url_request_context_getter.h" 13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/host_port_pair.h" 14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/http/http_network_session.h" 153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "net/http/http_request_info.h" 163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "net/http/http_stream.h" 17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/http/http_transaction_factory.h" 18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/proxy/proxy_service.h" 19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/url_request/url_request_context.h" 20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace chrome_browser_net { 22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static 243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid Preconnect::PreconnectOnUIThread(const GURL& url, 253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick UrlInfo::ResolutionMotivation motivation) { 26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Prewarm connection to Search URL. 27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ChromeThread::PostTask( 28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ChromeThread::IO, 29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FROM_HERE, 303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick NewRunnableFunction(Preconnect::PreconnectOnIOThread, url, motivation)); 313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return; 32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// static 353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid Preconnect::PreconnectOnIOThread(const GURL& url, 363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick UrlInfo::ResolutionMotivation motivation) { 373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick Preconnect* preconnect = new Preconnect(motivation); 383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // TODO(jar): Should I use PostTask for LearnedSubresources to delay the 393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // preconnection a tad? 403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick preconnect->Connect(url); 41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid Preconnect::Connect(const GURL& url) { 44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch URLRequestContextGetter* getter = Profile::GetDefaultRequestContext(); 45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!getter) 46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!ChromeThread::CurrentlyOn(ChromeThread::IO)) { 48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LOG(DFATAL) << "This must be run only on the IO thread."; 49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // We are now commited to doing the async preconnection call. 533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick UMA_HISTOGRAM_ENUMERATION("Net.PreconnectMotivation", motivation_, 543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick UrlInfo::MAX_MOTIVATED); 55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick URLRequestContext* context = getter->GetURLRequestContext(); 57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch net::HttpTransactionFactory* factory = context->http_transaction_factory(); 58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch net::HttpNetworkSession* session = factory->GetSession(); 59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick request_info_.reset(new net::HttpRequestInfo()); 613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick request_info_->url = url; 623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick request_info_->method = "GET"; 633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // It almost doesn't matter whether we use net::LOWEST or net::HIGHEST 643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // priority here, as we won't make a request, and will surrender the created 653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // socket to the pool as soon as we can. However, we would like to mark the 663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // speculative socket as such, and IF we use a net::LOWEST priority, and if 673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // a navigation asked for a socket (after us) then it would get our socket, 683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // and we'd get its later-arriving socket, which might make us record that 693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // the speculation didn't help :-/. By using net::HIGHEST, we ensure that 703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // a socket is given to us if "we asked first" and this allows us to mark it 713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // as speculative, and better detect stats (if it gets used). 723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // TODO(jar): histogram to see how often we accidentally use a previously- 733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // unused socket, when a previously used socket was available. 743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick request_info_->priority = net::HIGHEST; 753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Translate the motivation from UrlRequest motivations to HttpRequest 773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // motivations. 783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick switch (motivation_) { 793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick case UrlInfo::OMNIBOX_MOTIVATED: 803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick request_info_->motivation = net::HttpRequestInfo::OMNIBOX_MOTIVATED; 813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick break; 823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick case UrlInfo::LEARNED_REFERAL_MOTIVATED: 833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick request_info_->motivation = net::HttpRequestInfo::PRECONNECT_MOTIVATED; 843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick break; 853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick case UrlInfo::EARLY_LOAD_MOTIVATED: 863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick break; 873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick default: 883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Other motivations should never happen here. 893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick NOTREACHED(); 903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick break; 913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Setup the SSL Configuration. 943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick ssl_config_.reset(new net::SSLConfig()); 953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick session->ssl_config_service()->GetSSLConfig(ssl_config_.get()); 963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (session->http_stream_factory()->next_protos()) 973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick ssl_config_->next_protos = *session->http_stream_factory()->next_protos(); 98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // All preconnects should be for main pages. 1003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick ssl_config_->verify_ev_cert = true; 101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick proxy_info_.reset(new net::ProxyInfo()); 1033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick net::StreamFactory* stream_factory = session->http_stream_factory(); 1043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick stream_factory->RequestStream(request_info_.get(), ssl_config_.get(), 1053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick proxy_info_.get(), this, net_log_, session, 1063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick &stream_request_job_); 1073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid Preconnect::OnStreamReady(net::HttpStream* stream) { 1103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick delete stream; 1113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick delete this; 1123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid Preconnect::OnStreamFailed(int status) { 1153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick delete this; 1163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid Preconnect::OnCertificateError(int status, const net::SSLInfo& ssl_info) { 1193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick delete this; 1203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid Preconnect::OnNeedsProxyAuth(const net::HttpResponseInfo& proxy_response, 1233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick net::HttpAuthController* auth_controller) { 1243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick delete this; 125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid Preconnect::OnNeedsClientAuth(net::SSLCertRequestInfo* cert_info) { 1283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick delete this; 129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} // chrome_browser_net 132