preconnect.cc revision 5821806d5e7f356e8fa4b058a389a808ea183019
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 3// found in the LICENSE file. 4 5#include "chrome/browser/net/preconnect.h" 6 7#include "base/bind.h" 8#include "base/logging.h" 9#include "base/metrics/histogram.h" 10#include "content/public/browser/browser_thread.h" 11#include "net/base/net_log.h" 12#include "net/base/ssl_config_service.h" 13#include "net/http/http_network_session.h" 14#include "net/http/http_request_info.h" 15#include "net/http/http_stream_factory.h" 16#include "net/http/http_transaction_factory.h" 17#include "net/url_request/url_request_context.h" 18#include "net/url_request/url_request_context_getter.h" 19 20using content::BrowserThread; 21 22namespace chrome_browser_net { 23 24void PreconnectOnUIThread( 25 const GURL& url, 26 UrlInfo::ResolutionMotivation motivation, 27 int count, 28 net::URLRequestContextGetter* getter) { 29 // Prewarm connection to Search URL. 30 BrowserThread::PostTask( 31 BrowserThread::IO, 32 FROM_HERE, 33 base::Bind(&PreconnectOnIOThread, url, motivation, count, 34 make_scoped_refptr(getter))); 35 return; 36} 37 38 39void PreconnectOnIOThread( 40 const GURL& url, 41 UrlInfo::ResolutionMotivation motivation, 42 int count, 43 net::URLRequestContextGetter* getter) { 44 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) { 45 LOG(DFATAL) << "This must be run only on the IO thread."; 46 return; 47 } 48 if (!getter) 49 return; 50 // We are now commited to doing the async preconnection call. 51 UMA_HISTOGRAM_ENUMERATION("Net.PreconnectMotivation", motivation, 52 UrlInfo::MAX_MOTIVATED); 53 54 net::URLRequestContext* context = getter->GetURLRequestContext(); 55 net::HttpTransactionFactory* factory = context->http_transaction_factory(); 56 net::HttpNetworkSession* session = factory->GetSession(); 57 58 net::HttpRequestInfo request_info; 59 request_info.url = url; 60 request_info.method = "GET"; 61 request_info.extra_headers.SetHeader(net::HttpRequestHeaders::kUserAgent, 62 context->GetUserAgent(url)); 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::SELF_REFERAL_MOTIVATED: 86 case UrlInfo::EARLY_LOAD_MOTIVATED: 87 request_info.motivation = net::HttpRequestInfo::EARLY_LOAD_MOTIVATED; 88 break; 89 default: 90 // Other motivations should never happen here. 91 NOTREACHED(); 92 break; 93 } 94 95 // Setup the SSL Configuration. 96 net::SSLConfig ssl_config; 97 session->ssl_config_service()->GetSSLConfig(&ssl_config); 98 if (session->http_stream_factory()->has_next_protos()) 99 ssl_config.next_protos = session->http_stream_factory()->next_protos(); 100 101 // All preconnects should perform EV certificate verification. 102 ssl_config.verify_ev_cert = true; 103 104 net::HttpStreamFactory* http_stream_factory = session->http_stream_factory(); 105 http_stream_factory->PreconnectStreams(count, request_info, ssl_config, 106 ssl_config); 107} 108 109} // namespace chrome_browser_net 110