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 } |
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 // TODO(maniscalco): We treat this as a transient error, but it may in fact be |
| 191 // a very long lived error and require user action. Consider differentiating |
| 192 // between the causes of GetToken failure and act accordingly. Think about |
| 193 // the causes of GetToken failure. Are there (bug 412802). |
| 194 ReportResult(UPLOAD_TRANSIENT_ERROR, attachment_.GetId()); |
188 } | 195 } |
189 | 196 |
190 void AttachmentUploaderImpl::UploadState::GetToken() { | 197 void AttachmentUploaderImpl::UploadState::GetToken() { |
191 access_token_request_ = OAuth2TokenServiceRequest::CreateAndStart( | 198 access_token_request_ = OAuth2TokenServiceRequest::CreateAndStart( |
192 token_service_provider_, account_id_, scopes_, this); | 199 token_service_provider_, account_id_, scopes_, this); |
193 } | 200 } |
194 | 201 |
195 void AttachmentUploaderImpl::UploadState::ReportResult( | 202 void AttachmentUploaderImpl::UploadState::ReportResult( |
196 const UploadResult& result, | 203 const UploadResult& result, |
197 const AttachmentId& attachment_id) { | 204 const AttachmentId& attachment_id) { |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
269 GURL::Replacements replacements; | 276 GURL::Replacements replacements; |
270 replacements.SetPathStr(path); | 277 replacements.SetPathStr(path); |
271 return sync_service_url.ReplaceComponents(replacements); | 278 return sync_service_url.ReplaceComponents(replacements); |
272 } | 279 } |
273 | 280 |
274 void AttachmentUploaderImpl::DeleteUploadStateFor(const UniqueId& unique_id) { | 281 void AttachmentUploaderImpl::DeleteUploadStateFor(const UniqueId& unique_id) { |
275 state_map_.erase(unique_id); | 282 state_map_.erase(unique_id); |
276 } | 283 } |
277 | 284 |
278 } // namespace syncer | 285 } // namespace syncer |
OLD | NEW |