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