Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(361)

Side by Side Diff: sync/internal_api/attachments/attachment_uploader_impl.cc

Issue 556083002: Eliminate use of 'delete self' pattern in AttachmentUploaderImpl. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@persistentuploads-retry
Patch Set: Merge with master. Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | sync/internal_api/public/attachments/attachment_uploader_impl.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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/memory/weak_ptr.h"
8 #include "base/message_loop/message_loop.h" 9 #include "base/message_loop/message_loop.h"
9 #include "base/threading/non_thread_safe.h" 10 #include "base/threading/non_thread_safe.h"
10 #include "google_apis/gaia/gaia_constants.h" 11 #include "google_apis/gaia/gaia_constants.h"
11 #include "net/base/load_flags.h" 12 #include "net/base/load_flags.h"
12 #include "net/http/http_status_code.h" 13 #include "net/http/http_status_code.h"
13 #include "net/url_request/url_fetcher.h" 14 #include "net/url_request/url_fetcher.h"
14 #include "net/url_request/url_fetcher_delegate.h" 15 #include "net/url_request/url_fetcher_delegate.h"
15 #include "sync/api/attachments/attachment.h" 16 #include "sync/api/attachments/attachment.h"
16 #include "sync/protocol/sync.pb.h" 17 #include "sync/protocol/sync.pb.h"
17 18
18 namespace { 19 namespace {
19 20
20 const char kContentType[] = "application/octet-stream"; 21 const char kContentType[] = "application/octet-stream";
21 const char kAttachments[] = "attachments/"; 22 const char kAttachments[] = "attachments/";
22 23
23 } // namespace 24 } // namespace
24 25
25 namespace syncer { 26 namespace syncer {
26 27
27 // Encapsulates all the state associated with a single upload. 28 // Encapsulates all the state associated with a single upload.
28 class AttachmentUploaderImpl::UploadState : public net::URLFetcherDelegate, 29 class AttachmentUploaderImpl::UploadState : public net::URLFetcherDelegate,
29 public OAuth2TokenService::Consumer, 30 public OAuth2TokenService::Consumer,
30 public base::NonThreadSafe { 31 public base::NonThreadSafe {
31 public: 32 public:
32 // Construct an UploadState. 33 // Construct an UploadState.
33 // 34 //
34 // |owner| is a pointer to the object that will own (and must outlive!) this 35 // UploadState encapsulates the state associated with a single upload. When
35 // |UploadState. 36 // the upload completes, the UploadState object becomes "stopped".
37 //
38 // |owner| is a pointer to the object that owns this UploadState. Upon
39 // completion this object will PostTask to owner's OnUploadStateStopped
40 // method.
36 UploadState( 41 UploadState(
37 const GURL& upload_url, 42 const GURL& upload_url,
38 const scoped_refptr<net::URLRequestContextGetter>& 43 const scoped_refptr<net::URLRequestContextGetter>&
39 url_request_context_getter, 44 url_request_context_getter,
40 const Attachment& attachment, 45 const Attachment& attachment,
41 const UploadCallback& user_callback, 46 const UploadCallback& user_callback,
42 const std::string& account_id, 47 const std::string& account_id,
43 const OAuth2TokenService::ScopeSet& scopes, 48 const OAuth2TokenService::ScopeSet& scopes,
44 OAuth2TokenServiceRequest::TokenServiceProvider* token_service_provider, 49 OAuth2TokenServiceRequest::TokenServiceProvider* token_service_provider,
45 AttachmentUploaderImpl* owner); 50 const base::WeakPtr<AttachmentUploaderImpl>& owner);
46 51
47 virtual ~UploadState(); 52 virtual ~UploadState();
48 53
54 // Returns true if this object is stopped. Once stopped, this object is
55 // effectively dead and can be destroyed.
56 bool IsStopped() const;
57
49 // Add |user_callback| to the list of callbacks to be invoked when this upload 58 // Add |user_callback| to the list of callbacks to be invoked when this upload
50 // completed. 59 // completed.
60 //
61 // It is an error to call |AddUserCallback| on a stopped UploadState (see
62 // |IsStopped|).
51 void AddUserCallback(const UploadCallback& user_callback); 63 void AddUserCallback(const UploadCallback& user_callback);
52 64
53 // Return the Attachment this object is uploading. 65 // Return the Attachment this object is uploading.
54 const Attachment& GetAttachment(); 66 const Attachment& GetAttachment();
55 67
56 // URLFetcher implementation. 68 // URLFetcher implementation.
57 virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE; 69 virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE;
58 70
59 // OAuth2TokenService::Consumer. 71 // OAuth2TokenService::Consumer.
60 virtual void OnGetTokenSuccess(const OAuth2TokenService::Request* request, 72 virtual void OnGetTokenSuccess(const OAuth2TokenService::Request* request,
61 const std::string& access_token, 73 const std::string& access_token,
62 const base::Time& expiration_time) OVERRIDE; 74 const base::Time& expiration_time) OVERRIDE;
63 virtual void OnGetTokenFailure(const OAuth2TokenService::Request* request, 75 virtual void OnGetTokenFailure(const OAuth2TokenService::Request* request,
64 const GoogleServiceAuthError& error) OVERRIDE; 76 const GoogleServiceAuthError& error) OVERRIDE;
65 77
66 private: 78 private:
67 typedef std::vector<UploadCallback> UploadCallbackList; 79 typedef std::vector<UploadCallback> UploadCallbackList;
68 80
69 void GetToken(); 81 void GetToken();
70 82
71 void ReportResult(const UploadResult& result, 83 void StopAndReportResult(const UploadResult& result,
72 const AttachmentId& attachment_id); 84 const AttachmentId& attachment_id);
73 85
86 bool is_stopped_;
74 GURL upload_url_; 87 GURL upload_url_;
75 const scoped_refptr<net::URLRequestContextGetter>& 88 const scoped_refptr<net::URLRequestContextGetter>&
76 url_request_context_getter_; 89 url_request_context_getter_;
77 Attachment attachment_; 90 Attachment attachment_;
78 UploadCallbackList user_callbacks_; 91 UploadCallbackList user_callbacks_;
79 scoped_ptr<net::URLFetcher> fetcher_; 92 scoped_ptr<net::URLFetcher> fetcher_;
80 std::string account_id_; 93 std::string account_id_;
81 OAuth2TokenService::ScopeSet scopes_; 94 OAuth2TokenService::ScopeSet scopes_;
82 std::string access_token_; 95 std::string access_token_;
83 OAuth2TokenServiceRequest::TokenServiceProvider* token_service_provider_; 96 OAuth2TokenServiceRequest::TokenServiceProvider* token_service_provider_;
84 // Pointer to the AttachmentUploaderImpl that owns this object. 97 // Pointer to the AttachmentUploaderImpl that owns this object.
85 AttachmentUploaderImpl* owner_; 98 base::WeakPtr<AttachmentUploaderImpl> owner_;
86 scoped_ptr<OAuth2TokenServiceRequest> access_token_request_; 99 scoped_ptr<OAuth2TokenServiceRequest> access_token_request_;
87 100
88 DISALLOW_COPY_AND_ASSIGN(UploadState); 101 DISALLOW_COPY_AND_ASSIGN(UploadState);
89 }; 102 };
90 103
91 AttachmentUploaderImpl::UploadState::UploadState( 104 AttachmentUploaderImpl::UploadState::UploadState(
92 const GURL& upload_url, 105 const GURL& upload_url,
93 const scoped_refptr<net::URLRequestContextGetter>& 106 const scoped_refptr<net::URLRequestContextGetter>&
94 url_request_context_getter, 107 url_request_context_getter,
95 const Attachment& attachment, 108 const Attachment& attachment,
96 const UploadCallback& user_callback, 109 const UploadCallback& user_callback,
97 const std::string& account_id, 110 const std::string& account_id,
98 const OAuth2TokenService::ScopeSet& scopes, 111 const OAuth2TokenService::ScopeSet& scopes,
99 OAuth2TokenServiceRequest::TokenServiceProvider* token_service_provider, 112 OAuth2TokenServiceRequest::TokenServiceProvider* token_service_provider,
100 AttachmentUploaderImpl* owner) 113 const base::WeakPtr<AttachmentUploaderImpl>& owner)
101 : OAuth2TokenService::Consumer("attachment-uploader-impl"), 114 : OAuth2TokenService::Consumer("attachment-uploader-impl"),
115 is_stopped_(false),
102 upload_url_(upload_url), 116 upload_url_(upload_url),
103 url_request_context_getter_(url_request_context_getter), 117 url_request_context_getter_(url_request_context_getter),
104 attachment_(attachment), 118 attachment_(attachment),
105 user_callbacks_(1, user_callback), 119 user_callbacks_(1, user_callback),
106 account_id_(account_id), 120 account_id_(account_id),
107 scopes_(scopes), 121 scopes_(scopes),
108 token_service_provider_(token_service_provider), 122 token_service_provider_(token_service_provider),
109 owner_(owner) { 123 owner_(owner) {
110 DCHECK(upload_url_.is_valid()); 124 DCHECK(upload_url_.is_valid());
111 DCHECK(url_request_context_getter_.get()); 125 DCHECK(url_request_context_getter_.get());
112 DCHECK(!account_id_.empty()); 126 DCHECK(!account_id_.empty());
113 DCHECK(!scopes_.empty()); 127 DCHECK(!scopes_.empty());
114 DCHECK(token_service_provider_); 128 DCHECK(token_service_provider_);
115 DCHECK(owner_);
116 GetToken(); 129 GetToken();
117 } 130 }
118 131
119 AttachmentUploaderImpl::UploadState::~UploadState() { 132 AttachmentUploaderImpl::UploadState::~UploadState() {
120 } 133 }
121 134
135 bool AttachmentUploaderImpl::UploadState::IsStopped() const {
136 DCHECK(CalledOnValidThread());
137 return is_stopped_;
138 }
139
122 void AttachmentUploaderImpl::UploadState::AddUserCallback( 140 void AttachmentUploaderImpl::UploadState::AddUserCallback(
123 const UploadCallback& user_callback) { 141 const UploadCallback& user_callback) {
124 DCHECK(CalledOnValidThread()); 142 DCHECK(CalledOnValidThread());
143 DCHECK(!is_stopped_);
125 user_callbacks_.push_back(user_callback); 144 user_callbacks_.push_back(user_callback);
126 } 145 }
127 146
128 const Attachment& AttachmentUploaderImpl::UploadState::GetAttachment() { 147 const Attachment& AttachmentUploaderImpl::UploadState::GetAttachment() {
129 DCHECK(CalledOnValidThread()); 148 DCHECK(CalledOnValidThread());
130 return attachment_; 149 return attachment_;
131 } 150 }
132 151
133 void AttachmentUploaderImpl::UploadState::OnURLFetchComplete( 152 void AttachmentUploaderImpl::UploadState::OnURLFetchComplete(
134 const net::URLFetcher* source) { 153 const net::URLFetcher* source) {
135 DCHECK(CalledOnValidThread()); 154 DCHECK(CalledOnValidThread());
155 if (is_stopped_) {
156 return;
157 }
158
136 UploadResult result = UPLOAD_TRANSIENT_ERROR; 159 UploadResult result = UPLOAD_TRANSIENT_ERROR;
137 AttachmentId attachment_id = attachment_.GetId(); 160 AttachmentId attachment_id = attachment_.GetId();
138 const int response_code = source->GetResponseCode(); 161 const int response_code = source->GetResponseCode();
139 if (response_code == net::HTTP_OK) { 162 if (response_code == net::HTTP_OK) {
140 result = UPLOAD_SUCCESS; 163 result = UPLOAD_SUCCESS;
141 } else if (response_code == net::HTTP_UNAUTHORIZED) { 164 } else if (response_code == net::HTTP_UNAUTHORIZED) {
142 // Server tells us we've got a bad token so invalidate it. 165 // Server tells us we've got a bad token so invalidate it.
143 OAuth2TokenServiceRequest::InvalidateToken( 166 OAuth2TokenServiceRequest::InvalidateToken(
144 token_service_provider_, account_id_, scopes_, access_token_); 167 token_service_provider_, account_id_, scopes_, access_token_);
145 // Fail the request, but indicate that it may be successful if retried. 168 // Fail the request, but indicate that it may be successful if retried.
146 result = UPLOAD_TRANSIENT_ERROR; 169 result = UPLOAD_TRANSIENT_ERROR;
147 } else if (response_code == net::HTTP_FORBIDDEN) { 170 } else if (response_code == net::HTTP_FORBIDDEN) {
148 // User is not allowed to use attachments. Retrying won't help. 171 // User is not allowed to use attachments. Retrying won't help.
149 result = UPLOAD_UNSPECIFIED_ERROR; 172 result = UPLOAD_UNSPECIFIED_ERROR;
150 } else if (response_code == net::URLFetcher::RESPONSE_CODE_INVALID) { 173 } else if (response_code == net::URLFetcher::RESPONSE_CODE_INVALID) {
151 result = UPLOAD_TRANSIENT_ERROR; 174 result = UPLOAD_TRANSIENT_ERROR;
152 } 175 }
153 ReportResult(result, attachment_id); 176 StopAndReportResult(result, attachment_id);
154 } 177 }
155 178
156 void AttachmentUploaderImpl::UploadState::OnGetTokenSuccess( 179 void AttachmentUploaderImpl::UploadState::OnGetTokenSuccess(
157 const OAuth2TokenService::Request* request, 180 const OAuth2TokenService::Request* request,
158 const std::string& access_token, 181 const std::string& access_token,
159 const base::Time& expiration_time) { 182 const base::Time& expiration_time) {
183 DCHECK(CalledOnValidThread());
184 if (is_stopped_) {
185 return;
186 }
187
160 DCHECK_EQ(access_token_request_.get(), request); 188 DCHECK_EQ(access_token_request_.get(), request);
161 access_token_request_.reset(); 189 access_token_request_.reset();
162 access_token_ = access_token; 190 access_token_ = access_token;
163 fetcher_.reset( 191 fetcher_.reset(
164 net::URLFetcher::Create(upload_url_, net::URLFetcher::POST, this)); 192 net::URLFetcher::Create(upload_url_, net::URLFetcher::POST, this));
165 fetcher_->SetAutomaticallyRetryOn5xx(false); 193 fetcher_->SetAutomaticallyRetryOn5xx(false);
166 fetcher_->SetRequestContext(url_request_context_getter_.get()); 194 fetcher_->SetRequestContext(url_request_context_getter_.get());
167 // TODO(maniscalco): Is there a better way? Copying the attachment data into 195 // TODO(maniscalco): Is there a better way? Copying the attachment data into
168 // a string feels wrong given how large attachments may be (several MBs). If 196 // a string feels wrong given how large attachments may be (several MBs). If
169 // we may end up switching from URLFetcher to URLRequest, this copy won't be 197 // we may end up switching from URLFetcher to URLRequest, this copy won't be
170 // necessary. 198 // necessary.
171 scoped_refptr<base::RefCountedMemory> memory = attachment_.GetData(); 199 scoped_refptr<base::RefCountedMemory> memory = attachment_.GetData();
172 const std::string upload_content(memory->front_as<char>(), memory->size()); 200 const std::string upload_content(memory->front_as<char>(), memory->size());
173 fetcher_->SetUploadData(kContentType, upload_content); 201 fetcher_->SetUploadData(kContentType, upload_content);
174 const std::string auth_header("Authorization: Bearer " + access_token_); 202 const std::string auth_header("Authorization: Bearer " + access_token_);
175 fetcher_->AddExtraRequestHeader(auth_header); 203 fetcher_->AddExtraRequestHeader(auth_header);
176 fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SAVE_COOKIES | 204 fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SAVE_COOKIES |
177 net::LOAD_DO_NOT_SEND_COOKIES | 205 net::LOAD_DO_NOT_SEND_COOKIES |
178 net::LOAD_DISABLE_CACHE); 206 net::LOAD_DISABLE_CACHE);
179 // TODO(maniscalco): Set an appropriate headers (User-Agent, Content-type, and 207 // TODO(maniscalco): Set an appropriate headers (User-Agent, Content-type, and
180 // Content-length) on the request and include the content's MD5, 208 // Content-length) on the request and include the content's MD5,
181 // AttachmentId's unique_id and the "sync birthday" (bug 371521). 209 // AttachmentId's unique_id and the "sync birthday" (bug 371521).
182 fetcher_->Start(); 210 fetcher_->Start();
183 } 211 }
184 212
185 void AttachmentUploaderImpl::UploadState::OnGetTokenFailure( 213 void AttachmentUploaderImpl::UploadState::OnGetTokenFailure(
186 const OAuth2TokenService::Request* request, 214 const OAuth2TokenService::Request* request,
187 const GoogleServiceAuthError& error) { 215 const GoogleServiceAuthError& error) {
216 DCHECK(CalledOnValidThread());
217 if (is_stopped_) {
218 return;
219 }
220
188 DCHECK_EQ(access_token_request_.get(), request); 221 DCHECK_EQ(access_token_request_.get(), request);
189 access_token_request_.reset(); 222 access_token_request_.reset();
190 // TODO(maniscalco): We treat this as a transient error, but it may in fact be 223 // 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 224 // a very long lived error and require user action. Consider differentiating
192 // between the causes of GetToken failure and act accordingly. Think about 225 // between the causes of GetToken failure and act accordingly. Think about
193 // the causes of GetToken failure. Are there (bug 412802). 226 // the causes of GetToken failure. Are there (bug 412802).
194 ReportResult(UPLOAD_TRANSIENT_ERROR, attachment_.GetId()); 227 StopAndReportResult(UPLOAD_TRANSIENT_ERROR, attachment_.GetId());
195 } 228 }
196 229
197 void AttachmentUploaderImpl::UploadState::GetToken() { 230 void AttachmentUploaderImpl::UploadState::GetToken() {
198 access_token_request_ = OAuth2TokenServiceRequest::CreateAndStart( 231 access_token_request_ = OAuth2TokenServiceRequest::CreateAndStart(
199 token_service_provider_, account_id_, scopes_, this); 232 token_service_provider_, account_id_, scopes_, this);
200 } 233 }
201 234
202 void AttachmentUploaderImpl::UploadState::ReportResult( 235 void AttachmentUploaderImpl::UploadState::StopAndReportResult(
203 const UploadResult& result, 236 const UploadResult& result,
204 const AttachmentId& attachment_id) { 237 const AttachmentId& attachment_id) {
238 DCHECK(!is_stopped_);
239 is_stopped_ = true;
205 UploadCallbackList::const_iterator iter = user_callbacks_.begin(); 240 UploadCallbackList::const_iterator iter = user_callbacks_.begin();
206 UploadCallbackList::const_iterator end = user_callbacks_.end(); 241 UploadCallbackList::const_iterator end = user_callbacks_.end();
207 for (; iter != end; ++iter) { 242 for (; iter != end; ++iter) {
208 base::MessageLoop::current()->PostTask( 243 base::MessageLoop::current()->PostTask(
209 FROM_HERE, base::Bind(*iter, result, attachment_id)); 244 FROM_HERE, base::Bind(*iter, result, attachment_id));
210 } 245 }
211 // Destroy this object and return immediately. 246 base::MessageLoop::current()->PostTask(
212 owner_->DeleteUploadStateFor(attachment_.GetId().GetProto().unique_id()); 247 FROM_HERE,
213 return; 248 base::Bind(&AttachmentUploaderImpl::OnUploadStateStopped,
249 owner_,
250 attachment_id.GetProto().unique_id()));
214 } 251 }
215 252
216 AttachmentUploaderImpl::AttachmentUploaderImpl( 253 AttachmentUploaderImpl::AttachmentUploaderImpl(
217 const GURL& sync_service_url, 254 const GURL& sync_service_url,
218 const scoped_refptr<net::URLRequestContextGetter>& 255 const scoped_refptr<net::URLRequestContextGetter>&
219 url_request_context_getter, 256 url_request_context_getter,
220 const std::string& account_id, 257 const std::string& account_id,
221 const OAuth2TokenService::ScopeSet& scopes, 258 const OAuth2TokenService::ScopeSet& scopes,
222 const scoped_refptr<OAuth2TokenServiceRequest::TokenServiceProvider>& 259 const scoped_refptr<OAuth2TokenServiceRequest::TokenServiceProvider>&
223 token_service_provider) 260 token_service_provider)
224 : sync_service_url_(sync_service_url), 261 : sync_service_url_(sync_service_url),
225 url_request_context_getter_(url_request_context_getter), 262 url_request_context_getter_(url_request_context_getter),
226 account_id_(account_id), 263 account_id_(account_id),
227 scopes_(scopes), 264 scopes_(scopes),
228 token_service_provider_(token_service_provider) { 265 token_service_provider_(token_service_provider),
266 weak_ptr_factory_(this) {
229 DCHECK(CalledOnValidThread()); 267 DCHECK(CalledOnValidThread());
230 DCHECK(!account_id.empty()); 268 DCHECK(!account_id.empty());
231 DCHECK(!scopes.empty()); 269 DCHECK(!scopes.empty());
232 DCHECK(token_service_provider_.get()); 270 DCHECK(token_service_provider_.get());
233 } 271 }
234 272
235 AttachmentUploaderImpl::~AttachmentUploaderImpl() { 273 AttachmentUploaderImpl::~AttachmentUploaderImpl() {
236 DCHECK(CalledOnValidThread()); 274 DCHECK(CalledOnValidThread());
237 } 275 }
238 276
239 void AttachmentUploaderImpl::UploadAttachment(const Attachment& attachment, 277 void AttachmentUploaderImpl::UploadAttachment(const Attachment& attachment,
240 const UploadCallback& callback) { 278 const UploadCallback& callback) {
241 DCHECK(CalledOnValidThread()); 279 DCHECK(CalledOnValidThread());
242 const AttachmentId attachment_id = attachment.GetId(); 280 const AttachmentId attachment_id = attachment.GetId();
243 const std::string unique_id = attachment_id.GetProto().unique_id(); 281 const std::string unique_id = attachment_id.GetProto().unique_id();
244 DCHECK(!unique_id.empty()); 282 DCHECK(!unique_id.empty());
245 StateMap::iterator iter = state_map_.find(unique_id); 283 StateMap::iterator iter = state_map_.find(unique_id);
246 if (iter == state_map_.end()) { 284 if (iter != state_map_.end()) {
247 const GURL url = GetURLForAttachmentId(sync_service_url_, attachment_id); 285 // We have an old upload request for this attachment...
248 scoped_ptr<UploadState> upload_state( 286 if (!iter->second->IsStopped()) {
249 new UploadState(url, 287 // "join" to it.
250 url_request_context_getter_, 288 DCHECK(attachment.GetData()
251 attachment, 289 ->Equals(iter->second->GetAttachment().GetData()));
252 callback, 290 iter->second->AddUserCallback(callback);
253 account_id_, 291 return;
254 scopes_, 292 } else {
255 token_service_provider_.get(), 293 // It's stopped so we can't use it. Delete it.
256 this)); 294 state_map_.erase(iter);
257 state_map_.add(unique_id, upload_state.Pass()); 295 }
258 } else {
259 DCHECK(
260 attachment.GetData()->Equals(iter->second->GetAttachment().GetData()));
261 // We already have an upload for this attachment. "Join" it.
262 iter->second->AddUserCallback(callback);
263 } 296 }
297
298 const GURL url = GetURLForAttachmentId(sync_service_url_, attachment_id);
299 scoped_ptr<UploadState> upload_state(
300 new UploadState(url,
301 url_request_context_getter_,
302 attachment,
303 callback,
304 account_id_,
305 scopes_,
306 token_service_provider_.get(),
307 weak_ptr_factory_.GetWeakPtr()));
308 state_map_.add(unique_id, upload_state.Pass());
264 } 309 }
265 310
266 // Static. 311 // Static.
267 GURL AttachmentUploaderImpl::GetURLForAttachmentId( 312 GURL AttachmentUploaderImpl::GetURLForAttachmentId(
268 const GURL& sync_service_url, 313 const GURL& sync_service_url,
269 const AttachmentId& attachment_id) { 314 const AttachmentId& attachment_id) {
270 std::string path = sync_service_url.path(); 315 std::string path = sync_service_url.path();
271 if (path.empty() || *path.rbegin() != '/') { 316 if (path.empty() || *path.rbegin() != '/') {
272 path += '/'; 317 path += '/';
273 } 318 }
274 path += kAttachments; 319 path += kAttachments;
275 path += attachment_id.GetProto().unique_id(); 320 path += attachment_id.GetProto().unique_id();
276 GURL::Replacements replacements; 321 GURL::Replacements replacements;
277 replacements.SetPathStr(path); 322 replacements.SetPathStr(path);
278 return sync_service_url.ReplaceComponents(replacements); 323 return sync_service_url.ReplaceComponents(replacements);
279 } 324 }
280 325
281 void AttachmentUploaderImpl::DeleteUploadStateFor(const UniqueId& unique_id) { 326 void AttachmentUploaderImpl::OnUploadStateStopped(const UniqueId& unique_id) {
282 state_map_.erase(unique_id); 327 StateMap::iterator iter = state_map_.find(unique_id);
328 // Only erase if stopped. Because this method is called asynchronously, it's
329 // possible that a new request for this same id arrived after the UploadState
330 // stopped, but before this method was invoked. In that case the UploadState
331 // in the map might be a new one.
332 if (iter != state_map_.end() && iter->second->IsStopped()) {
333 state_map_.erase(iter);
334 }
283 } 335 }
284 336
285 } // namespace syncer 337 } // namespace syncer
OLDNEW
« no previous file with comments | « no previous file | sync/internal_api/public/attachments/attachment_uploader_impl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698