Chromium Code Reviews| 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 "sync/internal_api/public/attachments/attachment_uploader_impl.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/message_loop/message_loop.h" | 8 #include "base/message_loop/message_loop.h" |
| 9 #include "base/threading/non_thread_safe.h" | 9 #include "base/threading/non_thread_safe.h" |
| 10 #include "google_apis/gaia/gaia_constants.h" | 10 #include "google_apis/gaia/gaia_constants.h" |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 126 } | 126 } |
| 127 | 127 |
| 128 const Attachment& AttachmentUploaderImpl::UploadState::GetAttachment() { | 128 const Attachment& AttachmentUploaderImpl::UploadState::GetAttachment() { |
| 129 DCHECK(CalledOnValidThread()); | 129 DCHECK(CalledOnValidThread()); |
| 130 return attachment_; | 130 return attachment_; |
| 131 } | 131 } |
| 132 | 132 |
| 133 void AttachmentUploaderImpl::UploadState::OnURLFetchComplete( | 133 void AttachmentUploaderImpl::UploadState::OnURLFetchComplete( |
| 134 const net::URLFetcher* source) { | 134 const net::URLFetcher* source) { |
| 135 DCHECK(CalledOnValidThread()); | 135 DCHECK(CalledOnValidThread()); |
| 136 UploadResult result = UPLOAD_UNSPECIFIED_ERROR; | 136 UploadResult result = UPLOAD_TRANSIENT_ERROR; |
| 137 AttachmentId attachment_id = attachment_.GetId(); | 137 AttachmentId attachment_id = attachment_.GetId(); |
| 138 if (source->GetResponseCode() == net::HTTP_OK) { | 138 const int response_code = source->GetResponseCode(); |
| 139 if (response_code == net::HTTP_OK) { | |
| 139 result = UPLOAD_SUCCESS; | 140 result = UPLOAD_SUCCESS; |
| 140 } else if (source->GetResponseCode() == net::HTTP_UNAUTHORIZED) { | 141 } else if (response_code == net::HTTP_UNAUTHORIZED) { |
| 141 // TODO(maniscalco): One possibility is that we received a 401 because our | 142 // Server tells us we've got a bad token so invalidate it. |
| 142 // access token has expired. We should probably fetch a new access token | |
| 143 // and retry this upload before giving up and reporting failure to our | |
| 144 // caller (bug 380437). | |
| 145 OAuth2TokenServiceRequest::InvalidateToken( | 143 OAuth2TokenServiceRequest::InvalidateToken( |
| 146 token_service_provider_, account_id_, scopes_, access_token_); | 144 token_service_provider_, account_id_, scopes_, access_token_); |
| 147 } else { | 145 // Fail the request, but indicate that it may be successful if retried. |
| 148 // TODO(maniscalco): Once the protocol is better defined, deal with the | 146 result = UPLOAD_TRANSIENT_ERROR; |
| 149 // various HTTP response codes we may encounter. | 147 } else if (response_code == net::HTTP_FORBIDDEN) { |
| 148 // User is not allowed to use attachments. Retrying won't help. | |
| 149 result = UPLOAD_UNSPECIFIED_ERROR; | |
| 150 } else if (response_code == net::URLFetcher::RESPONSE_CODE_INVALID) { | |
| 151 result = UPLOAD_TRANSIENT_ERROR; | |
| 150 } | 152 } |
|
pavely
2014/09/09 19:42:23
We discussed that all 4xx except "forbidden" are p
pavely
2014/09/09 19:47:42
Sorry, I meant "unauthorized"
maniscalco
2014/09/09 21:15:43
I think you mean all are transient except for forb
maniscalco
2014/09/09 21:15:43
Acknowledged.
| |
| 151 ReportResult(result, attachment_id); | 153 ReportResult(result, attachment_id); |
| 152 } | 154 } |
| 153 | 155 |
| 154 void AttachmentUploaderImpl::UploadState::OnGetTokenSuccess( | 156 void AttachmentUploaderImpl::UploadState::OnGetTokenSuccess( |
| 155 const OAuth2TokenService::Request* request, | 157 const OAuth2TokenService::Request* request, |
| 156 const std::string& access_token, | 158 const std::string& access_token, |
| 157 const base::Time& expiration_time) { | 159 const base::Time& expiration_time) { |
| 158 DCHECK_EQ(access_token_request_.get(), request); | 160 DCHECK_EQ(access_token_request_.get(), request); |
| 159 access_token_request_.reset(); | 161 access_token_request_.reset(); |
| 160 access_token_ = access_token; | 162 access_token_ = access_token; |
| 161 fetcher_.reset( | 163 fetcher_.reset( |
| 162 net::URLFetcher::Create(upload_url_, net::URLFetcher::POST, this)); | 164 net::URLFetcher::Create(upload_url_, net::URLFetcher::POST, this)); |
| 165 fetcher_->SetAutomaticallyRetryOn5xx(false); | |
| 163 fetcher_->SetRequestContext(url_request_context_getter_.get()); | 166 fetcher_->SetRequestContext(url_request_context_getter_.get()); |
| 164 // TODO(maniscalco): Is there a better way? Copying the attachment data into | 167 // TODO(maniscalco): Is there a better way? Copying the attachment data into |
| 165 // a string feels wrong given how large attachments may be (several MBs). If | 168 // a string feels wrong given how large attachments may be (several MBs). If |
| 166 // we may end up switching from URLFetcher to URLRequest, this copy won't be | 169 // we may end up switching from URLFetcher to URLRequest, this copy won't be |
| 167 // necessary. | 170 // necessary. |
| 168 scoped_refptr<base::RefCountedMemory> memory = attachment_.GetData(); | 171 scoped_refptr<base::RefCountedMemory> memory = attachment_.GetData(); |
| 169 const std::string upload_content(memory->front_as<char>(), memory->size()); | 172 const std::string upload_content(memory->front_as<char>(), memory->size()); |
| 170 fetcher_->SetUploadData(kContentType, upload_content); | 173 fetcher_->SetUploadData(kContentType, upload_content); |
| 171 const std::string auth_header("Authorization: Bearer " + access_token_); | 174 const std::string auth_header("Authorization: Bearer " + access_token_); |
| 172 fetcher_->AddExtraRequestHeader(auth_header); | 175 fetcher_->AddExtraRequestHeader(auth_header); |
| 173 fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SAVE_COOKIES | | 176 fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SAVE_COOKIES | |
| 174 net::LOAD_DO_NOT_SEND_COOKIES | | 177 net::LOAD_DO_NOT_SEND_COOKIES | |
| 175 net::LOAD_DISABLE_CACHE); | 178 net::LOAD_DISABLE_CACHE); |
| 176 // TODO(maniscalco): Set an appropriate headers (User-Agent, Content-type, and | 179 // TODO(maniscalco): Set an appropriate headers (User-Agent, Content-type, and |
| 177 // Content-length) on the request and include the content's MD5, | 180 // Content-length) on the request and include the content's MD5, |
| 178 // AttachmentId's unique_id and the "sync birthday" (bug 371521). | 181 // AttachmentId's unique_id and the "sync birthday" (bug 371521). |
| 179 fetcher_->Start(); | 182 fetcher_->Start(); |
| 180 } | 183 } |
| 181 | 184 |
| 182 void AttachmentUploaderImpl::UploadState::OnGetTokenFailure( | 185 void AttachmentUploaderImpl::UploadState::OnGetTokenFailure( |
| 183 const OAuth2TokenService::Request* request, | 186 const OAuth2TokenService::Request* request, |
| 184 const GoogleServiceAuthError& error) { | 187 const GoogleServiceAuthError& error) { |
| 185 DCHECK_EQ(access_token_request_.get(), request); | 188 DCHECK_EQ(access_token_request_.get(), request); |
| 186 access_token_request_.reset(); | 189 access_token_request_.reset(); |
| 187 ReportResult(UPLOAD_UNSPECIFIED_ERROR, attachment_.GetId()); | 190 ReportResult(UPLOAD_TRANSIENT_ERROR, attachment_.GetId()); |
|
pavely
2014/09/09 19:42:23
Could you put a TODO that errors should be treated
maniscalco
2014/09/09 21:15:44
Happy to chat more in person. TODO added.
Were y
| |
| 188 } | 191 } |
| 189 | 192 |
| 190 void AttachmentUploaderImpl::UploadState::GetToken() { | 193 void AttachmentUploaderImpl::UploadState::GetToken() { |
| 191 access_token_request_ = OAuth2TokenServiceRequest::CreateAndStart( | 194 access_token_request_ = OAuth2TokenServiceRequest::CreateAndStart( |
| 192 token_service_provider_, account_id_, scopes_, this); | 195 token_service_provider_, account_id_, scopes_, this); |
| 193 } | 196 } |
| 194 | 197 |
| 195 void AttachmentUploaderImpl::UploadState::ReportResult( | 198 void AttachmentUploaderImpl::UploadState::ReportResult( |
| 196 const UploadResult& result, | 199 const UploadResult& result, |
| 197 const AttachmentId& attachment_id) { | 200 const AttachmentId& attachment_id) { |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 269 GURL::Replacements replacements; | 272 GURL::Replacements replacements; |
| 270 replacements.SetPathStr(path); | 273 replacements.SetPathStr(path); |
| 271 return sync_service_url.ReplaceComponents(replacements); | 274 return sync_service_url.ReplaceComponents(replacements); |
| 272 } | 275 } |
| 273 | 276 |
| 274 void AttachmentUploaderImpl::DeleteUploadStateFor(const UniqueId& unique_id) { | 277 void AttachmentUploaderImpl::DeleteUploadStateFor(const UniqueId& unique_id) { |
| 275 state_map_.erase(unique_id); | 278 state_map_.erase(unique_id); |
| 276 } | 279 } |
| 277 | 280 |
| 278 } // namespace syncer | 281 } // namespace syncer |
| OLD | NEW |