proxy_advisor.cc revision a02191e04bc25c4935f804f2c080ae28663d096d
1// Copyright 2013 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "chrome/browser/net/spdyproxy/proxy_advisor.h" 6 7#include "base/command_line.h" 8#include "base/logging.h" 9#include "base/memory/scoped_ptr.h" 10#include "base/prefs/pref_service.h" 11#include "base/stl_util.h" 12#include "chrome/common/chrome_switches.h" 13#include "chrome/common/pref_names.h" 14#include "components/data_reduction_proxy/browser/data_reduction_proxy_settings.h" 15#include "content/public/browser/browser_thread.h" 16#include "net/base/load_flags.h" 17#include "net/base/request_priority.h" 18#include "net/http/http_status_code.h" 19#include "net/proxy/proxy_info.h" 20#include "net/proxy/proxy_service.h" 21#include "net/url_request/url_request_context.h" 22#include "net/url_request/url_request_context_getter.h" 23 24// Ensure data reduction features are available. 25#if !defined(OS_ANDROID) && !defined(OS_IOS) 26#error proxy_advisor should only be included in Android or iOS builds. 27#endif 28 29using content::BrowserThread; 30using data_reduction_proxy::DataReductionProxySettings; 31 32namespace { 33const char kOmniboxMotivation[] = "omnibox"; 34const char kLowThresholdOmniboxMotivation[] = "low_threshold_omnibox"; 35const char kStartupDNSMotivation[] = "startup_dns"; 36const char kEarlyLoadMotivation[] = "early_load"; 37const char kLearnedReferralMotivation[] = "learned_referral"; 38const char kLowThresholdLearnedReferralMotivation[] = 39 "low_threshold_learned_referral"; 40const char kSelfReferralMotivation[] = "self_referral"; 41const char kPageScanMotivation[] = "page_scan"; 42 43// Maps a ResolutionMotivation to a string for use in the advisory HEAD 44// request. 45const char* MotivationName( 46 chrome_browser_net::UrlInfo::ResolutionMotivation motivation, 47 bool is_preconnect) { 48 switch (motivation) { 49 case chrome_browser_net::UrlInfo::OMNIBOX_MOTIVATED: 50 return 51 is_preconnect ? kOmniboxMotivation : kLowThresholdOmniboxMotivation; 52 case chrome_browser_net::UrlInfo::STARTUP_LIST_MOTIVATED: 53 return kStartupDNSMotivation; 54 case chrome_browser_net::UrlInfo::EARLY_LOAD_MOTIVATED: 55 return kEarlyLoadMotivation; 56 case chrome_browser_net::UrlInfo::LEARNED_REFERAL_MOTIVATED: 57 return is_preconnect ? 58 kLearnedReferralMotivation : kLowThresholdLearnedReferralMotivation; 59 case chrome_browser_net::UrlInfo::SELF_REFERAL_MOTIVATED: 60 return kSelfReferralMotivation; 61 case chrome_browser_net::UrlInfo::PAGE_SCAN_MOTIVATED: 62 return kPageScanMotivation; 63 default: 64 // Other motivations should never be passed to here. 65 NOTREACHED(); 66 break; 67 } 68 NOTREACHED(); 69 return ""; 70} 71 72} // namespace 73 74ProxyAdvisor::ProxyAdvisor(PrefService* pref_service, 75 net::URLRequestContextGetter* context_getter) 76 : context_getter_(context_getter) { 77 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 78 79 // pref_service may be null in mock test subclasses. 80 if (pref_service) { 81 proxy_pref_member_.Init( 82 data_reduction_proxy::prefs::kDataReductionProxyEnabled, 83 pref_service, 84 base::Bind(&ProxyAdvisor::UpdateProxyState, base::Unretained(this))); 85 proxy_pref_member_.MoveToThread( 86 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO)); 87 } 88} 89 90ProxyAdvisor::~ProxyAdvisor() { 91 STLDeleteElements(&inflight_requests_); 92} 93 94void ProxyAdvisor::OnResponseStarted(net::URLRequest* request) { 95 const net::URLRequestStatus& status(request->status()); 96 if (!status.is_success()) { 97 DLOG(WARNING) << "Proxy advisory failed " 98 << "status:" << status.status() 99 << " error:" << status.error(); 100 } else if (request->GetResponseCode() != net::HTTP_OK) { 101 DLOG(WARNING) << "Proxy advisory status: " << request->GetResponseCode(); 102 } 103 RequestComplete(request); 104} 105 106void ProxyAdvisor::OnReadCompleted(net::URLRequest* request, int bytes_read) { 107 // No-op for now, as we don't care yet. 108} 109 110void ProxyAdvisor::Advise( 111 const GURL& url, 112 chrome_browser_net::UrlInfo::ResolutionMotivation motivation, 113 bool is_preconnect) { 114 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 115 116 if (!WouldProxyURL(url)) 117 return; 118 119 std::string motivation_name(MotivationName(motivation, is_preconnect)); 120 std::string header_value = motivation_name + " " + url.spec(); 121 net::URLRequestContext* context = context_getter_->GetURLRequestContext(); 122 std::string endpoint = 123 DataReductionProxySettings::GetDataReductionProxyOrigin() + "preconnect"; 124 scoped_ptr<net::URLRequest> request = context->CreateRequest( 125 GURL(endpoint), net::DEFAULT_PRIORITY, this, NULL); 126 request->set_method("HEAD"); 127 request->SetExtraRequestHeaderByName( 128 "Proxy-Host-Advisory", header_value, false); 129 request->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES | 130 net::LOAD_DO_NOT_SAVE_COOKIES | 131 net::LOAD_BYPASS_PROXY | 132 net::LOAD_DISABLE_CACHE); 133 net::URLRequest* raw_request = request.get(); 134 inflight_requests_.insert(request.release()); 135 raw_request->Start(); 136} 137 138// TODO(marq): Move this into DataReductionProxySettings, and add support for 139// inspecting the current proxy configs -- if ResolveProxy on |url| can be 140// done synchronously, then this is no longer an approximation. 141bool ProxyAdvisor::WouldProxyURL(const GURL& url) { 142 if (!proxy_pref_member_.GetValue()) 143 return false; 144 145 if (url.SchemeIsSecure()) 146 return false; 147 148 return true; 149} 150 151void ProxyAdvisor::RequestComplete(net::URLRequest* request) { 152 DCHECK_EQ(1u, inflight_requests_.count(request)); 153 scoped_ptr<net::URLRequest> scoped_request_for_deletion(request); 154 inflight_requests_.erase(request); 155 // |scoped_request_for_deletion| will delete |request| 156} 157 158void ProxyAdvisor::UpdateProxyState() { 159 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 160 // Delete all inflight requests. Each request's destructor will call Cancel(). 161 STLDeleteElements(&inflight_requests_); 162} 163