Chromium Code Reviews| 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 "chrome/browser/browser_process.h" | 14 #include "chrome/browser/browser_process.h" |
| 14 #include "chrome/browser/local_discovery/privet_constants.h" | 15 #include "chrome/browser/local_discovery/privet_constants.h" |
| 15 #include "content/public/browser/browser_thread.h" | 16 #include "content/public/browser/browser_thread.h" |
| 16 #include "net/http/http_status_code.h" | 17 #include "net/http/http_status_code.h" |
| 17 #include "net/url_request/url_request_status.h" | 18 #include "net/url_request/url_request_status.h" |
| 18 | 19 |
| 19 namespace local_discovery { | 20 namespace local_discovery { |
| 20 | 21 |
| 21 namespace { | 22 namespace { |
| 23 | |
| 24 typedef std::map<std::string, std::string> TokenMap; | |
| 25 | |
| 26 struct TokenMapHolder { | |
| 27 public: | |
| 28 static TokenMapHolder* GetInstance() { | |
| 29 return Singleton<TokenMapHolder>::get(); | |
| 30 } | |
| 31 | |
| 32 TokenMap map; | |
| 33 }; | |
| 34 | |
| 22 const char kXPrivetTokenHeaderPrefix[] = "X-Privet-Token: "; | 35 const char kXPrivetTokenHeaderPrefix[] = "X-Privet-Token: "; |
| 23 const char kXPrivetEmptyToken[] = "\"\""; | 36 const char kXPrivetEmptyToken[] = "\"\""; |
| 24 const int kPrivetMaxRetries = 20; | 37 const int kPrivetMaxRetries = 20; |
| 25 const int kPrivetTimeoutOnError = 5; | 38 const int kPrivetTimeoutOnError = 5; |
| 26 } | 39 |
| 40 } // namespace | |
| 27 | 41 |
| 28 void PrivetURLFetcher::Delegate::OnNeedPrivetToken( | 42 void PrivetURLFetcher::Delegate::OnNeedPrivetToken( |
| 29 PrivetURLFetcher* fetcher, | 43 PrivetURLFetcher* fetcher, |
| 30 const TokenCallback& callback) { | 44 const TokenCallback& callback) { |
| 31 OnError(fetcher, TOKEN_ERROR); | 45 OnError(fetcher, TOKEN_ERROR); |
| 32 } | 46 } |
| 33 | 47 |
| 34 PrivetURLFetcher::PrivetURLFetcher( | 48 PrivetURLFetcher::PrivetURLFetcher( |
| 35 const std::string& token, | |
| 36 const GURL& url, | 49 const GURL& url, |
| 37 net::URLFetcher::RequestType request_type, | 50 net::URLFetcher::RequestType request_type, |
| 38 net::URLRequestContextGetter* request_context, | 51 net::URLRequestContextGetter* request_context, |
| 39 PrivetURLFetcher::Delegate* delegate) | 52 PrivetURLFetcher::Delegate* delegate) |
| 40 : privet_access_token_(token), url_(url), request_type_(request_type), | 53 : url_(url), request_type_(request_type), |
| 41 request_context_(request_context), delegate_(delegate), | 54 request_context_(request_context), delegate_(delegate), |
| 42 do_not_retry_on_transient_error_(false), allow_empty_privet_token_(false), | 55 do_not_retry_on_transient_error_(false), allow_empty_privet_token_(false), |
| 43 tries_(0), weak_factory_(this) { | 56 tries_(0), weak_factory_(this) { |
| 44 } | 57 } |
| 45 | 58 |
| 46 PrivetURLFetcher::~PrivetURLFetcher() { | 59 PrivetURLFetcher::~PrivetURLFetcher() { |
| 47 } | 60 } |
| 48 | 61 |
| 62 // static | |
| 63 void PrivetURLFetcher::SetTokenForHost(const std::string& host, | |
| 64 const std::string& token) { | |
| 65 TokenMapHolder::GetInstance()->map[host] = token; | |
| 66 } | |
| 67 | |
| 68 // static | |
| 69 void PrivetURLFetcher::ResetTokenMapForTests() { | |
| 70 TokenMapHolder::GetInstance()->map.clear(); | |
| 71 } | |
| 72 | |
| 49 void PrivetURLFetcher::DoNotRetryOnTransientError() { | 73 void PrivetURLFetcher::DoNotRetryOnTransientError() { |
| 50 do_not_retry_on_transient_error_ = true; | 74 do_not_retry_on_transient_error_ = true; |
| 51 } | 75 } |
| 52 | 76 |
| 53 void PrivetURLFetcher::AllowEmptyPrivetToken() { | 77 void PrivetURLFetcher::AllowEmptyPrivetToken() { |
| 54 allow_empty_privet_token_ = true; | 78 allow_empty_privet_token_ = true; |
| 55 } | 79 } |
| 56 | 80 |
| 81 std::string PrivetURLFetcher::GetPrivetAccessToken() { | |
| 82 TokenMapHolder* token_map_holder = TokenMapHolder::GetInstance(); | |
| 83 TokenMap::iterator found = token_map_holder->map.find(GetHostString()); | |
| 84 if (found != token_map_holder->map.end()) { | |
|
Vitaly Buka (NO REVIEWS)
2014/02/14 23:34:12
return found != token_map_holder->map.end() ? foun
Noam Samuel
2014/02/15 00:22:15
Done.
| |
| 85 return found->second; | |
| 86 } else { | |
| 87 return std::string(); | |
| 88 } | |
| 89 } | |
| 90 | |
| 91 std::string PrivetURLFetcher::GetHostString() { | |
| 92 return url_.GetOrigin().spec(); | |
| 93 } | |
| 94 | |
| 57 void PrivetURLFetcher::Try() { | 95 void PrivetURLFetcher::Try() { |
| 58 tries_++; | 96 tries_++; |
| 59 if (tries_ < kPrivetMaxRetries) { | 97 if (tries_ < kPrivetMaxRetries) { |
| 60 std::string token = privet_access_token_; | 98 std::string token = GetPrivetAccessToken(); |
| 61 | 99 |
| 62 if (token.empty()) | 100 if (token.empty()) |
| 63 token = kXPrivetEmptyToken; | 101 token = kXPrivetEmptyToken; |
| 64 | 102 |
| 65 url_fetcher_.reset(net::URLFetcher::Create(url_, request_type_, this)); | 103 url_fetcher_.reset(net::URLFetcher::Create(url_, request_type_, this)); |
| 66 url_fetcher_->SetRequestContext(request_context_); | 104 url_fetcher_->SetRequestContext(request_context_); |
| 67 url_fetcher_->AddExtraRequestHeader(std::string(kXPrivetTokenHeaderPrefix) + | 105 url_fetcher_->AddExtraRequestHeader(std::string(kXPrivetTokenHeaderPrefix) + |
| 68 token); | 106 token); |
| 69 | 107 |
| 70 // URLFetcher requires us to set upload data for POST requests. | 108 // URLFetcher requires us to set upload data for POST requests. |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 84 | 122 |
| 85 url_fetcher_->Start(); | 123 url_fetcher_->Start(); |
| 86 } else { | 124 } else { |
| 87 delegate_->OnError(this, RETRY_ERROR); | 125 delegate_->OnError(this, RETRY_ERROR); |
| 88 } | 126 } |
| 89 } | 127 } |
| 90 | 128 |
| 91 void PrivetURLFetcher::Start() { | 129 void PrivetURLFetcher::Start() { |
| 92 DCHECK_EQ(tries_, 0); // We haven't called |Start()| yet. | 130 DCHECK_EQ(tries_, 0); // We haven't called |Start()| yet. |
| 93 | 131 |
| 94 if (privet_access_token_.empty() && !allow_empty_privet_token_) { | 132 std::string privet_access_token = GetPrivetAccessToken(); |
| 133 if (privet_access_token.empty() && !allow_empty_privet_token_) { | |
| 95 RequestTokenRefresh(); | 134 RequestTokenRefresh(); |
| 96 } else { | 135 } else { |
| 97 Try(); | 136 Try(); |
| 98 } | 137 } |
| 99 } | 138 } |
| 100 | 139 |
| 101 void PrivetURLFetcher::SetUploadData(const std::string& upload_content_type, | 140 void PrivetURLFetcher::SetUploadData(const std::string& upload_content_type, |
| 102 const std::string& upload_data) { | 141 const std::string& upload_data) { |
| 103 DCHECK(upload_file_path_.empty()); | 142 DCHECK(upload_file_path_.empty()); |
| 104 upload_content_type_ = upload_content_type; | 143 upload_content_type_ = upload_content_type; |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 190 void PrivetURLFetcher::RequestTokenRefresh() { | 229 void PrivetURLFetcher::RequestTokenRefresh() { |
| 191 delegate_->OnNeedPrivetToken( | 230 delegate_->OnNeedPrivetToken( |
| 192 this, | 231 this, |
| 193 base::Bind(&PrivetURLFetcher::RefreshToken, weak_factory_.GetWeakPtr())); | 232 base::Bind(&PrivetURLFetcher::RefreshToken, weak_factory_.GetWeakPtr())); |
| 194 } | 233 } |
| 195 | 234 |
| 196 void PrivetURLFetcher::RefreshToken(const std::string& token) { | 235 void PrivetURLFetcher::RefreshToken(const std::string& token) { |
| 197 if (token.empty()) { | 236 if (token.empty()) { |
| 198 delegate_->OnError(this, TOKEN_ERROR); | 237 delegate_->OnError(this, TOKEN_ERROR); |
| 199 } else { | 238 } else { |
| 200 privet_access_token_ = token; | 239 SetTokenForHost(GetHostString(), token); |
| 201 Try(); | 240 Try(); |
| 202 } | 241 } |
| 203 } | 242 } |
| 204 | 243 |
| 205 bool PrivetURLFetcher::PrivetErrorTransient(const std::string& error) { | 244 bool PrivetURLFetcher::PrivetErrorTransient(const std::string& error) { |
| 206 return (error == kPrivetErrorDeviceBusy) || | 245 return (error == kPrivetErrorDeviceBusy) || |
| 207 (error == kPrivetErrorPendingUserAction) || | 246 (error == kPrivetErrorPendingUserAction) || |
| 208 (error == kPrivetErrorPrinterBusy); | 247 (error == kPrivetErrorPrinterBusy); |
| 209 } | 248 } |
| 210 | 249 |
| 211 PrivetURLFetcherFactory::PrivetURLFetcherFactory( | |
| 212 net::URLRequestContextGetter* request_context) | |
| 213 : request_context_(request_context) { | |
| 214 } | |
| 215 | |
| 216 PrivetURLFetcherFactory::~PrivetURLFetcherFactory() { | |
| 217 } | |
| 218 | |
| 219 scoped_ptr<PrivetURLFetcher> PrivetURLFetcherFactory::CreateURLFetcher( | |
| 220 const GURL& url, net::URLFetcher::RequestType request_type, | |
| 221 PrivetURLFetcher::Delegate* delegate) const { | |
| 222 return scoped_ptr<PrivetURLFetcher>( | |
| 223 new PrivetURLFetcher(token_, url, request_type, request_context_.get(), | |
| 224 delegate)); | |
| 225 } | |
| 226 | |
| 227 } // namespace local_discovery | 250 } // namespace local_discovery |
| OLD | NEW |