OLD | NEW |
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/memory/singleton.h" |
11 #include "base/message_loop/message_loop.h" | 12 #include "base/message_loop/message_loop.h" |
12 #include "base/rand_util.h" | 13 #include "base/rand_util.h" |
13 #include "base/strings/stringprintf.h" | 14 #include "base/strings/stringprintf.h" |
14 #include "chrome/browser/browser_process.h" | 15 #include "chrome/browser/browser_process.h" |
15 #include "chrome/browser/local_discovery/privet_constants.h" | 16 #include "chrome/browser/local_discovery/privet_constants.h" |
16 #include "content/public/browser/browser_thread.h" | 17 #include "content/public/browser/browser_thread.h" |
17 #include "net/http/http_status_code.h" | 18 #include "net/http/http_status_code.h" |
18 #include "net/url_request/url_request_status.h" | 19 #include "net/url_request/url_request_status.h" |
19 | 20 |
20 namespace local_discovery { | 21 namespace local_discovery { |
21 | 22 |
22 namespace { | 23 namespace { |
| 24 |
| 25 typedef std::map<std::string, std::string> TokenMap; |
| 26 |
| 27 struct TokenMapHolder { |
| 28 public: |
| 29 static TokenMapHolder* GetInstance() { |
| 30 return Singleton<TokenMapHolder>::get(); |
| 31 } |
| 32 |
| 33 TokenMap map; |
| 34 }; |
| 35 |
23 const char kXPrivetTokenHeaderPrefix[] = "X-Privet-Token: "; | 36 const char kXPrivetTokenHeaderPrefix[] = "X-Privet-Token: "; |
24 const char kRangeHeaderFormat[] = "Range: bytes=%d-%d"; | 37 const char kRangeHeaderFormat[] = "Range: bytes=%d-%d"; |
25 const char kXPrivetEmptyToken[] = "\"\""; | 38 const char kXPrivetEmptyToken[] = "\"\""; |
26 const int kPrivetMaxRetries = 20; | 39 const int kPrivetMaxRetries = 20; |
27 const int kPrivetTimeoutOnError = 5; | 40 const int kPrivetTimeoutOnError = 5; |
28 const int kHTTPErrorCodeInvalidXPrivetToken = 418; | 41 const int kHTTPErrorCodeInvalidXPrivetToken = 418; |
29 | 42 |
30 std::string MakeRangeHeader(int start, int end) { | 43 std::string MakeRangeHeader(int start, int end) { |
31 DCHECK_GE(start, 0); | 44 DCHECK_GE(start, 0); |
32 DCHECK_GT(end, 0); | 45 DCHECK_GT(end, 0); |
(...skipping 10 matching lines...) Expand all Loading... |
43 } | 56 } |
44 | 57 |
45 bool PrivetURLFetcher::Delegate::OnRawData(PrivetURLFetcher* fetcher, | 58 bool PrivetURLFetcher::Delegate::OnRawData(PrivetURLFetcher* fetcher, |
46 bool response_is_file, | 59 bool response_is_file, |
47 const std::string& data_string, | 60 const std::string& data_string, |
48 const base::FilePath& data_file) { | 61 const base::FilePath& data_file) { |
49 return false; | 62 return false; |
50 } | 63 } |
51 | 64 |
52 PrivetURLFetcher::PrivetURLFetcher( | 65 PrivetURLFetcher::PrivetURLFetcher( |
53 const std::string& token, | |
54 const GURL& url, | 66 const GURL& url, |
55 net::URLFetcher::RequestType request_type, | 67 net::URLFetcher::RequestType request_type, |
56 net::URLRequestContextGetter* request_context, | 68 net::URLRequestContextGetter* request_context, |
57 PrivetURLFetcher::Delegate* delegate) | 69 PrivetURLFetcher::Delegate* delegate) |
58 : privet_access_token_(token), | 70 : url_(url), |
59 url_(url), | |
60 request_type_(request_type), | 71 request_type_(request_type), |
61 request_context_(request_context), | 72 request_context_(request_context), |
62 delegate_(delegate), | 73 delegate_(delegate), |
63 do_not_retry_on_transient_error_(false), | 74 do_not_retry_on_transient_error_(false), |
64 allow_empty_privet_token_(false), | 75 allow_empty_privet_token_(false), |
65 has_byte_range_(false), | 76 has_byte_range_(false), |
66 make_response_file_(false), | 77 make_response_file_(false), |
67 byte_range_start_(0), | 78 byte_range_start_(0), |
68 byte_range_end_(0), | 79 byte_range_end_(0), |
69 tries_(0), | 80 tries_(0), |
70 weak_factory_(this) { | 81 weak_factory_(this) {} |
| 82 |
| 83 PrivetURLFetcher::~PrivetURLFetcher() { |
71 } | 84 } |
72 | 85 |
73 PrivetURLFetcher::~PrivetURLFetcher() { | 86 // static |
| 87 void PrivetURLFetcher::SetTokenForHost(const std::string& host, |
| 88 const std::string& token) { |
| 89 TokenMapHolder::GetInstance()->map[host] = token; |
| 90 } |
| 91 |
| 92 // static |
| 93 void PrivetURLFetcher::ResetTokenMapForTests() { |
| 94 TokenMapHolder::GetInstance()->map.clear(); |
74 } | 95 } |
75 | 96 |
76 void PrivetURLFetcher::DoNotRetryOnTransientError() { | 97 void PrivetURLFetcher::DoNotRetryOnTransientError() { |
77 DCHECK(tries_ == 0); | 98 DCHECK(tries_ == 0); |
78 do_not_retry_on_transient_error_ = true; | 99 do_not_retry_on_transient_error_ = true; |
79 } | 100 } |
80 | 101 |
81 void PrivetURLFetcher::AllowEmptyPrivetToken() { | 102 void PrivetURLFetcher::AllowEmptyPrivetToken() { |
82 DCHECK(tries_ == 0); | 103 DCHECK(tries_ == 0); |
83 allow_empty_privet_token_ = true; | 104 allow_empty_privet_token_ = true; |
84 } | 105 } |
85 | 106 |
| 107 std::string PrivetURLFetcher::GetPrivetAccessToken() { |
| 108 TokenMapHolder* token_map_holder = TokenMapHolder::GetInstance(); |
| 109 TokenMap::iterator found = token_map_holder->map.find(GetHostString()); |
| 110 return found != token_map_holder->map.end() ? found->second : std::string(); |
| 111 } |
| 112 |
| 113 std::string PrivetURLFetcher::GetHostString() { |
| 114 return url_.GetOrigin().spec(); |
| 115 } |
| 116 |
86 void PrivetURLFetcher::SaveResponseToFile() { | 117 void PrivetURLFetcher::SaveResponseToFile() { |
87 DCHECK(tries_ == 0); | 118 DCHECK(tries_ == 0); |
88 make_response_file_ = true; | 119 make_response_file_ = true; |
89 } | 120 } |
90 | 121 |
91 void PrivetURLFetcher::SetByteRange(int start, int end) { | 122 void PrivetURLFetcher::SetByteRange(int start, int end) { |
92 DCHECK(tries_ == 0); | 123 DCHECK(tries_ == 0); |
93 byte_range_start_ = start; | 124 byte_range_start_ = start; |
94 byte_range_end_ = end; | 125 byte_range_end_ = end; |
95 has_byte_range_ = true; | 126 has_byte_range_ = true; |
96 } | 127 } |
97 | 128 |
98 void PrivetURLFetcher::Try() { | 129 void PrivetURLFetcher::Try() { |
99 tries_++; | 130 tries_++; |
100 if (tries_ < kPrivetMaxRetries) { | 131 if (tries_ < kPrivetMaxRetries) { |
101 std::string token = privet_access_token_; | 132 std::string token = GetPrivetAccessToken(); |
102 | 133 |
103 if (token.empty()) | 134 if (token.empty()) |
104 token = kXPrivetEmptyToken; | 135 token = kXPrivetEmptyToken; |
105 | 136 |
106 url_fetcher_.reset(net::URLFetcher::Create(url_, request_type_, this)); | 137 url_fetcher_.reset(net::URLFetcher::Create(url_, request_type_, this)); |
107 url_fetcher_->SetRequestContext(request_context_); | 138 url_fetcher_->SetRequestContext(request_context_); |
108 url_fetcher_->AddExtraRequestHeader(std::string(kXPrivetTokenHeaderPrefix) + | 139 url_fetcher_->AddExtraRequestHeader(std::string(kXPrivetTokenHeaderPrefix) + |
109 token); | 140 token); |
110 if (has_byte_range_) { | 141 if (has_byte_range_) { |
111 url_fetcher_->AddExtraRequestHeader( | 142 url_fetcher_->AddExtraRequestHeader( |
(...skipping 23 matching lines...) Expand all Loading... |
135 | 166 |
136 url_fetcher_->Start(); | 167 url_fetcher_->Start(); |
137 } else { | 168 } else { |
138 delegate_->OnError(this, RETRY_ERROR); | 169 delegate_->OnError(this, RETRY_ERROR); |
139 } | 170 } |
140 } | 171 } |
141 | 172 |
142 void PrivetURLFetcher::Start() { | 173 void PrivetURLFetcher::Start() { |
143 DCHECK_EQ(tries_, 0); // We haven't called |Start()| yet. | 174 DCHECK_EQ(tries_, 0); // We haven't called |Start()| yet. |
144 | 175 |
145 if (privet_access_token_.empty() && !allow_empty_privet_token_) { | 176 std::string privet_access_token = GetPrivetAccessToken(); |
| 177 if (privet_access_token.empty() && !allow_empty_privet_token_) { |
146 RequestTokenRefresh(); | 178 RequestTokenRefresh(); |
147 } else { | 179 } else { |
148 Try(); | 180 Try(); |
149 } | 181 } |
150 } | 182 } |
151 | 183 |
152 void PrivetURLFetcher::SetUploadData(const std::string& upload_content_type, | 184 void PrivetURLFetcher::SetUploadData(const std::string& upload_content_type, |
153 const std::string& upload_data) { | 185 const std::string& upload_data) { |
154 DCHECK(upload_file_path_.empty()); | 186 DCHECK(upload_file_path_.empty()); |
155 upload_content_type_ = upload_content_type; | 187 upload_content_type_ = upload_content_type; |
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
291 void PrivetURLFetcher::RequestTokenRefresh() { | 323 void PrivetURLFetcher::RequestTokenRefresh() { |
292 delegate_->OnNeedPrivetToken( | 324 delegate_->OnNeedPrivetToken( |
293 this, | 325 this, |
294 base::Bind(&PrivetURLFetcher::RefreshToken, weak_factory_.GetWeakPtr())); | 326 base::Bind(&PrivetURLFetcher::RefreshToken, weak_factory_.GetWeakPtr())); |
295 } | 327 } |
296 | 328 |
297 void PrivetURLFetcher::RefreshToken(const std::string& token) { | 329 void PrivetURLFetcher::RefreshToken(const std::string& token) { |
298 if (token.empty()) { | 330 if (token.empty()) { |
299 delegate_->OnError(this, TOKEN_ERROR); | 331 delegate_->OnError(this, TOKEN_ERROR); |
300 } else { | 332 } else { |
301 privet_access_token_ = token; | 333 SetTokenForHost(GetHostString(), token); |
302 Try(); | 334 Try(); |
303 } | 335 } |
304 } | 336 } |
305 | 337 |
306 bool PrivetURLFetcher::PrivetErrorTransient(const std::string& error) { | 338 bool PrivetURLFetcher::PrivetErrorTransient(const std::string& error) { |
307 return (error == kPrivetErrorDeviceBusy) || | 339 return (error == kPrivetErrorDeviceBusy) || |
308 (error == kPrivetErrorPendingUserAction) || | 340 (error == kPrivetErrorPendingUserAction) || |
309 (error == kPrivetErrorPrinterBusy); | 341 (error == kPrivetErrorPrinterBusy); |
310 } | 342 } |
311 | 343 |
312 PrivetURLFetcherFactory::PrivetURLFetcherFactory( | |
313 net::URLRequestContextGetter* request_context) | |
314 : request_context_(request_context) { | |
315 } | |
316 | |
317 PrivetURLFetcherFactory::~PrivetURLFetcherFactory() { | |
318 } | |
319 | |
320 scoped_ptr<PrivetURLFetcher> PrivetURLFetcherFactory::CreateURLFetcher( | |
321 const GURL& url, net::URLFetcher::RequestType request_type, | |
322 PrivetURLFetcher::Delegate* delegate) const { | |
323 return scoped_ptr<PrivetURLFetcher>( | |
324 new PrivetURLFetcher(token_, url, request_type, request_context_.get(), | |
325 delegate)); | |
326 } | |
327 | |
328 } // namespace local_discovery | 344 } // namespace local_discovery |
OLD | NEW |