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/message_loop/message_loop.h" | 11 #include "base/message_loop/message_loop.h" |
12 #include "base/rand_util.h" | 12 #include "base/rand_util.h" |
13 #include "base/strings/stringprintf.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 { |
22 const char kXPrivetTokenHeaderPrefix[] = "X-Privet-Token: "; | 23 const char kXPrivetTokenHeaderPrefix[] = "X-Privet-Token: "; |
24 const char kRangeHeaderFormat[] = "Range: bytes=%d-%d"; | |
23 const char kXPrivetEmptyToken[] = "\"\""; | 25 const char kXPrivetEmptyToken[] = "\"\""; |
24 const int kPrivetMaxRetries = 20; | 26 const int kPrivetMaxRetries = 20; |
25 const int kPrivetTimeoutOnError = 5; | 27 const int kPrivetTimeoutOnError = 5; |
28 const int kHTTPErrorCodeInvalidXPrivetToken = 418; | |
29 | |
30 std::string MakeRangeHeader(int start, int end) { | |
31 DCHECK(start >= 0); | |
Vitaly Buka (NO REVIEWS)
2014/02/07 19:47:39
DCHECK_GT?
Noam Samuel
2014/02/12 20:25:16
Done.
| |
32 DCHECK(end > 0); | |
33 DCHECK(end > start); | |
34 return base::StringPrintf(kRangeHeaderFormat, start, end); | |
26 } | 35 } |
27 | 36 |
37 } // namespace | |
38 | |
28 void PrivetURLFetcher::Delegate::OnNeedPrivetToken( | 39 void PrivetURLFetcher::Delegate::OnNeedPrivetToken( |
29 PrivetURLFetcher* fetcher, | 40 PrivetURLFetcher* fetcher, |
30 const TokenCallback& callback) { | 41 const TokenCallback& callback) { |
31 OnError(fetcher, TOKEN_ERROR); | 42 OnError(fetcher, TOKEN_ERROR); |
32 } | 43 } |
33 | 44 |
34 PrivetURLFetcher::PrivetURLFetcher( | 45 PrivetURLFetcher::PrivetURLFetcher( |
35 const std::string& token, | 46 const std::string& token, |
36 const GURL& url, | 47 const GURL& url, |
37 net::URLFetcher::RequestType request_type, | 48 net::URLFetcher::RequestType request_type, |
38 net::URLRequestContextGetter* request_context, | 49 net::URLRequestContextGetter* request_context, |
39 PrivetURLFetcher::Delegate* delegate) | 50 PrivetURLFetcher::Delegate* delegate) |
40 : privet_access_token_(token), url_(url), request_type_(request_type), | 51 : privet_access_token_(token), url_(url), request_type_(request_type), |
Vitaly Buka (NO REVIEWS)
2014/02/07 19:47:39
one per line might be more readable.
Noam Samuel
2014/02/12 20:25:16
Done.
| |
41 request_context_(request_context), delegate_(delegate), | 52 request_context_(request_context), delegate_(delegate), |
42 do_not_retry_on_transient_error_(false), allow_empty_privet_token_(false), | 53 do_not_retry_on_transient_error_(false), allow_empty_privet_token_(false), |
43 tries_(0), weak_factory_(this) { | 54 do_not_parse_data_(false), has_byte_range_(false), |
Vitaly Buka (NO REVIEWS)
2014/02/07 19:47:39
probably do_not_parse_data_ is depends on delegate
Noam Samuel
2014/02/12 20:25:16
Done.
| |
55 make_response_file_(false), byte_range_start_(0), | |
56 byte_range_end_(0), tries_(0), weak_factory_(this) { | |
44 } | 57 } |
45 | 58 |
46 PrivetURLFetcher::~PrivetURLFetcher() { | 59 PrivetURLFetcher::~PrivetURLFetcher() { |
47 } | 60 } |
48 | 61 |
49 void PrivetURLFetcher::DoNotRetryOnTransientError() { | 62 void PrivetURLFetcher::DoNotRetryOnTransientError() { |
63 DCHECK(tries_ == 0); | |
50 do_not_retry_on_transient_error_ = true; | 64 do_not_retry_on_transient_error_ = true; |
51 } | 65 } |
52 | 66 |
53 void PrivetURLFetcher::AllowEmptyPrivetToken() { | 67 void PrivetURLFetcher::AllowEmptyPrivetToken() { |
68 DCHECK(tries_ == 0); | |
54 allow_empty_privet_token_ = true; | 69 allow_empty_privet_token_ = true; |
55 } | 70 } |
56 | 71 |
72 void PrivetURLFetcher::DoNotParseData() { | |
73 DCHECK(tries_ == 0); | |
74 do_not_parse_data_ = true; | |
75 } | |
76 | |
77 void PrivetURLFetcher::SaveResponseToFile() { | |
78 DCHECK(tries_ == 0); | |
79 make_response_file_ = true; | |
80 } | |
81 | |
82 void PrivetURLFetcher::SetByteRange(int start, int end) { | |
83 DCHECK(tries_ == 0); | |
84 byte_range_start_ = start; | |
85 byte_range_end_ = end; | |
86 has_byte_range_ = true; | |
87 } | |
88 | |
57 void PrivetURLFetcher::Try() { | 89 void PrivetURLFetcher::Try() { |
58 tries_++; | 90 tries_++; |
59 if (tries_ < kPrivetMaxRetries) { | 91 if (tries_ < kPrivetMaxRetries) { |
60 std::string token = privet_access_token_; | 92 std::string token = privet_access_token_; |
61 | 93 |
62 if (token.empty()) | 94 if (token.empty()) |
63 token = kXPrivetEmptyToken; | 95 token = kXPrivetEmptyToken; |
64 | 96 |
65 url_fetcher_.reset(net::URLFetcher::Create(url_, request_type_, this)); | 97 url_fetcher_.reset(net::URLFetcher::Create(url_, request_type_, this)); |
66 url_fetcher_->SetRequestContext(request_context_); | 98 url_fetcher_->SetRequestContext(request_context_); |
67 url_fetcher_->AddExtraRequestHeader(std::string(kXPrivetTokenHeaderPrefix) + | 99 url_fetcher_->AddExtraRequestHeader(std::string(kXPrivetTokenHeaderPrefix) + |
68 token); | 100 token); |
101 if (has_byte_range_) { | |
102 url_fetcher_->AddExtraRequestHeader( | |
103 MakeRangeHeader(byte_range_start_, byte_range_end_)); | |
104 } | |
105 | |
106 if (make_response_file_) { | |
107 url_fetcher_->SaveResponseToTemporaryFile( | |
108 content::BrowserThread::GetMessageLoopProxyForThread( | |
109 content::BrowserThread::FILE)); | |
110 } | |
69 | 111 |
70 // URLFetcher requires us to set upload data for POST requests. | 112 // URLFetcher requires us to set upload data for POST requests. |
71 if (request_type_ == net::URLFetcher::POST) { | 113 if (request_type_ == net::URLFetcher::POST) { |
72 if (!upload_file_path_.empty()) { | 114 if (!upload_file_path_.empty()) { |
73 url_fetcher_->SetUploadFilePath( | 115 url_fetcher_->SetUploadFilePath( |
74 upload_content_type_, | 116 upload_content_type_, |
75 upload_file_path_, | 117 upload_file_path_, |
76 0 /*offset*/, | 118 0 /*offset*/, |
77 kuint64max /*length*/, | 119 kuint64max /*length*/, |
78 content::BrowserThread::GetMessageLoopProxyForThread( | 120 content::BrowserThread::GetMessageLoopProxyForThread( |
79 content::BrowserThread::FILE)); | 121 content::BrowserThread::FILE)); |
80 } else { | 122 } else { |
81 url_fetcher_->SetUploadData(upload_content_type_, upload_data_); | 123 url_fetcher_->SetUploadData(upload_content_type_, upload_data_); |
82 } | 124 } |
83 } | 125 } |
84 | 126 |
85 url_fetcher_->Start(); | 127 url_fetcher_->Start(); |
86 } else { | 128 } else { |
87 delegate_->OnError(this, RETRY_ERROR); | 129 delegate_->OnError(this, RETRY_ERROR); |
88 } | 130 } |
89 } | 131 } |
90 | 132 |
91 void PrivetURLFetcher::Start() { | 133 void PrivetURLFetcher::Start() { |
92 DCHECK_EQ(tries_, 0); // We haven't called |Start()| yet. | 134 DCHECK_EQ(tries_, 0); // We haven't called |Start()| yet. |
93 | 135 |
136 // Byte ranges should only be used when we're not parsing the data | |
137 // as JSON. | |
138 DCHECK(!has_byte_range_ || do_not_parse_data_); | |
139 | |
140 // We should only be saving raw data to a file. | |
141 DCHECK(!make_response_file_ || do_not_parse_data_); | |
142 | |
94 if (privet_access_token_.empty() && !allow_empty_privet_token_) { | 143 if (privet_access_token_.empty() && !allow_empty_privet_token_) { |
95 RequestTokenRefresh(); | 144 RequestTokenRefresh(); |
96 } else { | 145 } else { |
97 Try(); | 146 Try(); |
98 } | 147 } |
99 } | 148 } |
100 | 149 |
101 void PrivetURLFetcher::SetUploadData(const std::string& upload_content_type, | 150 void PrivetURLFetcher::SetUploadData(const std::string& upload_content_type, |
102 const std::string& upload_data) { | 151 const std::string& upload_data) { |
103 DCHECK(upload_file_path_.empty()); | 152 DCHECK(upload_file_path_.empty()); |
104 upload_content_type_ = upload_content_type; | 153 upload_content_type_ = upload_content_type; |
105 upload_data_ = upload_data; | 154 upload_data_ = upload_data; |
106 } | 155 } |
107 | 156 |
108 void PrivetURLFetcher::SetUploadFilePath( | 157 void PrivetURLFetcher::SetUploadFilePath( |
109 const std::string& upload_content_type, | 158 const std::string& upload_content_type, |
110 const base::FilePath& upload_file_path) { | 159 const base::FilePath& upload_file_path) { |
111 DCHECK(upload_data_.empty()); | 160 DCHECK(upload_data_.empty()); |
112 upload_content_type_ = upload_content_type; | 161 upload_content_type_ = upload_content_type; |
113 upload_file_path_ = upload_file_path; | 162 upload_file_path_ = upload_file_path; |
114 } | 163 } |
115 | 164 |
116 void PrivetURLFetcher::OnURLFetchComplete(const net::URLFetcher* source) { | 165 void PrivetURLFetcher::OnURLFetchComplete(const net::URLFetcher* source) { |
117 if (source->GetResponseCode() == net::HTTP_SERVICE_UNAVAILABLE) { | 166 if (source->GetResponseCode() == net::HTTP_SERVICE_UNAVAILABLE) { |
118 ScheduleRetry(kPrivetTimeoutOnError); | 167 ScheduleRetry(kPrivetTimeoutOnError); |
119 return; | 168 return; |
120 } | 169 } |
121 | 170 |
171 if (do_not_parse_data_) { | |
172 OnURLFetchCompleteDoNotParseData(source); | |
173 } else { | |
174 OnURLFetchCompleteParseData(source); | |
175 } | |
176 } | |
177 | |
178 void PrivetURLFetcher::OnURLFetchCompleteDoNotParseData( | |
179 const net::URLFetcher* source) { | |
180 if (source->GetResponseCode() == kHTTPErrorCodeInvalidXPrivetToken) { | |
181 RequestTokenRefresh(); | |
182 return; | |
183 } | |
184 | |
185 if (source->GetResponseCode() != net::HTTP_OK && | |
186 source->GetResponseCode() != net::HTTP_PARTIAL_CONTENT) { | |
187 delegate_->OnError(this, RESPONSE_CODE_ERROR); | |
188 return; | |
189 } | |
190 | |
191 if (make_response_file_) { | |
192 base::FilePath response_file_path; | |
193 | |
194 if (!source->GetResponseAsFilePath(true, &response_file_path)) { | |
195 delegate_->OnError(this, URL_FETCH_ERROR); | |
196 return; | |
197 } | |
198 | |
199 delegate_->OnRawData(this, true, std::string(), response_file_path); | |
200 } else { | |
201 std::string response_str; | |
202 | |
203 if (!source->GetResponseAsString(&response_str)) { | |
204 delegate_->OnError(this, URL_FETCH_ERROR); | |
205 return; | |
206 } | |
207 | |
208 delegate_->OnRawData(this, false, response_str, base::FilePath()); | |
209 } | |
210 } | |
211 | |
212 void PrivetURLFetcher::OnURLFetchCompleteParseData( | |
213 const net::URLFetcher* source) { | |
122 if (source->GetResponseCode() != net::HTTP_OK) { | 214 if (source->GetResponseCode() != net::HTTP_OK) { |
123 delegate_->OnError(this, RESPONSE_CODE_ERROR); | 215 delegate_->OnError(this, RESPONSE_CODE_ERROR); |
124 return; | 216 return; |
125 } | 217 } |
126 | 218 |
127 std::string response_str; | 219 std::string response_str; |
128 | 220 |
129 if (!source->GetResponseAsString(&response_str)) { | 221 if (!source->GetResponseAsString(&response_str)) { |
130 delegate_->OnError(this, URL_FETCH_ERROR); | 222 delegate_->OnError(this, URL_FETCH_ERROR); |
131 return; | 223 return; |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
218 | 310 |
219 scoped_ptr<PrivetURLFetcher> PrivetURLFetcherFactory::CreateURLFetcher( | 311 scoped_ptr<PrivetURLFetcher> PrivetURLFetcherFactory::CreateURLFetcher( |
220 const GURL& url, net::URLFetcher::RequestType request_type, | 312 const GURL& url, net::URLFetcher::RequestType request_type, |
221 PrivetURLFetcher::Delegate* delegate) const { | 313 PrivetURLFetcher::Delegate* delegate) const { |
222 return scoped_ptr<PrivetURLFetcher>( | 314 return scoped_ptr<PrivetURLFetcher>( |
223 new PrivetURLFetcher(token_, url, request_type, request_context_.get(), | 315 new PrivetURLFetcher(token_, url, request_type, request_context_.get(), |
224 delegate)); | 316 delegate)); |
225 } | 317 } |
226 | 318 |
227 } // namespace local_discovery | 319 } // namespace local_discovery |
OLD | NEW |