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

Side by Side Diff: chrome/browser/local_discovery/privet_url_fetcher.cc

Issue 1417363004: Verify certificate of Privet v3 device (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 1 month 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
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 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 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/local_discovery/privet_url_fetcher.h" 5 #include "chrome/browser/local_discovery/privet_url_fetcher.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/json/json_reader.h" 10 #include "base/json/json_reader.h"
11 #include "base/location.h" 11 #include "base/location.h"
12 #include "base/memory/singleton.h" 12 #include "base/memory/singleton.h"
13 #include "base/rand_util.h" 13 #include "base/rand_util.h"
14 #include "base/single_thread_task_runner.h" 14 #include "base/single_thread_task_runner.h"
15 #include "base/strings/stringprintf.h" 15 #include "base/strings/stringprintf.h"
16 #include "base/thread_task_runner_handle.h" 16 #include "base/thread_task_runner_handle.h"
17 #include "chrome/browser/browser_process.h" 17 #include "chrome/browser/browser_process.h"
18 #include "chrome/browser/local_discovery/privet_constants.h" 18 #include "chrome/browser/local_discovery/privet_constants.h"
19 #include "content/public/browser/browser_thread.h" 19 #include "content/public/browser/browser_thread.h"
20 #include "net/base/load_flags.h" 20 #include "net/base/load_flags.h"
21 #include "net/http/http_status_code.h" 21 #include "net/http/http_status_code.h"
22 #include "net/url_request/url_request_context.h"
22 #include "net/url_request/url_request_status.h" 23 #include "net/url_request/url_request_status.h"
23 24
24 namespace local_discovery { 25 namespace local_discovery {
25 26
26 namespace { 27 namespace {
27 28
28 typedef std::map<std::string, std::string> TokenMap; 29 typedef std::map<std::string, std::string> TokenMap;
29 30
30 struct TokenMapHolder { 31 struct TokenMapHolder {
31 public: 32 public:
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
67 bool PrivetURLFetcher::Delegate::OnRawData(PrivetURLFetcher* fetcher, 68 bool PrivetURLFetcher::Delegate::OnRawData(PrivetURLFetcher* fetcher,
68 bool response_is_file, 69 bool response_is_file,
69 const std::string& data_string, 70 const std::string& data_string,
70 const base::FilePath& data_file) { 71 const base::FilePath& data_file) {
71 return false; 72 return false;
72 } 73 }
73 74
74 PrivetURLFetcher::PrivetURLFetcher( 75 PrivetURLFetcher::PrivetURLFetcher(
75 const GURL& url, 76 const GURL& url,
76 net::URLFetcher::RequestType request_type, 77 net::URLFetcher::RequestType request_type,
77 net::URLRequestContextGetter* request_context, 78 const scoped_refptr<net::URLRequestContextGetter>& context_getter,
78 PrivetURLFetcher::Delegate* delegate) 79 PrivetURLFetcher::Delegate* delegate)
79 : url_(url), 80 : url_(url),
80 request_type_(request_type), 81 request_type_(request_type),
81 request_context_(request_context), 82 context_getter_(context_getter),
82 delegate_(delegate), 83 delegate_(delegate),
84 max_retries_(kPrivetMaxRetries),
83 do_not_retry_on_transient_error_(false), 85 do_not_retry_on_transient_error_(false),
84 send_empty_privet_token_(false), 86 send_empty_privet_token_(false),
85 has_byte_range_(false), 87 has_byte_range_(false),
86 make_response_file_(false), 88 make_response_file_(false),
87 v3_mode_(false), 89 v3_mode_(false),
88 byte_range_start_(0), 90 byte_range_start_(0),
89 byte_range_end_(0), 91 byte_range_end_(0),
90 tries_(0), 92 tries_(0),
91 weak_factory_(this) { 93 weak_factory_(this) {}
92 }
93 94
94 PrivetURLFetcher::~PrivetURLFetcher() { 95 PrivetURLFetcher::~PrivetURLFetcher() {
95 } 96 }
96 97
97 // static 98 // static
98 void PrivetURLFetcher::SetTokenForHost(const std::string& host, 99 void PrivetURLFetcher::SetTokenForHost(const std::string& host,
99 const std::string& token) { 100 const std::string& token) {
100 TokenMapHolder::GetInstance()->map[host] = token; 101 TokenMapHolder::GetInstance()->map[host] = token;
101 } 102 }
102 103
103 // static 104 // static
104 void PrivetURLFetcher::ResetTokenMapForTests() { 105 void PrivetURLFetcher::ResetTokenMapForTests() {
105 TokenMapHolder::GetInstance()->map.clear(); 106 TokenMapHolder::GetInstance()->map.clear();
106 } 107 }
107 108
109 void PrivetURLFetcher::SetMaxRetries(int max_retries) {
110 DCHECK_EQ(tries_, 0);
111 max_retries_ = max_retries;
112 }
113
108 void PrivetURLFetcher::DoNotRetryOnTransientError() { 114 void PrivetURLFetcher::DoNotRetryOnTransientError() {
109 DCHECK(tries_ == 0); 115 DCHECK_EQ(tries_, 0);
110 do_not_retry_on_transient_error_ = true; 116 do_not_retry_on_transient_error_ = true;
111 } 117 }
112 118
113 void PrivetURLFetcher::SendEmptyPrivetToken() { 119 void PrivetURLFetcher::SendEmptyPrivetToken() {
114 DCHECK(tries_ == 0); 120 DCHECK_EQ(tries_, 0);
115 send_empty_privet_token_ = true; 121 send_empty_privet_token_ = true;
116 } 122 }
117 123
118 std::string PrivetURLFetcher::GetPrivetAccessToken() { 124 std::string PrivetURLFetcher::GetPrivetAccessToken() {
119 if (send_empty_privet_token_) { 125 if (send_empty_privet_token_) {
120 return std::string(); 126 return std::string();
121 } 127 }
122 128
123 TokenMapHolder* token_map_holder = TokenMapHolder::GetInstance(); 129 TokenMapHolder* token_map_holder = TokenMapHolder::GetInstance();
124 TokenMap::iterator found = token_map_holder->map.find(GetHostString()); 130 TokenMap::iterator found = token_map_holder->map.find(GetHostString());
125 return found != token_map_holder->map.end() ? found->second : std::string(); 131 return found != token_map_holder->map.end() ? found->second : std::string();
126 } 132 }
127 133
128 std::string PrivetURLFetcher::GetHostString() { 134 std::string PrivetURLFetcher::GetHostString() {
129 return url_.GetOrigin().spec(); 135 return url_.GetOrigin().spec();
130 } 136 }
131 137
132 void PrivetURLFetcher::SaveResponseToFile() { 138 void PrivetURLFetcher::SaveResponseToFile() {
133 DCHECK(tries_ == 0); 139 DCHECK_EQ(tries_, 0);
134 make_response_file_ = true; 140 make_response_file_ = true;
135 } 141 }
136 142
137 void PrivetURLFetcher::V3Mode() { 143 void PrivetURLFetcher::V3Mode() {
138 v3_mode_ = true; 144 v3_mode_ = true;
139 } 145 }
140 146
141 void PrivetURLFetcher::SetByteRange(int start, int end) { 147 void PrivetURLFetcher::SetByteRange(int start, int end) {
142 DCHECK(tries_ == 0); 148 DCHECK_EQ(tries_, 0);
143 byte_range_start_ = start; 149 byte_range_start_ = start;
144 byte_range_end_ = end; 150 byte_range_end_ = end;
145 has_byte_range_ = true; 151 has_byte_range_ = true;
146 } 152 }
147 153
148 void PrivetURLFetcher::Try() { 154 void PrivetURLFetcher::Try() {
149 tries_++; 155 tries_++;
150 if (tries_ < kPrivetMaxRetries) { 156 if (tries_ <= max_retries_) {
157 DVLOG(1) << "Try number: " << tries_;
151 url_fetcher_ = net::URLFetcher::Create(url_, request_type_, this); 158 url_fetcher_ = net::URLFetcher::Create(url_, request_type_, this);
152 // Privet requests are relevant to hosts on local network only. 159 // Privet requests are relevant to hosts on local network only.
153 url_fetcher_->SetLoadFlags(url_fetcher_->GetLoadFlags() | 160 url_fetcher_->SetLoadFlags(
154 net::LOAD_BYPASS_PROXY | 161 url_fetcher_->GetLoadFlags() | net::LOAD_BYPASS_PROXY |
155 net::LOAD_DISABLE_CACHE); 162 net::LOAD_DISABLE_CACHE | net::LOAD_DO_NOT_SEND_COOKIES);
156 url_fetcher_->SetRequestContext(request_context_.get()); 163 url_fetcher_->SetRequestContext(context_getter_.get());
157 164
158 if (v3_mode_) { 165 if (v3_mode_) {
159 url_fetcher_->AddExtraRequestHeader( 166 url_fetcher_->AddExtraRequestHeader(
160 std::string(kPrivetV3AuthTokenHeaderPrefix) + 167 std::string(kPrivetV3AuthTokenHeaderPrefix) +
161 delegate_->GetAuthToken()); 168 delegate_->GetAuthToken());
162 } else { 169 } else {
163 std::string token = GetPrivetAccessToken(); 170 std::string token = GetPrivetAccessToken();
164 171
165 if (token.empty()) 172 if (token.empty())
166 token = kXPrivetEmptyToken; 173 token = kXPrivetEmptyToken;
(...skipping 23 matching lines...) Expand all
190 kuint64max /*length*/, 197 kuint64max /*length*/,
191 content::BrowserThread::GetMessageLoopProxyForThread( 198 content::BrowserThread::GetMessageLoopProxyForThread(
192 content::BrowserThread::FILE)); 199 content::BrowserThread::FILE));
193 } else { 200 } else {
194 url_fetcher_->SetUploadData(upload_content_type_, upload_data_); 201 url_fetcher_->SetUploadData(upload_content_type_, upload_data_);
195 } 202 }
196 } 203 }
197 204
198 url_fetcher_->Start(); 205 url_fetcher_->Start();
199 } else { 206 } else {
200 delegate_->OnError(this, RETRY_ERROR); 207 delegate_->OnError(this, UNKNOWN_ERROR);
201 } 208 }
202 } 209 }
203 210
204 void PrivetURLFetcher::Start() { 211 void PrivetURLFetcher::Start() {
205 DCHECK_EQ(tries_, 0); // We haven't called |Start()| yet. 212 DCHECK_EQ(tries_, 0); // We haven't called |Start()| yet.
206 213
207 if (!send_empty_privet_token_ && !v3_mode_) { 214 if (!send_empty_privet_token_ && !v3_mode_) {
208 std::string privet_access_token; 215 std::string privet_access_token;
209 privet_access_token = GetPrivetAccessToken(); 216 privet_access_token = GetPrivetAccessToken();
210 if (privet_access_token.empty()) { 217 if (privet_access_token.empty()) {
(...skipping 14 matching lines...) Expand all
225 232
226 void PrivetURLFetcher::SetUploadFilePath( 233 void PrivetURLFetcher::SetUploadFilePath(
227 const std::string& upload_content_type, 234 const std::string& upload_content_type,
228 const base::FilePath& upload_file_path) { 235 const base::FilePath& upload_file_path) {
229 DCHECK(upload_data_.empty()); 236 DCHECK(upload_data_.empty());
230 upload_content_type_ = upload_content_type; 237 upload_content_type_ = upload_content_type;
231 upload_file_path_ = upload_file_path; 238 upload_file_path_ = upload_file_path;
232 } 239 }
233 240
234 void PrivetURLFetcher::OnURLFetchComplete(const net::URLFetcher* source) { 241 void PrivetURLFetcher::OnURLFetchComplete(const net::URLFetcher* source) {
235 if (source->GetResponseCode() == net::HTTP_SERVICE_UNAVAILABLE || 242 DVLOG(1) << "Status: " << source->GetStatus().status()
236 source->GetResponseCode() == net::URLFetcher::RESPONSE_CODE_INVALID) { 243 << ", ResponseCode: " << source->GetResponseCode();
244 if (source->GetStatus().status() != net::URLRequestStatus::CANCELED &&
245 (source->GetResponseCode() == net::HTTP_SERVICE_UNAVAILABLE ||
246 source->GetResponseCode() == net::URLFetcher::RESPONSE_CODE_INVALID)) {
237 ScheduleRetry(kPrivetTimeoutOnError); 247 ScheduleRetry(kPrivetTimeoutOnError);
238 return; 248 return;
239 } 249 }
240 250
241 if (!OnURLFetchCompleteDoNotParseData(source)) { 251 if (!OnURLFetchCompleteDoNotParseData(source)) {
242 // Byte ranges should only be used when we're not parsing the data 252 // Byte ranges should only be used when we're not parsing the data
243 // as JSON. 253 // as JSON.
244 DCHECK(!has_byte_range_); 254 DCHECK(!has_byte_range_);
245 255
246 // We should only be saving raw data to a file. 256 // We should only be saving raw data to a file.
247 DCHECK(!make_response_file_); 257 DCHECK(!make_response_file_);
248 258
249 OnURLFetchCompleteParseData(source); 259 OnURLFetchCompleteParseData(source);
250 } 260 }
251 } 261 }
252 262
253 // Note that this function returns "true" in error cases to indicate 263 // Note that this function returns "true" in error cases to indicate
254 // that it has fully handled the responses. 264 // that it has fully handled the responses.
255 bool PrivetURLFetcher::OnURLFetchCompleteDoNotParseData( 265 bool PrivetURLFetcher::OnURLFetchCompleteDoNotParseData(
256 const net::URLFetcher* source) { 266 const net::URLFetcher* source) {
267 if (source->GetStatus().status() == net::URLRequestStatus::CANCELED) {
268 delegate_->OnError(this, REQUEST_CANCELED);
269 return true;
270 }
271
257 if (source->GetResponseCode() == kHTTPErrorCodeInvalidXPrivetToken) { 272 if (source->GetResponseCode() == kHTTPErrorCodeInvalidXPrivetToken) {
258 RequestTokenRefresh(); 273 RequestTokenRefresh();
259 return true; 274 return true;
260 } 275 }
261 276
262 if (source->GetResponseCode() != net::HTTP_OK && 277 if (source->GetResponseCode() != net::HTTP_OK &&
263 source->GetResponseCode() != net::HTTP_PARTIAL_CONTENT && 278 source->GetResponseCode() != net::HTTP_PARTIAL_CONTENT &&
264 source->GetResponseCode() != net::HTTP_BAD_REQUEST) { 279 source->GetResponseCode() != net::HTTP_BAD_REQUEST) {
265 delegate_->OnError(this, RESPONSE_CODE_ERROR); 280 delegate_->OnError(this, RESPONSE_CODE_ERROR);
266 return true; 281 return true;
267 } 282 }
268 283
269 if (make_response_file_) { 284 if (make_response_file_) {
270 base::FilePath response_file_path; 285 base::FilePath response_file_path;
271 286
272 if (!source->GetResponseAsFilePath(true, &response_file_path)) { 287 if (!source->GetResponseAsFilePath(true, &response_file_path)) {
273 delegate_->OnError(this, URL_FETCH_ERROR); 288 delegate_->OnError(this, UNKNOWN_ERROR);
274 return true; 289 return true;
275 } 290 }
276 291
277 return delegate_->OnRawData(this, true, std::string(), response_file_path); 292 return delegate_->OnRawData(this, true, std::string(), response_file_path);
278 } else { 293 } else {
279 std::string response_str; 294 std::string response_str;
280 295
281 if (!source->GetResponseAsString(&response_str)) { 296 if (!source->GetResponseAsString(&response_str)) {
282 delegate_->OnError(this, URL_FETCH_ERROR); 297 delegate_->OnError(this, UNKNOWN_ERROR);
283 return true; 298 return true;
284 } 299 }
285 300
286 return delegate_->OnRawData(this, false, response_str, base::FilePath()); 301 return delegate_->OnRawData(this, false, response_str, base::FilePath());
287 } 302 }
288 } 303 }
289 304
290 void PrivetURLFetcher::OnURLFetchCompleteParseData( 305 void PrivetURLFetcher::OnURLFetchCompleteParseData(
291 const net::URLFetcher* source) { 306 const net::URLFetcher* source) {
292 // Response contains error description. 307 // Response contains error description.
293 bool is_error_response = false; 308 bool is_error_response = false;
294 if (v3_mode_ && source->GetResponseCode() == net::HTTP_BAD_REQUEST) { 309 if (v3_mode_ && source->GetResponseCode() == net::HTTP_BAD_REQUEST) {
295 is_error_response = true; 310 is_error_response = true;
296 } else if (source->GetResponseCode() != net::HTTP_OK) { 311 } else if (source->GetResponseCode() != net::HTTP_OK) {
297 delegate_->OnError(this, RESPONSE_CODE_ERROR); 312 delegate_->OnError(this, RESPONSE_CODE_ERROR);
298 return; 313 return;
299 } 314 }
300 315
301 std::string response_str; 316 std::string response_str;
302 if (!source->GetResponseAsString(&response_str)) { 317 if (!source->GetResponseAsString(&response_str)) {
303 delegate_->OnError(this, URL_FETCH_ERROR); 318 delegate_->OnError(this, UNKNOWN_ERROR);
304 return; 319 return;
305 } 320 }
306 321
307 base::JSONReader json_reader(base::JSON_ALLOW_TRAILING_COMMAS); 322 base::JSONReader json_reader(base::JSON_ALLOW_TRAILING_COMMAS);
308 scoped_ptr<base::Value> value = json_reader.ReadToValue(response_str); 323 scoped_ptr<base::Value> value = json_reader.ReadToValue(response_str);
309 if (!value) { 324 if (!value) {
310 delegate_->OnError(this, JSON_PARSE_ERROR); 325 delegate_->OnError(this, JSON_PARSE_ERROR);
311 return; 326 return;
312 } 327 }
313 328
(...skipping 30 matching lines...) Expand all
344 void PrivetURLFetcher::ScheduleRetry(int timeout_seconds) { 359 void PrivetURLFetcher::ScheduleRetry(int timeout_seconds) {
345 double random_scaling_factor = 360 double random_scaling_factor =
346 1 + base::RandDouble() * kPrivetMaximumTimeRandomAddition; 361 1 + base::RandDouble() * kPrivetMaximumTimeRandomAddition;
347 362
348 int timeout_seconds_randomized = 363 int timeout_seconds_randomized =
349 static_cast<int>(timeout_seconds * random_scaling_factor); 364 static_cast<int>(timeout_seconds * random_scaling_factor);
350 365
351 timeout_seconds_randomized = 366 timeout_seconds_randomized =
352 std::max(timeout_seconds_randomized, kPrivetMinimumTimeout); 367 std::max(timeout_seconds_randomized, kPrivetMinimumTimeout);
353 368
369 // Don't wait because only error callback is going to be called.
370 if (tries_ >= max_retries_)
371 timeout_seconds_randomized = 0;
372
354 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( 373 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
355 FROM_HERE, base::Bind(&PrivetURLFetcher::Try, weak_factory_.GetWeakPtr()), 374 FROM_HERE, base::Bind(&PrivetURLFetcher::Try, weak_factory_.GetWeakPtr()),
356 base::TimeDelta::FromSeconds(timeout_seconds_randomized)); 375 base::TimeDelta::FromSeconds(timeout_seconds_randomized));
357 } 376 }
358 377
359 void PrivetURLFetcher::RequestTokenRefresh() { 378 void PrivetURLFetcher::RequestTokenRefresh() {
360 delegate_->OnNeedPrivetToken( 379 delegate_->OnNeedPrivetToken(
361 this, 380 this,
362 base::Bind(&PrivetURLFetcher::RefreshToken, weak_factory_.GetWeakPtr())); 381 base::Bind(&PrivetURLFetcher::RefreshToken, weak_factory_.GetWeakPtr()));
363 } 382 }
364 383
365 void PrivetURLFetcher::RefreshToken(const std::string& token) { 384 void PrivetURLFetcher::RefreshToken(const std::string& token) {
366 if (token.empty()) { 385 if (token.empty()) {
367 delegate_->OnError(this, TOKEN_ERROR); 386 delegate_->OnError(this, TOKEN_ERROR);
368 } else { 387 } else {
369 SetTokenForHost(GetHostString(), token); 388 SetTokenForHost(GetHostString(), token);
370 Try(); 389 Try();
371 } 390 }
372 } 391 }
373 392
374 bool PrivetURLFetcher::PrivetErrorTransient(const std::string& error) { 393 bool PrivetURLFetcher::PrivetErrorTransient(const std::string& error) {
375 return (error == kPrivetErrorDeviceBusy) || 394 return (error == kPrivetErrorDeviceBusy) ||
376 (error == kPrivetV3ErrorDeviceBusy) || 395 (error == kPrivetV3ErrorDeviceBusy) ||
377 (error == kPrivetErrorPendingUserAction) || 396 (error == kPrivetErrorPendingUserAction) ||
378 (error == kPrivetErrorPrinterBusy); 397 (error == kPrivetErrorPrinterBusy);
379 } 398 }
380 399
381 } // namespace local_discovery 400 } // namespace local_discovery
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698