| 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 |