OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "sync/internal_api/public/attachments/attachment_downloader_impl.h" | 5 #include "sync/internal_api/public/attachments/attachment_downloader_impl.h" |
6 | 6 |
7 #include "base/base64.h" | 7 #include "base/base64.h" |
8 #include "base/bind.h" | 8 #include "base/bind.h" |
9 #include "base/message_loop/message_loop.h" | 9 #include "base/message_loop/message_loop.h" |
10 #include "base/metrics/histogram.h" | 10 #include "base/metrics/histogram.h" |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
125 DCHECK(request == access_token_request_.get()); | 125 DCHECK(request == access_token_request_.get()); |
126 access_token_request_.reset(); | 126 access_token_request_.reset(); |
127 StateList::const_iterator iter; | 127 StateList::const_iterator iter; |
128 // Without access token all downloads fail. | 128 // Without access token all downloads fail. |
129 for (iter = requests_waiting_for_access_token_.begin(); | 129 for (iter = requests_waiting_for_access_token_.begin(); |
130 iter != requests_waiting_for_access_token_.end(); | 130 iter != requests_waiting_for_access_token_.end(); |
131 ++iter) { | 131 ++iter) { |
132 DownloadState* download_state = *iter; | 132 DownloadState* download_state = *iter; |
133 scoped_refptr<base::RefCountedString> null_attachment_data; | 133 scoped_refptr<base::RefCountedString> null_attachment_data; |
134 ReportResult(*download_state, DOWNLOAD_TRANSIENT_ERROR, | 134 ReportResult(*download_state, DOWNLOAD_TRANSIENT_ERROR, |
135 null_attachment_data); | 135 null_attachment_data, 0); |
136 DCHECK(state_map_.find(download_state->attachment_url) != state_map_.end()); | 136 DCHECK(state_map_.find(download_state->attachment_url) != state_map_.end()); |
137 state_map_.erase(download_state->attachment_url); | 137 state_map_.erase(download_state->attachment_url); |
138 } | 138 } |
139 requests_waiting_for_access_token_.clear(); | 139 requests_waiting_for_access_token_.clear(); |
140 } | 140 } |
141 | 141 |
142 void AttachmentDownloaderImpl::OnURLFetchComplete( | 142 void AttachmentDownloaderImpl::OnURLFetchComplete( |
143 const net::URLFetcher* source) { | 143 const net::URLFetcher* source) { |
144 DCHECK(CalledOnValidThread()); | 144 DCHECK(CalledOnValidThread()); |
145 | 145 |
(...skipping 22 matching lines...) Expand all Loading... |
168 | 168 |
169 attachment_crc32c = ComputeCrc32c(attachment_data); | 169 attachment_crc32c = ComputeCrc32c(attachment_data); |
170 uint32_t crc32c_from_headers = 0; | 170 uint32_t crc32c_from_headers = 0; |
171 if (ExtractCrc32c(source->GetResponseHeaders(), &crc32c_from_headers) && | 171 if (ExtractCrc32c(source->GetResponseHeaders(), &crc32c_from_headers) && |
172 attachment_crc32c != crc32c_from_headers) { | 172 attachment_crc32c != crc32c_from_headers) { |
173 // Fail download only if there is useful crc32c in header and it doesn't | 173 // Fail download only if there is useful crc32c in header and it doesn't |
174 // match data. All other cases are fine. When crc32c is not in headers | 174 // match data. All other cases are fine. When crc32c is not in headers |
175 // locally calculated one will be stored and used for further checks. | 175 // locally calculated one will be stored and used for further checks. |
176 result = DOWNLOAD_TRANSIENT_ERROR; | 176 result = DOWNLOAD_TRANSIENT_ERROR; |
177 } else { | 177 } else { |
178 // If the id's crc32c doesn't match that of the downloaded attachment, | 178 result = DOWNLOAD_SUCCESS; |
179 // then we're stuck and retrying is unlikely to help. | |
180 if (attachment_crc32c != download_state.attachment_id.GetCrc32c()) { | |
181 result = DOWNLOAD_UNSPECIFIED_ERROR; | |
182 } else { | |
183 result = DOWNLOAD_SUCCESS; | |
184 } | |
185 } | 179 } |
186 UMA_HISTOGRAM_BOOLEAN("Sync.Attachments.DownloadChecksumResult", | 180 UMA_HISTOGRAM_BOOLEAN("Sync.Attachments.DownloadChecksumResult", |
187 result == DOWNLOAD_SUCCESS); | 181 result == DOWNLOAD_SUCCESS); |
188 } else if (response_code == net::HTTP_UNAUTHORIZED) { | 182 } else if (response_code == net::HTTP_UNAUTHORIZED) { |
189 // Server tells us we've got a bad token so invalidate it. | 183 // Server tells us we've got a bad token so invalidate it. |
190 OAuth2TokenServiceRequest::InvalidateToken(token_service_provider_.get(), | 184 OAuth2TokenServiceRequest::InvalidateToken(token_service_provider_.get(), |
191 account_id_, | 185 account_id_, |
192 oauth2_scopes_, | 186 oauth2_scopes_, |
193 download_state.access_token); | 187 download_state.access_token); |
194 // Fail the request, but indicate that it may be successful if retried. | 188 // Fail the request, but indicate that it may be successful if retried. |
195 result = DOWNLOAD_TRANSIENT_ERROR; | 189 result = DOWNLOAD_TRANSIENT_ERROR; |
196 } else if (response_code == net::HTTP_FORBIDDEN) { | 190 } else if (response_code == net::HTTP_FORBIDDEN) { |
197 // User is not allowed to use attachments. Retrying won't help. | 191 // User is not allowed to use attachments. Retrying won't help. |
198 result = DOWNLOAD_UNSPECIFIED_ERROR; | 192 result = DOWNLOAD_UNSPECIFIED_ERROR; |
199 } else if (response_code == net::URLFetcher::RESPONSE_CODE_INVALID) { | 193 } else if (response_code == net::URLFetcher::RESPONSE_CODE_INVALID) { |
200 result = DOWNLOAD_TRANSIENT_ERROR; | 194 result = DOWNLOAD_TRANSIENT_ERROR; |
201 } | 195 } |
202 ReportResult(download_state, result, attachment_data); | 196 ReportResult(download_state, result, attachment_data, attachment_crc32c); |
203 state_map_.erase(iter); | 197 state_map_.erase(iter); |
204 } | 198 } |
205 | 199 |
206 scoped_ptr<net::URLFetcher> AttachmentDownloaderImpl::CreateFetcher( | 200 scoped_ptr<net::URLFetcher> AttachmentDownloaderImpl::CreateFetcher( |
207 const AttachmentUrl& url, | 201 const AttachmentUrl& url, |
208 const std::string& access_token) { | 202 const std::string& access_token) { |
209 scoped_ptr<net::URLFetcher> url_fetcher( | 203 scoped_ptr<net::URLFetcher> url_fetcher( |
210 net::URLFetcher::Create(GURL(url), net::URLFetcher::GET, this)); | 204 net::URLFetcher::Create(GURL(url), net::URLFetcher::GET, this)); |
211 AttachmentUploaderImpl::ConfigureURLFetcherCommon( | 205 AttachmentUploaderImpl::ConfigureURLFetcherCommon( |
212 url_fetcher.get(), access_token, raw_store_birthday_, model_type_, | 206 url_fetcher.get(), access_token, raw_store_birthday_, model_type_, |
213 url_request_context_getter_.get()); | 207 url_request_context_getter_.get()); |
214 return url_fetcher.Pass(); | 208 return url_fetcher.Pass(); |
215 } | 209 } |
216 | 210 |
217 void AttachmentDownloaderImpl::RequestAccessToken( | 211 void AttachmentDownloaderImpl::RequestAccessToken( |
218 DownloadState* download_state) { | 212 DownloadState* download_state) { |
219 requests_waiting_for_access_token_.push_back(download_state); | 213 requests_waiting_for_access_token_.push_back(download_state); |
220 // Start access token request if there is no active one. | 214 // Start access token request if there is no active one. |
221 if (access_token_request_ == NULL) { | 215 if (access_token_request_ == NULL) { |
222 access_token_request_ = OAuth2TokenServiceRequest::CreateAndStart( | 216 access_token_request_ = OAuth2TokenServiceRequest::CreateAndStart( |
223 token_service_provider_.get(), account_id_, oauth2_scopes_, this); | 217 token_service_provider_.get(), account_id_, oauth2_scopes_, this); |
224 } | 218 } |
225 } | 219 } |
226 | 220 |
227 void AttachmentDownloaderImpl::ReportResult( | 221 void AttachmentDownloaderImpl::ReportResult( |
228 const DownloadState& download_state, | 222 const DownloadState& download_state, |
229 const DownloadResult& result, | 223 const DownloadResult& result, |
230 const scoped_refptr<base::RefCountedString>& attachment_data) { | 224 const scoped_refptr<base::RefCountedString>& attachment_data, |
| 225 uint32_t attachment_crc32c) { |
231 std::vector<DownloadCallback>::const_iterator iter; | 226 std::vector<DownloadCallback>::const_iterator iter; |
232 for (iter = download_state.user_callbacks.begin(); | 227 for (iter = download_state.user_callbacks.begin(); |
233 iter != download_state.user_callbacks.end(); | 228 iter != download_state.user_callbacks.end(); |
234 ++iter) { | 229 ++iter) { |
235 scoped_ptr<Attachment> attachment; | 230 scoped_ptr<Attachment> attachment; |
236 if (result == DOWNLOAD_SUCCESS) { | 231 if (result == DOWNLOAD_SUCCESS) { |
237 attachment.reset(new Attachment(Attachment::CreateFromParts( | 232 attachment.reset(new Attachment(Attachment::CreateFromParts( |
238 download_state.attachment_id, attachment_data))); | 233 download_state.attachment_id, attachment_data, attachment_crc32c))); |
239 } | 234 } |
240 | 235 |
241 base::MessageLoop::current()->PostTask( | 236 base::MessageLoop::current()->PostTask( |
242 FROM_HERE, base::Bind(*iter, result, base::Passed(&attachment))); | 237 FROM_HERE, base::Bind(*iter, result, base::Passed(&attachment))); |
243 } | 238 } |
244 } | 239 } |
245 | 240 |
246 bool AttachmentDownloaderImpl::ExtractCrc32c( | 241 bool AttachmentDownloaderImpl::ExtractCrc32c( |
247 const net::HttpResponseHeaders* headers, | 242 const net::HttpResponseHeaders* headers, |
248 uint32_t* crc32c) { | 243 uint32_t* crc32c) { |
(...skipping 28 matching lines...) Expand all Loading... |
277 | 272 |
278 if (crc32c_raw.size() != sizeof(*crc32c)) | 273 if (crc32c_raw.size() != sizeof(*crc32c)) |
279 return false; | 274 return false; |
280 | 275 |
281 *crc32c = | 276 *crc32c = |
282 base::NetToHost32(*reinterpret_cast<const uint32_t*>(crc32c_raw.c_str())); | 277 base::NetToHost32(*reinterpret_cast<const uint32_t*>(crc32c_raw.c_str())); |
283 return true; | 278 return true; |
284 } | 279 } |
285 | 280 |
286 } // namespace syncer | 281 } // namespace syncer |
OLD | NEW |