preconnect.cc revision 3345a6884c488ff3a535c2c9acdd33d74b37e311
1c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Copyright (c) 2010 The Chromium Authors. All rights reserved.
2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file.
4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/net/preconnect.h"
6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/histogram.h"
8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/logging.h"
93345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/string_util.h"
10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/profile.h"
11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/chrome_thread.h"
12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/net/url_request_context_getter.h"
13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/host_port_pair.h"
14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/http/http_network_session.h"
153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "net/http/http_request_info.h"
163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "net/http/http_stream.h"
17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/http/http_transaction_factory.h"
18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/proxy/proxy_service.h"
19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/url_request/url_request_context.h"
20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace chrome_browser_net {
22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static
243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid Preconnect::PreconnectOnUIThread(const GURL& url,
253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    UrlInfo::ResolutionMotivation motivation) {
26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Prewarm connection to Search URL.
27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ChromeThread::PostTask(
28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      ChromeThread::IO,
29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      FROM_HERE,
303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      NewRunnableFunction(Preconnect::PreconnectOnIOThread, url, motivation));
313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return;
32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// static
353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid Preconnect::PreconnectOnIOThread(const GURL& url,
363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    UrlInfo::ResolutionMotivation motivation) {
373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  Preconnect* preconnect = new Preconnect(motivation);
383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // TODO(jar): Should I use PostTask for LearnedSubresources to delay the
393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // preconnection a tad?
403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  preconnect->Connect(url);
41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid Preconnect::Connect(const GURL& url) {
44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  URLRequestContextGetter* getter = Profile::GetDefaultRequestContext();
45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!getter)
46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!ChromeThread::CurrentlyOn(ChromeThread::IO)) {
48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    LOG(DFATAL) << "This must be run only on the IO thread.";
49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // We are now commited to doing the async preconnection call.
533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  UMA_HISTOGRAM_ENUMERATION("Net.PreconnectMotivation", motivation_,
543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                            UrlInfo::MAX_MOTIVATED);
55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  URLRequestContext* context = getter->GetURLRequestContext();
57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  net::HttpTransactionFactory* factory = context->http_transaction_factory();
58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  net::HttpNetworkSession* session = factory->GetSession();
59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  request_info_.reset(new net::HttpRequestInfo());
613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  request_info_->url = url;
623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  request_info_->method = "GET";
633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // It almost doesn't matter whether we use net::LOWEST or net::HIGHEST
643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // priority here, as we won't make a request, and will surrender the created
653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // socket to the pool as soon as we can.  However, we would like to mark the
663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // speculative socket as such, and IF we use a net::LOWEST priority, and if
673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // a navigation asked for a socket (after us) then it would get our socket,
683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // and we'd get its later-arriving socket, which might make us record that
693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // the speculation didn't help :-/.  By using net::HIGHEST, we ensure that
703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // a socket is given to us if "we asked first" and this allows us to mark it
713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // as speculative, and better detect stats (if it gets used).
723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // TODO(jar): histogram to see how often we accidentally use a previously-
733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // unused socket, when a previously used socket was available.
743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  request_info_->priority = net::HIGHEST;
753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Translate the motivation from UrlRequest motivations to HttpRequest
773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // motivations.
783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  switch (motivation_) {
793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    case UrlInfo::OMNIBOX_MOTIVATED:
803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      request_info_->motivation = net::HttpRequestInfo::OMNIBOX_MOTIVATED;
813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      break;
823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    case UrlInfo::LEARNED_REFERAL_MOTIVATED:
833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      request_info_->motivation = net::HttpRequestInfo::PRECONNECT_MOTIVATED;
843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      break;
853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    case UrlInfo::EARLY_LOAD_MOTIVATED:
863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      break;
873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    default:
883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      // Other motivations should never happen here.
893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      NOTREACHED();
903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      break;
913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Setup the SSL Configuration.
943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ssl_config_.reset(new net::SSLConfig());
953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  session->ssl_config_service()->GetSSLConfig(ssl_config_.get());
963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (session->http_stream_factory()->next_protos())
973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    ssl_config_->next_protos = *session->http_stream_factory()->next_protos();
98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // All preconnects should be for main pages.
1003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ssl_config_->verify_ev_cert = true;
101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  proxy_info_.reset(new net::ProxyInfo());
1033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  net::StreamFactory* stream_factory = session->http_stream_factory();
1043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  stream_factory->RequestStream(request_info_.get(), ssl_config_.get(),
1053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                proxy_info_.get(), this, net_log_, session,
1063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                &stream_request_job_);
1073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid Preconnect::OnStreamReady(net::HttpStream* stream) {
1103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  delete stream;
1113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  delete this;
1123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid Preconnect::OnStreamFailed(int status) {
1153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  delete this;
1163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid Preconnect::OnCertificateError(int status, const net::SSLInfo& ssl_info) {
1193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  delete this;
1203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid Preconnect::OnNeedsProxyAuth(const net::HttpResponseInfo& proxy_response,
1233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                  net::HttpAuthController* auth_controller) {
1243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  delete this;
125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid Preconnect::OnNeedsClientAuth(net::SSLCertRequestInfo* cert_info) {
1283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  delete this;
129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
1303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}  // chrome_browser_net
132