Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(271)

Side by Side Diff: chrome/browser/net/preconnect.cc

Issue 3050040: Reland 54771 (and 54795) To enable TCP Preconnection by default... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 10 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chrome/browser/net/preconnect.h ('k') | chrome/browser/net/predictor.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/net/preconnect.h" 5 #include "chrome/browser/net/preconnect.h"
6 6
7 #include "base/histogram.h" 7 #include "base/histogram.h"
8 #include "base/logging.h" 8 #include "base/logging.h"
9 #include "base/string_util.h" 9 #include "base/string_util.h"
10 #include "chrome/browser/profile.h" 10 #include "chrome/browser/profile.h"
11 #include "chrome/browser/chrome_thread.h" 11 #include "chrome/browser/chrome_thread.h"
12 #include "chrome/common/net/url_request_context_getter.h" 12 #include "chrome/common/net/url_request_context_getter.h"
13 #include "net/base/host_port_pair.h" 13 #include "net/base/host_port_pair.h"
14 #include "net/http/http_network_session.h" 14 #include "net/http/http_network_session.h"
15 #include "net/http/http_transaction_factory.h" 15 #include "net/http/http_transaction_factory.h"
16 #include "net/proxy/proxy_service.h" 16 #include "net/proxy/proxy_service.h"
17 #include "net/url_request/url_request_context.h" 17 #include "net/url_request/url_request_context.h"
18 18
19 namespace chrome_browser_net { 19 namespace chrome_browser_net {
20 20
21 // static 21 // static
22 bool Preconnect::preconnect_despite_proxy_ = false; 22 bool Preconnect::preconnect_despite_proxy_ = false;
23 23
24 // We will deliberately leak this singular instance, which is used only for 24
25 // callbacks. 25 Preconnect::~Preconnect() {
26 // static 26 if (!handle_.is_initialized())
27 Preconnect* Preconnect::callback_instance_; 27 return;
28 DCHECK(motivation_ == UrlInfo::LEARNED_REFERAL_MOTIVATED ||
29 motivation_ == UrlInfo::OMNIBOX_MOTIVATED);
30 if (motivation_ == UrlInfo::OMNIBOX_MOTIVATED)
31 handle_.socket()->SetOmniboxSpeculation();
32 else
33 handle_.socket()->SetSubresourceSpeculation();
34 handle_.Reset();
35 }
28 36
29 // static 37 // static
30 void Preconnect::PreconnectOnUIThread(const GURL& url, 38 void Preconnect::PreconnectOnUIThread(const GURL& url,
31 UrlInfo::ResolutionMotivation motivation) { 39 UrlInfo::ResolutionMotivation motivation) {
32 // Try to do connection warming for this search provider.
33 URLRequestContextGetter* getter = Profile::GetDefaultRequestContext();
34 if (!getter)
35 return;
36 // Prewarm connection to Search URL. 40 // Prewarm connection to Search URL.
37 ChromeThread::PostTask( 41 ChromeThread::PostTask(
38 ChromeThread::IO, 42 ChromeThread::IO,
39 FROM_HERE, 43 FROM_HERE,
40 NewRunnableFunction(Preconnect::PreconnectOnIOThread, url, motivation)); 44 NewRunnableFunction(Preconnect::PreconnectOnIOThread, url, motivation));
41 return; 45 return;
42 } 46 }
43 47
44 enum ProxyStatus { 48 enum ProxyStatus {
45 PROXY_STATUS_IGNORED, 49 PROXY_STATUS_IGNORED,
46 PROXY_UNINITIALIZED, 50 PROXY_UNINITIALIZED,
47 PROXY_NOT_USED, 51 PROXY_NOT_USED,
48 PROXY_PAC_RESOLVER, 52 PROXY_PAC_RESOLVER,
49 PROXY_HAS_RULES, 53 PROXY_HAS_RULES,
50 PROXY_MAX, 54 PROXY_MAX,
51 }; 55 };
52 56
53 static void HistogramPreconnectStatus(ProxyStatus status) { 57 static void HistogramPreconnectStatus(ProxyStatus status) {
54 UMA_HISTOGRAM_ENUMERATION("Net.PreconnectProxyStatus", status, PROXY_MAX); 58 UMA_HISTOGRAM_ENUMERATION("Net.PreconnectProxyStatus", status, PROXY_MAX);
55 } 59 }
56 60
57 // static 61 // static
58 void Preconnect::PreconnectOnIOThread(const GURL& url, 62 void Preconnect::PreconnectOnIOThread(const GURL& url,
59 UrlInfo::ResolutionMotivation motivation) { 63 UrlInfo::ResolutionMotivation motivation) {
64 scoped_refptr<Preconnect> preconnect = new Preconnect(motivation);
65 // TODO(jar): Should I use PostTask for LearnedSubresources to delay the
66 // preconnection a tad?
67 preconnect->Connect(url);
68 }
69
70 void Preconnect::Connect(const GURL& url) {
60 URLRequestContextGetter* getter = Profile::GetDefaultRequestContext(); 71 URLRequestContextGetter* getter = Profile::GetDefaultRequestContext();
61 if (!getter) 72 if (!getter)
62 return; 73 return;
63 if (!ChromeThread::CurrentlyOn(ChromeThread::IO)) { 74 if (!ChromeThread::CurrentlyOn(ChromeThread::IO)) {
64 LOG(DFATAL) << "This must be run only on the IO thread."; 75 LOG(DFATAL) << "This must be run only on the IO thread.";
65 return; 76 return;
66 } 77 }
78
79 AddRef(); // Stay alive until socket is available.
80
67 URLRequestContext* context = getter->GetURLRequestContext(); 81 URLRequestContext* context = getter->GetURLRequestContext();
68 82
69 if (preconnect_despite_proxy_) { 83 if (preconnect_despite_proxy_) {
70 HistogramPreconnectStatus(PROXY_STATUS_IGNORED); 84 HistogramPreconnectStatus(PROXY_STATUS_IGNORED);
71 } else { 85 } else {
72 // Currently we avoid all preconnects if there is a proxy configuration. 86 // Currently we avoid all preconnects if there is a proxy configuration.
73 net::ProxyService* proxy_service = context->proxy_service(); 87 net::ProxyService* proxy_service = context->proxy_service();
74 if (!proxy_service->config_has_been_initialized()) { 88 if (!proxy_service->config_has_been_initialized()) {
75 HistogramPreconnectStatus(PROXY_UNINITIALIZED); 89 HistogramPreconnectStatus(PROXY_UNINITIALIZED);
76 } else { 90 } else {
77 if (proxy_service->config().MayRequirePACResolver()) { 91 if (proxy_service->config().MayRequirePACResolver()) {
78 HistogramPreconnectStatus(PROXY_PAC_RESOLVER); 92 HistogramPreconnectStatus(PROXY_PAC_RESOLVER);
79 return; 93 return;
80 } 94 }
81 if (!proxy_service->config().proxy_rules().empty()) { 95 if (!proxy_service->config().proxy_rules().empty()) {
82 HistogramPreconnectStatus(PROXY_HAS_RULES); 96 HistogramPreconnectStatus(PROXY_HAS_RULES);
83 return; 97 return;
84 } 98 }
85 HistogramPreconnectStatus(PROXY_NOT_USED); 99 HistogramPreconnectStatus(PROXY_NOT_USED);
86 } 100 }
87 } 101 }
88 102
89 UMA_HISTOGRAM_ENUMERATION("Net.PreconnectMotivation", motivation, 103 UMA_HISTOGRAM_ENUMERATION("Net.PreconnectMotivation", motivation_,
90 UrlInfo::MAX_MOTIVATED); 104 UrlInfo::MAX_MOTIVATED);
91 105
92 net::HttpTransactionFactory* factory = context->http_transaction_factory(); 106 net::HttpTransactionFactory* factory = context->http_transaction_factory();
93 net::HttpNetworkSession* session = factory->GetSession(); 107 net::HttpNetworkSession* session = factory->GetSession();
94 108
95 net::ClientSocketHandle handle;
96 if (!callback_instance_)
97 callback_instance_ = new Preconnect;
98
99 scoped_refptr<net::TCPSocketParams> tcp_params = 109 scoped_refptr<net::TCPSocketParams> tcp_params =
100 new net::TCPSocketParams(url.host(), url.EffectiveIntPort(), net::LOW, 110 new net::TCPSocketParams(url.host(), url.EffectiveIntPort(), net::LOW,
101 GURL(), false); 111 GURL(), false);
102 112
103 net::HostPortPair endpoint(url.host(), url.EffectiveIntPort()); 113 net::HostPortPair endpoint(url.host(), url.EffectiveIntPort());
104 std::string group_name = endpoint.ToString(); 114 std::string group_name = endpoint.ToString();
105 115
116 // It almost doesn't matter whether we use net::LOWEST or net::HIGHEST
117 // priority here, as we won't make a request, and will surrender the created
118 // socket to the pool as soon as we can. However, we would like to mark the
119 // speculative socket as such, and IF we use a net::LOWEST priority, and if
120 // a navigation asked for a socket (after us) then it would get our socket,
121 // and we'd get its later-arriving socket, which might make us record that
122 // the speculation didn't help :-/. By using net::HIGHEST, we ensure that
123 // a socket is given to us if "we asked first" and this allows us to mark it
124 // as speculative, and better detect stats (if it gets used).
125 // TODO(jar): histogram to see how often we accidentally use a previously-
126 // unused socket, when a previously used socket was available.
127 net::RequestPriority priority = net::HIGHEST;
128
106 if (url.SchemeIs("https")) { 129 if (url.SchemeIs("https")) {
107 group_name = StringPrintf("ssl/%s", group_name.c_str()); 130 group_name = StringPrintf("ssl/%s", group_name.c_str());
108 131
109 net::SSLConfig ssl_config; 132 net::SSLConfig ssl_config;
110 session->ssl_config_service()->GetSSLConfig(&ssl_config); 133 session->ssl_config_service()->GetSSLConfig(&ssl_config);
111 // All preconnects should be for main pages. 134 // All preconnects should be for main pages.
112 ssl_config.verify_ev_cert = true; 135 ssl_config.verify_ev_cert = true;
113 136
114 scoped_refptr<net::SSLSocketParams> ssl_params = 137 scoped_refptr<net::SSLSocketParams> ssl_params =
115 new net::SSLSocketParams(tcp_params, NULL, NULL, 138 new net::SSLSocketParams(tcp_params, NULL, NULL,
116 net::ProxyServer::SCHEME_DIRECT, 139 net::ProxyServer::SCHEME_DIRECT,
117 url.HostNoBrackets(), ssl_config, 140 url.HostNoBrackets(), ssl_config,
118 0, false, false); 141 0, false, false);
119 142
120 const scoped_refptr<net::SSLClientSocketPool>& pool = 143 const scoped_refptr<net::SSLClientSocketPool>& pool =
121 session->ssl_socket_pool(); 144 session->ssl_socket_pool();
122 145
123 handle.Init(group_name, ssl_params, net::LOWEST, callback_instance_, pool, 146 handle_.Init(group_name, ssl_params, priority, this, pool,
124 net::BoundNetLog()); 147 net::BoundNetLog());
125 handle.Reset();
126 return; 148 return;
127 } 149 }
128 150
129 const scoped_refptr<net::TCPClientSocketPool>& pool = 151 const scoped_refptr<net::TCPClientSocketPool>& pool =
130 session->tcp_socket_pool(); 152 session->tcp_socket_pool();
131 handle.Init(group_name, tcp_params, net::LOWEST, callback_instance_, pool, 153 handle_.Init(group_name, tcp_params, priority, this, pool,
132 net::BoundNetLog()); 154 net::BoundNetLog());
133 handle.Reset();
134 } 155 }
135 156
136 void Preconnect::RunWithParams(const Tuple1<int>& params) { 157 void Preconnect::RunWithParams(const Tuple1<int>& params) {
137 // This will rarely be called, as we reset the connection just after creating. 158 if (params.a < 0 && handle_.socket())
138 NOTREACHED(); 159 handle_.socket()->Disconnect();
160 Release();
139 } 161 }
140 } // chrome_browser_net 162 } // chrome_browser_net
OLDNEW
« no previous file with comments | « chrome/browser/net/preconnect.h ('k') | chrome/browser/net/predictor.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698