1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 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/logging.h" 8731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "base/metrics/histogram.h" 921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/profiles/profile.h" 10dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/browser_thread.h" 11dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "net/base/net_log.h" 12dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "net/base/ssl_config_service.h" 13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/http/http_network_session.h" 14dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "net/http/http_request_info.h" 15dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "net/http/http_stream_factory.h" 16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/http/http_transaction_factory.h" 17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/url_request/url_request_context.h" 18ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "net/url_request/url_request_context_getter.h" 19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace chrome_browser_net { 21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 22dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid PreconnectOnUIThread( 23dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen const GURL& url, 24dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen UrlInfo::ResolutionMotivation motivation, 25dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen int count) { 26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Prewarm connection to Search URL. 27731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::PostTask( 28731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::IO, 29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FROM_HERE, 30dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen NewRunnableFunction(PreconnectOnIOThread, url, motivation, 31201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch count)); 323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return; 33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 35731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 36dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid PreconnectOnIOThread( 37dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen const GURL& url, 38dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen UrlInfo::ResolutionMotivation motivation, 39dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen int count) { 40ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen net::URLRequestContextGetter* getter = Profile::GetDefaultRequestContext(); 41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!getter) 42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 43731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) { 44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LOG(DFATAL) << "This must be run only on the IO thread."; 45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // We are now commited to doing the async preconnection call. 49dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen UMA_HISTOGRAM_ENUMERATION("Net.PreconnectMotivation", motivation, 503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick UrlInfo::MAX_MOTIVATED); 51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 5272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen net::URLRequestContext* context = getter->GetURLRequestContext(); 53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch net::HttpTransactionFactory* factory = context->http_transaction_factory(); 54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch net::HttpNetworkSession* session = factory->GetSession(); 55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 56dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen net::HttpRequestInfo request_info; 57dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen request_info.url = url; 58dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen request_info.method = "GET"; 59ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen request_info.extra_headers.SetHeader(net::HttpRequestHeaders::kUserAgent, 60ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen context->GetUserAgent(url)); 613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // It almost doesn't matter whether we use net::LOWEST or net::HIGHEST 623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // priority here, as we won't make a request, and will surrender the created 633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // socket to the pool as soon as we can. However, we would like to mark the 643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // speculative socket as such, and IF we use a net::LOWEST priority, and if 653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // a navigation asked for a socket (after us) then it would get our socket, 663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // and we'd get its later-arriving socket, which might make us record that 673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // the speculation didn't help :-/. By using net::HIGHEST, we ensure that 683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // a socket is given to us if "we asked first" and this allows us to mark it 693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // as speculative, and better detect stats (if it gets used). 703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // TODO(jar): histogram to see how often we accidentally use a previously- 713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // unused socket, when a previously used socket was available. 72dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen request_info.priority = net::HIGHEST; 733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Translate the motivation from UrlRequest motivations to HttpRequest 753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // motivations. 76dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen switch (motivation) { 773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick case UrlInfo::OMNIBOX_MOTIVATED: 78dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen request_info.motivation = net::HttpRequestInfo::OMNIBOX_MOTIVATED; 793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick break; 803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick case UrlInfo::LEARNED_REFERAL_MOTIVATED: 81dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen request_info.motivation = net::HttpRequestInfo::PRECONNECT_MOTIVATED; 823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick break; 83ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen case UrlInfo::SELF_REFERAL_MOTIVATED: 843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick case UrlInfo::EARLY_LOAD_MOTIVATED: 85dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen request_info.motivation = net::HttpRequestInfo::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. 94dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen net::SSLConfig ssl_config; 95dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen session->ssl_config_service()->GetSSLConfig(&ssl_config); 963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (session->http_stream_factory()->next_protos()) 97dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen ssl_config.next_protos = *session->http_stream_factory()->next_protos(); 98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 99513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // All preconnects should perform EV certificate verification. 100dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen ssl_config.verify_ev_cert = true; 101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 102dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen net::HttpStreamFactory* http_stream_factory = session->http_stream_factory(); 103dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen http_stream_factory->PreconnectStreams( 104dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen count, request_info, ssl_config, net::BoundNetLog()); 105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 107201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch} // namespace chrome_browser_net 108