preconnect.cc revision 3345a6884c488ff3a535c2c9acdd33d74b37e311
1// Copyright (c) 2010 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "chrome/browser/net/preconnect.h" 6 7#include "base/histogram.h" 8#include "base/logging.h" 9#include "base/string_util.h" 10#include "chrome/browser/profile.h" 11#include "chrome/browser/chrome_thread.h" 12#include "chrome/common/net/url_request_context_getter.h" 13#include "net/base/host_port_pair.h" 14#include "net/http/http_network_session.h" 15#include "net/http/http_request_info.h" 16#include "net/http/http_stream.h" 17#include "net/http/http_transaction_factory.h" 18#include "net/proxy/proxy_service.h" 19#include "net/url_request/url_request_context.h" 20 21namespace chrome_browser_net { 22 23// static 24void Preconnect::PreconnectOnUIThread(const GURL& url, 25 UrlInfo::ResolutionMotivation motivation) { 26 // Prewarm connection to Search URL. 27 ChromeThread::PostTask( 28 ChromeThread::IO, 29 FROM_HERE, 30 NewRunnableFunction(Preconnect::PreconnectOnIOThread, url, motivation)); 31 return; 32} 33 34// static 35void Preconnect::PreconnectOnIOThread(const GURL& url, 36 UrlInfo::ResolutionMotivation motivation) { 37 Preconnect* preconnect = new Preconnect(motivation); 38 // TODO(jar): Should I use PostTask for LearnedSubresources to delay the 39 // preconnection a tad? 40 preconnect->Connect(url); 41} 42 43void Preconnect::Connect(const GURL& url) { 44 URLRequestContextGetter* getter = Profile::GetDefaultRequestContext(); 45 if (!getter) 46 return; 47 if (!ChromeThread::CurrentlyOn(ChromeThread::IO)) { 48 LOG(DFATAL) << "This must be run only on the IO thread."; 49 return; 50 } 51 52 // We are now commited to doing the async preconnection call. 53 UMA_HISTOGRAM_ENUMERATION("Net.PreconnectMotivation", motivation_, 54 UrlInfo::MAX_MOTIVATED); 55 56 URLRequestContext* context = getter->GetURLRequestContext(); 57 net::HttpTransactionFactory* factory = context->http_transaction_factory(); 58 net::HttpNetworkSession* session = factory->GetSession(); 59 60 request_info_.reset(new net::HttpRequestInfo()); 61 request_info_->url = url; 62 request_info_->method = "GET"; 63 // It almost doesn't matter whether we use net::LOWEST or net::HIGHEST 64 // priority here, as we won't make a request, and will surrender the created 65 // socket to the pool as soon as we can. However, we would like to mark the 66 // speculative socket as such, and IF we use a net::LOWEST priority, and if 67 // a navigation asked for a socket (after us) then it would get our socket, 68 // and we'd get its later-arriving socket, which might make us record that 69 // the speculation didn't help :-/. By using net::HIGHEST, we ensure that 70 // a socket is given to us if "we asked first" and this allows us to mark it 71 // as speculative, and better detect stats (if it gets used). 72 // TODO(jar): histogram to see how often we accidentally use a previously- 73 // unused socket, when a previously used socket was available. 74 request_info_->priority = net::HIGHEST; 75 76 // Translate the motivation from UrlRequest motivations to HttpRequest 77 // motivations. 78 switch (motivation_) { 79 case UrlInfo::OMNIBOX_MOTIVATED: 80 request_info_->motivation = net::HttpRequestInfo::OMNIBOX_MOTIVATED; 81 break; 82 case UrlInfo::LEARNED_REFERAL_MOTIVATED: 83 request_info_->motivation = net::HttpRequestInfo::PRECONNECT_MOTIVATED; 84 break; 85 case UrlInfo::EARLY_LOAD_MOTIVATED: 86 break; 87 default: 88 // Other motivations should never happen here. 89 NOTREACHED(); 90 break; 91 } 92 93 // Setup the SSL Configuration. 94 ssl_config_.reset(new net::SSLConfig()); 95 session->ssl_config_service()->GetSSLConfig(ssl_config_.get()); 96 if (session->http_stream_factory()->next_protos()) 97 ssl_config_->next_protos = *session->http_stream_factory()->next_protos(); 98 99 // All preconnects should be for main pages. 100 ssl_config_->verify_ev_cert = true; 101 102 proxy_info_.reset(new net::ProxyInfo()); 103 net::StreamFactory* stream_factory = session->http_stream_factory(); 104 stream_factory->RequestStream(request_info_.get(), ssl_config_.get(), 105 proxy_info_.get(), this, net_log_, session, 106 &stream_request_job_); 107} 108 109void Preconnect::OnStreamReady(net::HttpStream* stream) { 110 delete stream; 111 delete this; 112} 113 114void Preconnect::OnStreamFailed(int status) { 115 delete this; 116} 117 118void Preconnect::OnCertificateError(int status, const net::SSLInfo& ssl_info) { 119 delete this; 120} 121 122void Preconnect::OnNeedsProxyAuth(const net::HttpResponseInfo& proxy_response, 123 net::HttpAuthController* auth_controller) { 124 delete this; 125} 126 127void Preconnect::OnNeedsClientAuth(net::SSLCertRequestInfo* cert_info) { 128 delete this; 129} 130 131} // chrome_browser_net 132