15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/net/preconnect.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/metrics/histogram.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_thread.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_log.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_network_session.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_request_info.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_stream_factory.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_transaction_factory.h" 162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/ssl/ssl_config_service.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/url_request_context.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/url_request_context_getter.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserThread; 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace chrome_browser_net { 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PreconnectOnUIThread( 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& url, 2690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const GURL& first_party_for_cookies, 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UrlInfo::ResolutionMotivation motivation, 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int count, 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::URLRequestContextGetter* getter) { 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Prewarm connection to Search URL. 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::PostTask( 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::IO, 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 3490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::Bind(&PreconnectOnIOThread, url, first_party_for_cookies, 3590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) motivation, count, make_scoped_refptr(getter))); 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PreconnectOnIOThread( 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& url, 4290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const GURL& first_party_for_cookies, 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UrlInfo::ResolutionMotivation motivation, 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int count, 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::URLRequestContextGetter* getter) { 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) { 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(DFATAL) << "This must be run only on the IO thread."; 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!getter) 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We are now commited to doing the async preconnection call. 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_ENUMERATION("Net.PreconnectMotivation", motivation, 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UrlInfo::MAX_MOTIVATED); 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::URLRequestContext* context = getter->GetURLRequestContext(); 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::HttpTransactionFactory* factory = context->http_transaction_factory(); 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::HttpNetworkSession* session = factory->GetSession(); 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::HttpRequestInfo request_info; 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_info.url = url; 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_info.method = "GET"; 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_info.extra_headers.SetHeader(net::HttpRequestHeaders::kUserAgent, 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) context->GetUserAgent(url)); 6590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 6690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) net::NetworkDelegate* delegate = context->network_delegate(); 6790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (delegate->CanEnablePrivacyMode(url, first_party_for_cookies)) 6890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) request_info.privacy_mode = net::kPrivacyModeEnabled; 6990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // It almost doesn't matter whether we use net::LOWEST or net::HIGHEST 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // priority here, as we won't make a request, and will surrender the created 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // socket to the pool as soon as we can. However, we would like to mark the 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // speculative socket as such, and IF we use a net::LOWEST priority, and if 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // a navigation asked for a socket (after us) then it would get our socket, 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // and we'd get its later-arriving socket, which might make us record that 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the speculation didn't help :-/. By using net::HIGHEST, we ensure that 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // a socket is given to us if "we asked first" and this allows us to mark it 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // as speculative, and better detect stats (if it gets used). 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(jar): histogram to see how often we accidentally use a previously- 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // unused socket, when a previously used socket was available. 812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) net::RequestPriority priority = net::HIGHEST; 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Translate the motivation from UrlRequest motivations to HttpRequest 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // motivations. 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (motivation) { 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case UrlInfo::OMNIBOX_MOTIVATED: 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_info.motivation = net::HttpRequestInfo::OMNIBOX_MOTIVATED; 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case UrlInfo::LEARNED_REFERAL_MOTIVATED: 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_info.motivation = net::HttpRequestInfo::PRECONNECT_MOTIVATED; 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 923240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch case UrlInfo::MOUSE_OVER_MOTIVATED: 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case UrlInfo::SELF_REFERAL_MOTIVATED: 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case UrlInfo::EARLY_LOAD_MOTIVATED: 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_info.motivation = net::HttpRequestInfo::EARLY_LOAD_MOTIVATED; 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Other motivations should never happen here. 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Setup the SSL Configuration. 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::SSLConfig ssl_config; 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) session->ssl_config_service()->GetSSLConfig(&ssl_config); 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (session->http_stream_factory()->has_next_protos()) 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ssl_config.next_protos = session->http_stream_factory()->next_protos(); 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // All preconnects should perform EV certificate verification. 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ssl_config.verify_ev_cert = true; 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::HttpStreamFactory* http_stream_factory = session->http_stream_factory(); 1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) http_stream_factory->PreconnectStreams(count, request_info, priority, 1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ssl_config, ssl_config); 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace chrome_browser_net 118