preconnect.cc revision 3345a6884c488ff3a535c2c9acdd33d74b37e311
1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2010 The Chromium Authors. All rights reserved. 2bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// Use of this source code is governed by a BSD-style license that can be 3bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// found in the LICENSE file. 4bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 5bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "chrome/browser/net/preconnect.h" 6bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 7bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "base/histogram.h" 8bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "base/logging.h" 9bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "base/string_util.h" 10bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "chrome/browser/profile.h" 11bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "chrome/browser/chrome_thread.h" 12bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "chrome/common/net/url_request_context_getter.h" 1372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "net/base/host_port_pair.h" 1472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "net/http/http_network_session.h" 1572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "net/http/http_request_info.h" 16bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "net/http/http_stream.h" 17bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "net/http/http_transaction_factory.h" 18bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "net/proxy/proxy_service.h" 19bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "net/url_request/url_request_context.h" 20bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 21bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsennamespace chrome_browser_net { 22bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 23731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// static 24ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid Preconnect::PreconnectOnUIThread(const GURL& url, 25731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick UrlInfo::ResolutionMotivation motivation) { 26bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen // Prewarm connection to Search URL. 27bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen ChromeThread::PostTask( 284a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch ChromeThread::IO, 293f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen FROM_HERE, 303f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen NewRunnableFunction(Preconnect::PreconnectOnIOThread, url, motivation)); 314a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch return; 324a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch} 33bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 34731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// static 35bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenvoid Preconnect::PreconnectOnIOThread(const GURL& url, 36731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick UrlInfo::ResolutionMotivation motivation) { 37ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen Preconnect* preconnect = new Preconnect(motivation); 38513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // TODO(jar): Should I use PostTask for LearnedSubresources to delay the 39513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // preconnection a tad? 40513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch preconnect->Connect(url); 41bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen} 42bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 43bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenvoid Preconnect::Connect(const GURL& url) { 44513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch URLRequestContextGetter* getter = Profile::GetDefaultRequestContext(); 45bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen if (!getter) 46bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen return; 47731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (!ChromeThread::CurrentlyOn(ChromeThread::IO)) { 483f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen LOG(DFATAL) << "This must be run only on the IO thread."; 49731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return; 503f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen } 513f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen 52731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // We are now commited to doing the async preconnection call. 53dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen UMA_HISTOGRAM_ENUMERATION("Net.PreconnectMotivation", motivation_, 54dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen UrlInfo::MAX_MOTIVATED); 55731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 56731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick URLRequestContext* context = getter->GetURLRequestContext(); 57731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick net::HttpTransactionFactory* factory = context->http_transaction_factory(); 58731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick net::HttpNetworkSession* session = factory->GetSession(); 59731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 60731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick request_info_.reset(new net::HttpRequestInfo()); 61bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen request_info_->url = url; 62513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch request_info_->method = "GET"; 63bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen // It almost doesn't matter whether we use net::LOWEST or net::HIGHEST 64bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen // priority here, as we won't make a request, and will surrender the created 65bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen // socket to the pool as soon as we can. However, we would like to mark the 66513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // speculative socket as such, and IF we use a net::LOWEST priority, and if 67bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen // a navigation asked for a socket (after us) then it would get our socket, 68513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // and we'd get its later-arriving socket, which might make us record that 69bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen // the speculation didn't help :-/. By using net::HIGHEST, we ensure that 70bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen // a socket is given to us if "we asked first" and this allows us to mark it 71bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen // as speculative, and better detect stats (if it gets used). 72bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen // TODO(jar): histogram to see how often we accidentally use a previously- 73731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // unused socket, when a previously used socket was available. 74731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick request_info_->priority = net::HIGHEST; 75731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 76bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen // Translate the motivation from UrlRequest motivations to HttpRequest 77bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen // motivations. 78513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch switch (motivation_) { 79513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch case UrlInfo::OMNIBOX_MOTIVATED: 80513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch request_info_->motivation = net::HttpRequestInfo::OMNIBOX_MOTIVATED; 81731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick break; 82513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch case UrlInfo::LEARNED_REFERAL_MOTIVATED: 83513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch request_info_->motivation = net::HttpRequestInfo::PRECONNECT_MOTIVATED; 843f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen break; 853f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen case UrlInfo::EARLY_LOAD_MOTIVATED: 8621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen break; 8721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen default: 8821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // Other motivations should never happen here. 89dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen NOTREACHED(); 90ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen break; 9121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 9221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 9321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // Setup the SSL Configuration. 94dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen ssl_config_.reset(new net::SSLConfig()); 95ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen session->ssl_config_service()->GetSSLConfig(ssl_config_.get()); 96513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (session->http_stream_factory()->next_protos()) 9721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen ssl_config_->next_protos = *session->http_stream_factory()->next_protos(); 98513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 99731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // All preconnects should be for main pages. 100731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick ssl_config_->verify_ev_cert = true; 101731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 102731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick proxy_info_.reset(new net::ProxyInfo()); 103dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen net::StreamFactory* stream_factory = session->http_stream_factory(); 104731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick stream_factory->RequestStream(request_info_.get(), ssl_config_.get(), 105731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick proxy_info_.get(), this, net_log_, session, 106ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen &stream_request_job_); 107731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 108ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 109bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenvoid Preconnect::OnStreamReady(net::HttpStream* stream) { 110bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen delete stream; 111bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen delete this; 112731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 113bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 1143f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenvoid Preconnect::OnStreamFailed(int status) { 1153f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen delete this; 116bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen} 117bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 118731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickvoid Preconnect::OnCertificateError(int status, const net::SSLInfo& ssl_info) { 119bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen delete this; 1203f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen} 1213f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen 122bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenvoid Preconnect::OnNeedsProxyAuth(const net::HttpResponseInfo& proxy_response, 123bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen net::HttpAuthController* auth_controller) { 124bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen delete this; 125513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 126bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 127bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenvoid Preconnect::OnNeedsClientAuth(net::SSLCertRequestInfo* cert_info) { 128bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen delete this; 129} 130 131} // chrome_browser_net 132