preconnect.cc revision 3240926e260ce088908e02ac07a6cf7b0c0cbf44
195640e3a20adea634b4df4ccf8c93f411184c438joi@chromium.org// Copyright (c) 2012 The Chromium Authors. All rights reserved. 295640e3a20adea634b4df4ccf8c93f411184c438joi@chromium.org// Use of this source code is governed by a BSD-style license that can be 301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org// found in the LICENSE file. 401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org#include "chrome/browser/net/preconnect.h" 601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org#include "base/bind.h" 801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org#include "base/logging.h" 901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org#include "base/metrics/histogram.h" 1001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org#include "content/public/browser/browser_thread.h" 1101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org#include "net/base/net_log.h" 1201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org#include "net/http/http_network_session.h" 1301fadb72b6e94e6511eaffd1874a8cc095f098a7joi@chromium.org#include "net/http/http_request_info.h" 1401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org#include "net/http/http_stream_factory.h" 15ec8016c73b3b945b6284746230913d88653f35e7benrg@chromium.org#include "net/http/http_transaction_factory.h" 16b9161407f737461b5db16a29782f8a31d19e602dbenrg@chromium.org#include "net/ssl/ssl_config_service.h" 17b9161407f737461b5db16a29782f8a31d19e602dbenrg@chromium.org#include "net/url_request/url_request_context.h" 1801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org#include "net/url_request/url_request_context_getter.h" 1901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 2001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.orgusing content::BrowserThread; 2101fadb72b6e94e6511eaffd1874a8cc095f098a7joi@chromium.org 2201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.orgnamespace chrome_browser_net { 2301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 2401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.orgvoid PreconnectOnUIThread( 2501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org const GURL& url, 2601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org const GURL& first_party_for_cookies, 2701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org UrlInfo::ResolutionMotivation motivation, 2801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org int count, 2901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org net::URLRequestContextGetter* getter) { 3001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org // Prewarm connection to Search URL. 3101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org BrowserThread::PostTask( 3201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org BrowserThread::IO, 3301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org FROM_HERE, 3401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org base::Bind(&PreconnectOnIOThread, url, first_party_for_cookies, 3501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org motivation, count, make_scoped_refptr(getter))); 3601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org return; 3701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org} 3801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 3901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 4001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.orgvoid PreconnectOnIOThread( 4101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org const GURL& url, 4201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org const GURL& first_party_for_cookies, 4301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org UrlInfo::ResolutionMotivation motivation, 4401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org int count, 4501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org net::URLRequestContextGetter* getter) { 4601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) { 4701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org LOG(DFATAL) << "This must be run only on the IO thread."; 4801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org return; 4901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org } 5001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org if (!getter) 5101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org return; 5201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org // We are now commited to doing the async preconnection call. 5301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org UMA_HISTOGRAM_ENUMERATION("Net.PreconnectMotivation", motivation, 5401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org UrlInfo::MAX_MOTIVATED); 5501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 5601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org net::URLRequestContext* context = getter->GetURLRequestContext(); 5701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org net::HttpTransactionFactory* factory = context->http_transaction_factory(); 5801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org net::HttpNetworkSession* session = factory->GetSession(); 5901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 6001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org net::HttpRequestInfo request_info; 6101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org request_info.url = url; 6201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org request_info.method = "GET"; 6301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org request_info.extra_headers.SetHeader(net::HttpRequestHeaders::kUserAgent, 6401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org context->GetUserAgent(url)); 6501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 6601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org net::NetworkDelegate* delegate = context->network_delegate(); 6701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org if (delegate->CanEnablePrivacyMode(url, first_party_for_cookies)) 6801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org request_info.privacy_mode = net::kPrivacyModeEnabled; 6901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 7001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org // It almost doesn't matter whether we use net::LOWEST or net::HIGHEST 7101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org // priority here, as we won't make a request, and will surrender the created 7201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org // socket to the pool as soon as we can. However, we would like to mark the 7301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org // speculative socket as such, and IF we use a net::LOWEST priority, and if 7401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org // a navigation asked for a socket (after us) then it would get our socket, 7501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org // and we'd get its later-arriving socket, which might make us record that 7601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org // the speculation didn't help :-/. By using net::HIGHEST, we ensure that 7701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org // a socket is given to us if "we asked first" and this allows us to mark it 7801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org // as speculative, and better detect stats (if it gets used). 7901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org // TODO(jar): histogram to see how often we accidentally use a previously- 8001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org // unused socket, when a previously used socket was available. 8101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org net::RequestPriority priority = net::HIGHEST; 8201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 8301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org // Translate the motivation from UrlRequest motivations to HttpRequest 8401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org // motivations. 8501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org switch (motivation) { 8601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org case UrlInfo::OMNIBOX_MOTIVATED: 8701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org request_info.motivation = net::HttpRequestInfo::OMNIBOX_MOTIVATED; 8801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org break; 8901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org case UrlInfo::LEARNED_REFERAL_MOTIVATED: 9001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org request_info.motivation = net::HttpRequestInfo::PRECONNECT_MOTIVATED; 9101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org break; 9201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org case UrlInfo::MOUSE_OVER_MOTIVATED: 9301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org case UrlInfo::SELF_REFERAL_MOTIVATED: 9401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org case UrlInfo::EARLY_LOAD_MOTIVATED: 9501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org request_info.motivation = net::HttpRequestInfo::EARLY_LOAD_MOTIVATED; 9601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org break; 9701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org default: 9801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org // Other motivations should never happen here. 9901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org NOTREACHED(); 10001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org break; 10101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org } 10201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 10301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org // Setup the SSL Configuration. 10401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org net::SSLConfig ssl_config; 10501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org session->ssl_config_service()->GetSSLConfig(&ssl_config); 10601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org if (session->http_stream_factory()->has_next_protos()) 10701b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org ssl_config.next_protos = session->http_stream_factory()->next_protos(); 10801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 10901b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org // All preconnects should perform EV certificate verification. 11001b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org ssl_config.verify_ev_cert = true; 11101b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 11201b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org net::HttpStreamFactory* http_stream_factory = session->http_stream_factory(); 11301b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org http_stream_factory->PreconnectStreams(count, request_info, priority, 11401b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org ssl_config, ssl_config); 11501b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org} 11601b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org 117ec8016c73b3b945b6284746230913d88653f35e7benrg@chromium.org} // namespace chrome_browser_net 11801b3bc768461bd303bff39f8cd1663682254e407joi@chromium.org