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