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_uploader_impl.h" | 5 #include "components/sync/core/attachments/attachment_uploader_impl.h" |
6 | 6 |
7 #include <stdint.h> | 7 #include <stdint.h> |
| 8 |
8 #include <string> | 9 #include <string> |
9 #include <utility> | 10 #include <utility> |
10 #include <vector> | 11 #include <vector> |
11 | 12 |
12 #include "base/base64.h" | 13 #include "base/base64.h" |
13 #include "base/base64url.h" | 14 #include "base/base64url.h" |
14 #include "base/bind.h" | 15 #include "base/bind.h" |
15 #include "base/location.h" | 16 #include "base/location.h" |
16 #include "base/macros.h" | 17 #include "base/macros.h" |
17 #include "base/memory/weak_ptr.h" | 18 #include "base/memory/weak_ptr.h" |
18 #include "base/metrics/sparse_histogram.h" | 19 #include "base/metrics/sparse_histogram.h" |
19 #include "base/single_thread_task_runner.h" | 20 #include "base/single_thread_task_runner.h" |
20 #include "base/strings/string_piece.h" | 21 #include "base/strings/string_piece.h" |
21 #include "base/strings/stringprintf.h" | 22 #include "base/strings/stringprintf.h" |
22 #include "base/sys_byteorder.h" | 23 #include "base/sys_byteorder.h" |
23 #include "base/threading/non_thread_safe.h" | 24 #include "base/threading/non_thread_safe.h" |
24 #include "base/threading/thread_task_runner_handle.h" | 25 #include "base/threading/thread_task_runner_handle.h" |
| 26 #include "components/sync/api/attachments/attachment.h" |
| 27 #include "components/sync/protocol/sync.pb.h" |
25 #include "google_apis/gaia/gaia_constants.h" | 28 #include "google_apis/gaia/gaia_constants.h" |
26 #include "net/base/load_flags.h" | 29 #include "net/base/load_flags.h" |
27 #include "net/http/http_status_code.h" | 30 #include "net/http/http_status_code.h" |
28 #include "net/url_request/url_fetcher.h" | 31 #include "net/url_request/url_fetcher.h" |
29 #include "net/url_request/url_fetcher_delegate.h" | 32 #include "net/url_request/url_fetcher_delegate.h" |
30 #include "net/url_request/url_request_status.h" | 33 #include "net/url_request/url_request_status.h" |
31 #include "sync/api/attachments/attachment.h" | |
32 #include "sync/protocol/sync.pb.h" | |
33 | 34 |
34 namespace { | 35 namespace { |
35 | 36 |
36 const char kContentType[] = "application/octet-stream"; | 37 const char kContentType[] = "application/octet-stream"; |
37 const char kAttachments[] = "attachments/"; | 38 const char kAttachments[] = "attachments/"; |
38 const char kSyncStoreBirthday[] = "X-Sync-Store-Birthday"; | 39 const char kSyncStoreBirthday[] = "X-Sync-Store-Birthday"; |
39 const char kSyncDataTypeId[] = "X-Sync-Data-Type-Id"; | 40 const char kSyncDataTypeId[] = "X-Sync-Data-Type-Id"; |
40 | 41 |
41 } // namespace | 42 } // namespace |
42 | 43 |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
148 model_type_(model_type) { | 149 model_type_(model_type) { |
149 DCHECK(upload_url_.is_valid()); | 150 DCHECK(upload_url_.is_valid()); |
150 DCHECK(url_request_context_getter_.get()); | 151 DCHECK(url_request_context_getter_.get()); |
151 DCHECK(!account_id_.empty()); | 152 DCHECK(!account_id_.empty()); |
152 DCHECK(!scopes_.empty()); | 153 DCHECK(!scopes_.empty()); |
153 DCHECK(token_service_provider_); | 154 DCHECK(token_service_provider_); |
154 DCHECK(!raw_store_birthday_.empty()); | 155 DCHECK(!raw_store_birthday_.empty()); |
155 GetToken(); | 156 GetToken(); |
156 } | 157 } |
157 | 158 |
158 AttachmentUploaderImpl::UploadState::~UploadState() { | 159 AttachmentUploaderImpl::UploadState::~UploadState() {} |
159 } | |
160 | 160 |
161 bool AttachmentUploaderImpl::UploadState::IsStopped() const { | 161 bool AttachmentUploaderImpl::UploadState::IsStopped() const { |
162 DCHECK(CalledOnValidThread()); | 162 DCHECK(CalledOnValidThread()); |
163 return is_stopped_; | 163 return is_stopped_; |
164 } | 164 } |
165 | 165 |
166 void AttachmentUploaderImpl::UploadState::AddUserCallback( | 166 void AttachmentUploaderImpl::UploadState::AddUserCallback( |
167 const UploadCallback& user_callback) { | 167 const UploadCallback& user_callback) { |
168 DCHECK(CalledOnValidThread()); | 168 DCHECK(CalledOnValidThread()); |
169 DCHECK(!is_stopped_); | 169 DCHECK(!is_stopped_); |
170 user_callbacks_.push_back(user_callback); | 170 user_callbacks_.push_back(user_callback); |
171 } | 171 } |
172 | 172 |
173 const Attachment& AttachmentUploaderImpl::UploadState::GetAttachment() { | 173 const Attachment& AttachmentUploaderImpl::UploadState::GetAttachment() { |
174 DCHECK(CalledOnValidThread()); | 174 DCHECK(CalledOnValidThread()); |
175 return attachment_; | 175 return attachment_; |
176 } | 176 } |
177 | 177 |
178 void AttachmentUploaderImpl::UploadState::OnURLFetchComplete( | 178 void AttachmentUploaderImpl::UploadState::OnURLFetchComplete( |
179 const net::URLFetcher* source) { | 179 const net::URLFetcher* source) { |
180 DCHECK(CalledOnValidThread()); | 180 DCHECK(CalledOnValidThread()); |
181 if (is_stopped_) { | 181 if (is_stopped_) { |
182 return; | 182 return; |
183 } | 183 } |
184 | 184 |
185 UploadResult result = UPLOAD_TRANSIENT_ERROR; | 185 UploadResult result = UPLOAD_TRANSIENT_ERROR; |
186 AttachmentId attachment_id = attachment_.GetId(); | 186 AttachmentId attachment_id = attachment_.GetId(); |
187 net::URLRequestStatus status = source->GetStatus(); | 187 net::URLRequestStatus status = source->GetStatus(); |
188 const int response_code = source->GetResponseCode(); | 188 const int response_code = source->GetResponseCode(); |
189 UMA_HISTOGRAM_SPARSE_SLOWLY("Sync.Attachments.UploadResponseCode", | 189 UMA_HISTOGRAM_SPARSE_SLOWLY( |
| 190 "Sync.Attachments.UploadResponseCode", |
190 status.is_success() ? response_code : status.error()); | 191 status.is_success() ? response_code : status.error()); |
191 if (response_code == net::HTTP_OK) { | 192 if (response_code == net::HTTP_OK) { |
192 result = UPLOAD_SUCCESS; | 193 result = UPLOAD_SUCCESS; |
193 } else if (response_code == net::HTTP_UNAUTHORIZED) { | 194 } else if (response_code == net::HTTP_UNAUTHORIZED) { |
194 // Server tells us we've got a bad token so invalidate it. | 195 // Server tells us we've got a bad token so invalidate it. |
195 OAuth2TokenServiceRequest::InvalidateToken( | 196 OAuth2TokenServiceRequest::InvalidateToken( |
196 token_service_provider_, account_id_, scopes_, access_token_); | 197 token_service_provider_, account_id_, scopes_, access_token_); |
197 // Fail the request, but indicate that it may be successful if retried. | 198 // Fail the request, but indicate that it may be successful if retried. |
198 result = UPLOAD_TRANSIENT_ERROR; | 199 result = UPLOAD_TRANSIENT_ERROR; |
199 } else if (response_code == net::HTTP_FORBIDDEN) { | 200 } else if (response_code == net::HTTP_FORBIDDEN) { |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
307 const UploadCallback& callback) { | 308 const UploadCallback& callback) { |
308 DCHECK(CalledOnValidThread()); | 309 DCHECK(CalledOnValidThread()); |
309 const AttachmentId attachment_id = attachment.GetId(); | 310 const AttachmentId attachment_id = attachment.GetId(); |
310 const std::string unique_id = attachment_id.GetProto().unique_id(); | 311 const std::string unique_id = attachment_id.GetProto().unique_id(); |
311 DCHECK(!unique_id.empty()); | 312 DCHECK(!unique_id.empty()); |
312 StateMap::iterator iter = state_map_.find(unique_id); | 313 StateMap::iterator iter = state_map_.find(unique_id); |
313 if (iter != state_map_.end()) { | 314 if (iter != state_map_.end()) { |
314 // We have an old upload request for this attachment... | 315 // We have an old upload request for this attachment... |
315 if (!iter->second->IsStopped()) { | 316 if (!iter->second->IsStopped()) { |
316 // "join" to it. | 317 // "join" to it. |
317 DCHECK(attachment.GetData() | 318 DCHECK(attachment.GetData()->Equals( |
318 ->Equals(iter->second->GetAttachment().GetData())); | 319 iter->second->GetAttachment().GetData())); |
319 iter->second->AddUserCallback(callback); | 320 iter->second->AddUserCallback(callback); |
320 return; | 321 return; |
321 } else { | 322 } else { |
322 // It's stopped so we can't use it. Delete it. | 323 // It's stopped so we can't use it. Delete it. |
323 state_map_.erase(iter); | 324 state_map_.erase(iter); |
324 } | 325 } |
325 } | 326 } |
326 | 327 |
327 const GURL url = GetURLForAttachmentId(sync_service_url_, attachment_id); | 328 const GURL url = GetURLForAttachmentId(sync_service_url_, attachment_id); |
328 std::unique_ptr<UploadState> upload_state(new UploadState( | 329 std::unique_ptr<UploadState> upload_state(new UploadState( |
(...skipping 25 matching lines...) Expand all Loading... |
354 // stopped, but before this method was invoked. In that case the UploadState | 355 // stopped, but before this method was invoked. In that case the UploadState |
355 // in the map might be a new one. | 356 // in the map might be a new one. |
356 if (iter != state_map_.end() && iter->second->IsStopped()) { | 357 if (iter != state_map_.end() && iter->second->IsStopped()) { |
357 state_map_.erase(iter); | 358 state_map_.erase(iter); |
358 } | 359 } |
359 } | 360 } |
360 | 361 |
361 std::string AttachmentUploaderImpl::FormatCrc32cHash(uint32_t crc32c) { | 362 std::string AttachmentUploaderImpl::FormatCrc32cHash(uint32_t crc32c) { |
362 const uint32_t crc32c_big_endian = base::HostToNet32(crc32c); | 363 const uint32_t crc32c_big_endian = base::HostToNet32(crc32c); |
363 const base::StringPiece raw(reinterpret_cast<const char*>(&crc32c_big_endian), | 364 const base::StringPiece raw(reinterpret_cast<const char*>(&crc32c_big_endian), |
364 sizeof(crc32c_big_endian)); | 365 sizeof(crc32c_big_endian)); |
365 std::string encoded; | 366 std::string encoded; |
366 base::Base64Encode(raw, &encoded); | 367 base::Base64Encode(raw, &encoded); |
367 return encoded; | 368 return encoded; |
368 } | 369 } |
369 | 370 |
370 void AttachmentUploaderImpl::ConfigureURLFetcherCommon( | 371 void AttachmentUploaderImpl::ConfigureURLFetcherCommon( |
371 net::URLFetcher* fetcher, | 372 net::URLFetcher* fetcher, |
372 const std::string& access_token, | 373 const std::string& access_token, |
373 const std::string& raw_store_birthday, | 374 const std::string& raw_store_birthday, |
374 ModelType model_type, | 375 ModelType model_type, |
375 net::URLRequestContextGetter* request_context_getter) { | 376 net::URLRequestContextGetter* request_context_getter) { |
376 DCHECK(request_context_getter); | 377 DCHECK(request_context_getter); |
377 DCHECK(fetcher); | 378 DCHECK(fetcher); |
378 fetcher->SetAutomaticallyRetryOn5xx(false); | 379 fetcher->SetAutomaticallyRetryOn5xx(false); |
379 fetcher->SetRequestContext(request_context_getter); | 380 fetcher->SetRequestContext(request_context_getter); |
380 fetcher->SetLoadFlags(net::LOAD_DO_NOT_SAVE_COOKIES | | 381 fetcher->SetLoadFlags(net::LOAD_DO_NOT_SAVE_COOKIES | |
381 net::LOAD_DO_NOT_SEND_COOKIES | | 382 net::LOAD_DO_NOT_SEND_COOKIES | |
382 net::LOAD_DISABLE_CACHE); | 383 net::LOAD_DISABLE_CACHE); |
383 fetcher->AddExtraRequestHeader(base::StringPrintf( | 384 fetcher->AddExtraRequestHeader(base::StringPrintf( |
384 "%s: Bearer %s", net::HttpRequestHeaders::kAuthorization, | 385 "%s: Bearer %s", net::HttpRequestHeaders::kAuthorization, |
385 access_token.c_str())); | 386 access_token.c_str())); |
386 // Encode the birthday. Birthday is opaque so we assume it could contain | 387 // Encode the birthday. Birthday is opaque so we assume it could contain |
387 // anything. Encode it so that it's safe to pass as an HTTP header value. | 388 // anything. Encode it so that it's safe to pass as an HTTP header value. |
388 std::string encoded_store_birthday; | 389 std::string encoded_store_birthday; |
389 base::Base64UrlEncode( | 390 base::Base64UrlEncode(raw_store_birthday, |
390 raw_store_birthday, base::Base64UrlEncodePolicy::OMIT_PADDING, | 391 base::Base64UrlEncodePolicy::OMIT_PADDING, |
391 &encoded_store_birthday); | 392 &encoded_store_birthday); |
392 fetcher->AddExtraRequestHeader(base::StringPrintf( | 393 fetcher->AddExtraRequestHeader(base::StringPrintf( |
393 "%s: %s", kSyncStoreBirthday, encoded_store_birthday.c_str())); | 394 "%s: %s", kSyncStoreBirthday, encoded_store_birthday.c_str())); |
394 | 395 |
395 // Use field number to pass ModelType because it's stable and we have server | 396 // Use field number to pass ModelType because it's stable and we have server |
396 // code to decode it. | 397 // code to decode it. |
397 const int field_number = GetSpecificsFieldNumberFromModelType(model_type); | 398 const int field_number = GetSpecificsFieldNumberFromModelType(model_type); |
398 fetcher->AddExtraRequestHeader( | 399 fetcher->AddExtraRequestHeader( |
399 base::StringPrintf("%s: %d", kSyncDataTypeId, field_number)); | 400 base::StringPrintf("%s: %d", kSyncDataTypeId, field_number)); |
400 } | 401 } |
401 | 402 |
402 } // namespace syncer | 403 } // namespace syncer |
OLD | NEW |