1// Copyright (c) 2011 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/logging.h" 8#include "base/metrics/histogram.h" 9#include "chrome/browser/profiles/profile.h" 10#include "content/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 20namespace chrome_browser_net { 21 22void PreconnectOnUIThread( 23 const GURL& url, 24 UrlInfo::ResolutionMotivation motivation, 25 int count) { 26 // Prewarm connection to Search URL. 27 BrowserThread::PostTask( 28 BrowserThread::IO, 29 FROM_HERE, 30 NewRunnableFunction(PreconnectOnIOThread, url, motivation, 31 count)); 32 return; 33} 34 35 36void PreconnectOnIOThread( 37 const GURL& url, 38 UrlInfo::ResolutionMotivation motivation, 39 int count) { 40 net::URLRequestContextGetter* getter = Profile::GetDefaultRequestContext(); 41 if (!getter) 42 return; 43 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) { 44 LOG(DFATAL) << "This must be run only on the IO thread."; 45 return; 46 } 47 48 // We are now commited to doing the async preconnection call. 49 UMA_HISTOGRAM_ENUMERATION("Net.PreconnectMotivation", motivation, 50 UrlInfo::MAX_MOTIVATED); 51 52 net::URLRequestContext* context = getter->GetURLRequestContext(); 53 net::HttpTransactionFactory* factory = context->http_transaction_factory(); 54 net::HttpNetworkSession* session = factory->GetSession(); 55 56 net::HttpRequestInfo request_info; 57 request_info.url = url; 58 request_info.method = "GET"; 59 request_info.extra_headers.SetHeader(net::HttpRequestHeaders::kUserAgent, 60 context->GetUserAgent(url)); 61 // It almost doesn't matter whether we use net::LOWEST or net::HIGHEST 62 // priority here, as we won't make a request, and will surrender the created 63 // socket to the pool as soon as we can. However, we would like to mark the 64 // speculative socket as such, and IF we use a net::LOWEST priority, and if 65 // a navigation asked for a socket (after us) then it would get our socket, 66 // and we'd get its later-arriving socket, which might make us record that 67 // the speculation didn't help :-/. By using net::HIGHEST, we ensure that 68 // a socket is given to us if "we asked first" and this allows us to mark it 69 // as speculative, and better detect stats (if it gets used). 70 // TODO(jar): histogram to see how often we accidentally use a previously- 71 // unused socket, when a previously used socket was available. 72 request_info.priority = net::HIGHEST; 73 74 // Translate the motivation from UrlRequest motivations to HttpRequest 75 // motivations. 76 switch (motivation) { 77 case UrlInfo::OMNIBOX_MOTIVATED: 78 request_info.motivation = net::HttpRequestInfo::OMNIBOX_MOTIVATED; 79 break; 80 case UrlInfo::LEARNED_REFERAL_MOTIVATED: 81 request_info.motivation = net::HttpRequestInfo::PRECONNECT_MOTIVATED; 82 break; 83 case UrlInfo::SELF_REFERAL_MOTIVATED: 84 case UrlInfo::EARLY_LOAD_MOTIVATED: 85 request_info.motivation = net::HttpRequestInfo::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 net::SSLConfig ssl_config; 95 session->ssl_config_service()->GetSSLConfig(&ssl_config); 96 if (session->http_stream_factory()->next_protos()) 97 ssl_config.next_protos = *session->http_stream_factory()->next_protos(); 98 99 // All preconnects should perform EV certificate verification. 100 ssl_config.verify_ev_cert = true; 101 102 net::HttpStreamFactory* http_stream_factory = session->http_stream_factory(); 103 http_stream_factory->PreconnectStreams( 104 count, request_info, ssl_config, net::BoundNetLog()); 105} 106 107} // namespace chrome_browser_net 108