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/api/attachments/attachment_service_impl.h" | 5 #include "sync/api/attachments/attachment_service_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 "sync/api/attachments/attachment.h" | 9 #include "sync/api/attachments/attachment.h" |
| 10 #include "sync/internal_api/public/attachments/fake_attachment_downloader.h" |
10 #include "sync/internal_api/public/attachments/fake_attachment_store.h" | 11 #include "sync/internal_api/public/attachments/fake_attachment_store.h" |
11 #include "sync/internal_api/public/attachments/fake_attachment_uploader.h" | 12 #include "sync/internal_api/public/attachments/fake_attachment_uploader.h" |
12 | 13 |
13 namespace syncer { | 14 namespace syncer { |
14 | 15 |
| 16 // GetOrDownloadAttachments starts multiple parallel DownloadAttachment calls. |
| 17 // GetOrDownloadState tracks completion of these calls and posts callback for |
| 18 // consumer once all attachments are either retrieved or reported unavailable. |
| 19 class AttachmentServiceImpl::GetOrDownloadState |
| 20 : public base::RefCounted<GetOrDownloadState>, |
| 21 public base::NonThreadSafe { |
| 22 public: |
| 23 // GetOrDownloadState gets parameter from values passed to |
| 24 // AttachmentService::GetOrDownloadAttachments. |
| 25 // |attachment_ids| is a list of attachmens to retrieve. |
| 26 // |callback| will be posted on current thread when all attachments retrieved |
| 27 // or confirmed unavailable. |
| 28 GetOrDownloadState(const AttachmentIdList& attachment_ids, |
| 29 const GetOrDownloadCallback& callback); |
| 30 |
| 31 // Attachment was just retrieved. Add it to retrieved attachments. |
| 32 void AddAttachment(const Attachment& attachment); |
| 33 |
| 34 // Both reading from local store and downloading attachment failed. |
| 35 // Add it to unavailable set. |
| 36 void AddUnavailableAttachmentId(const AttachmentId& attachment_id); |
| 37 |
| 38 private: |
| 39 friend class base::RefCounted<GetOrDownloadState>; |
| 40 virtual ~GetOrDownloadState(); |
| 41 |
| 42 // If all attachment requests completed then post callback to consumer with |
| 43 // results. |
| 44 void PostResultIfAllRequestsCompleted(); |
| 45 |
| 46 GetOrDownloadCallback callback_; |
| 47 |
| 48 // Requests for these attachments are still in progress. |
| 49 AttachmentIdSet in_progress_attachments_; |
| 50 |
| 51 AttachmentIdSet unavailable_attachments_; |
| 52 scoped_ptr<AttachmentMap> retrieved_attachments_; |
| 53 |
| 54 DISALLOW_COPY_AND_ASSIGN(GetOrDownloadState); |
| 55 }; |
| 56 |
| 57 AttachmentServiceImpl::GetOrDownloadState::GetOrDownloadState( |
| 58 const AttachmentIdList& attachment_ids, |
| 59 const GetOrDownloadCallback& callback) |
| 60 : callback_(callback), retrieved_attachments_(new AttachmentMap()) { |
| 61 std::copy( |
| 62 attachment_ids.begin(), |
| 63 attachment_ids.end(), |
| 64 std::inserter(in_progress_attachments_, in_progress_attachments_.end())); |
| 65 PostResultIfAllRequestsCompleted(); |
| 66 } |
| 67 |
| 68 AttachmentServiceImpl::GetOrDownloadState::~GetOrDownloadState() { |
| 69 DCHECK(CalledOnValidThread()); |
| 70 } |
| 71 |
| 72 void AttachmentServiceImpl::GetOrDownloadState::AddAttachment( |
| 73 const Attachment& attachment) { |
| 74 DCHECK(CalledOnValidThread()); |
| 75 DCHECK(retrieved_attachments_->find(attachment.GetId()) == |
| 76 retrieved_attachments_->end()); |
| 77 retrieved_attachments_->insert( |
| 78 std::make_pair(attachment.GetId(), attachment)); |
| 79 DCHECK(in_progress_attachments_.find(attachment.GetId()) != |
| 80 in_progress_attachments_.end()); |
| 81 in_progress_attachments_.erase(attachment.GetId()); |
| 82 PostResultIfAllRequestsCompleted(); |
| 83 } |
| 84 |
| 85 void AttachmentServiceImpl::GetOrDownloadState::AddUnavailableAttachmentId( |
| 86 const AttachmentId& attachment_id) { |
| 87 DCHECK(CalledOnValidThread()); |
| 88 DCHECK(unavailable_attachments_.find(attachment_id) == |
| 89 unavailable_attachments_.end()); |
| 90 unavailable_attachments_.insert(attachment_id); |
| 91 DCHECK(in_progress_attachments_.find(attachment_id) != |
| 92 in_progress_attachments_.end()); |
| 93 in_progress_attachments_.erase(attachment_id); |
| 94 PostResultIfAllRequestsCompleted(); |
| 95 } |
| 96 |
| 97 void |
| 98 AttachmentServiceImpl::GetOrDownloadState::PostResultIfAllRequestsCompleted() { |
| 99 if (in_progress_attachments_.empty()) { |
| 100 // All requests completed. Let's notify consumer. |
| 101 GetOrDownloadResult result = |
| 102 unavailable_attachments_.empty() ? GET_SUCCESS : GET_UNSPECIFIED_ERROR; |
| 103 base::MessageLoop::current()->PostTask( |
| 104 FROM_HERE, |
| 105 base::Bind(callback_, result, base::Passed(&retrieved_attachments_))); |
| 106 } |
| 107 } |
| 108 |
15 AttachmentServiceImpl::AttachmentServiceImpl( | 109 AttachmentServiceImpl::AttachmentServiceImpl( |
16 scoped_ptr<AttachmentStore> attachment_store, | 110 scoped_ptr<AttachmentStore> attachment_store, |
17 scoped_ptr<AttachmentUploader> attachment_uploader, | 111 scoped_ptr<AttachmentUploader> attachment_uploader, |
| 112 scoped_ptr<AttachmentDownloader> attachment_downloader, |
18 Delegate* delegate) | 113 Delegate* delegate) |
19 : attachment_store_(attachment_store.Pass()), | 114 : attachment_store_(attachment_store.Pass()), |
20 attachment_uploader_(attachment_uploader.Pass()), | 115 attachment_uploader_(attachment_uploader.Pass()), |
| 116 attachment_downloader_(attachment_downloader.Pass()), |
21 delegate_(delegate), | 117 delegate_(delegate), |
22 weak_ptr_factory_(this) { | 118 weak_ptr_factory_(this) { |
23 DCHECK(CalledOnValidThread()); | 119 DCHECK(CalledOnValidThread()); |
24 DCHECK(attachment_store_); | 120 DCHECK(attachment_store_); |
25 DCHECK(attachment_uploader_); | 121 DCHECK(attachment_uploader_); |
26 } | 122 } |
27 | 123 |
28 AttachmentServiceImpl::~AttachmentServiceImpl() { | 124 AttachmentServiceImpl::~AttachmentServiceImpl() { |
29 DCHECK(CalledOnValidThread()); | 125 DCHECK(CalledOnValidThread()); |
30 } | 126 } |
31 | 127 |
32 // Static. | 128 // Static. |
33 scoped_ptr<syncer::AttachmentService> AttachmentServiceImpl::CreateForTest() { | 129 scoped_ptr<syncer::AttachmentService> AttachmentServiceImpl::CreateForTest() { |
34 scoped_ptr<syncer::AttachmentStore> attachment_store( | 130 scoped_ptr<syncer::AttachmentStore> attachment_store( |
35 new syncer::FakeAttachmentStore(base::MessageLoopProxy::current())); | 131 new syncer::FakeAttachmentStore(base::MessageLoopProxy::current())); |
36 scoped_ptr<AttachmentUploader> attachment_uploader( | 132 scoped_ptr<AttachmentUploader> attachment_uploader( |
37 new FakeAttachmentUploader); | 133 new FakeAttachmentUploader); |
| 134 scoped_ptr<AttachmentDownloader> attachment_downloader( |
| 135 new FakeAttachmentDownloader()); |
38 scoped_ptr<syncer::AttachmentService> attachment_service( | 136 scoped_ptr<syncer::AttachmentService> attachment_service( |
39 new syncer::AttachmentServiceImpl( | 137 new syncer::AttachmentServiceImpl(attachment_store.Pass(), |
40 attachment_store.Pass(), attachment_uploader.Pass(), NULL)); | 138 attachment_uploader.Pass(), |
| 139 attachment_downloader.Pass(), |
| 140 NULL)); |
41 return attachment_service.Pass(); | 141 return attachment_service.Pass(); |
42 } | 142 } |
43 | 143 |
44 void AttachmentServiceImpl::GetOrDownloadAttachments( | 144 void AttachmentServiceImpl::GetOrDownloadAttachments( |
45 const AttachmentIdList& attachment_ids, | 145 const AttachmentIdList& attachment_ids, |
46 const GetOrDownloadCallback& callback) { | 146 const GetOrDownloadCallback& callback) { |
47 DCHECK(CalledOnValidThread()); | 147 DCHECK(CalledOnValidThread()); |
| 148 scoped_refptr<GetOrDownloadState> state( |
| 149 new GetOrDownloadState(attachment_ids, callback)); |
48 attachment_store_->Read(attachment_ids, | 150 attachment_store_->Read(attachment_ids, |
49 base::Bind(&AttachmentServiceImpl::ReadDone, | 151 base::Bind(&AttachmentServiceImpl::ReadDone, |
50 weak_ptr_factory_.GetWeakPtr(), | 152 weak_ptr_factory_.GetWeakPtr(), |
51 callback)); | 153 state)); |
52 } | 154 } |
53 | 155 |
54 void AttachmentServiceImpl::DropAttachments( | 156 void AttachmentServiceImpl::DropAttachments( |
55 const AttachmentIdList& attachment_ids, | 157 const AttachmentIdList& attachment_ids, |
56 const DropCallback& callback) { | 158 const DropCallback& callback) { |
57 DCHECK(CalledOnValidThread()); | 159 DCHECK(CalledOnValidThread()); |
58 attachment_store_->Drop(attachment_ids, | 160 attachment_store_->Drop(attachment_ids, |
59 base::Bind(&AttachmentServiceImpl::DropDone, | 161 base::Bind(&AttachmentServiceImpl::DropDone, |
60 weak_ptr_factory_.GetWeakPtr(), | 162 weak_ptr_factory_.GetWeakPtr(), |
61 callback)); | 163 callback)); |
(...skipping 27 matching lines...) Expand all Loading... |
89 const AttachmentIdList& old_attachment_ids, | 191 const AttachmentIdList& old_attachment_ids, |
90 const SyncData& updated_sync_data) { | 192 const SyncData& updated_sync_data) { |
91 DCHECK(CalledOnValidThread()); | 193 DCHECK(CalledOnValidThread()); |
92 // TODO(maniscalco): At this point we need to ensure we write all new | 194 // TODO(maniscalco): At this point we need to ensure we write all new |
93 // attachments referenced by updated_sync_data to local storage and schedule | 195 // attachments referenced by updated_sync_data to local storage and schedule |
94 // them up upload to the server. We also need to remove any no unreferenced | 196 // them up upload to the server. We also need to remove any no unreferenced |
95 // attachments from local storage (bug 356351). | 197 // attachments from local storage (bug 356351). |
96 } | 198 } |
97 | 199 |
98 void AttachmentServiceImpl::ReadDone( | 200 void AttachmentServiceImpl::ReadDone( |
99 const GetOrDownloadCallback& callback, | 201 const scoped_refptr<GetOrDownloadState>& state, |
100 const AttachmentStore::Result& result, | 202 const AttachmentStore::Result& result, |
101 scoped_ptr<AttachmentMap> attachments, | 203 scoped_ptr<AttachmentMap> attachments, |
102 scoped_ptr<AttachmentIdList> unavailable_attachment_ids) { | 204 scoped_ptr<AttachmentIdList> unavailable_attachment_ids) { |
103 AttachmentService::GetOrDownloadResult get_result = | 205 // Add read attachments to result. |
104 AttachmentService::GET_UNSPECIFIED_ERROR; | 206 for (AttachmentMap::const_iterator iter = attachments->begin(); |
105 if (result == AttachmentStore::SUCCESS) { | 207 iter != attachments->end(); |
106 get_result = AttachmentService::GET_SUCCESS; | 208 ++iter) { |
| 209 state->AddAttachment(iter->second); |
107 } | 210 } |
108 // TODO(maniscalco): Deal with case where an error occurred (bug 361251). | 211 // Try to download locally unavailable attachments. |
109 base::MessageLoop::current()->PostTask( | 212 for (AttachmentIdList::const_iterator iter = |
110 FROM_HERE, base::Bind(callback, get_result, base::Passed(&attachments))); | 213 unavailable_attachment_ids->begin(); |
| 214 iter != unavailable_attachment_ids->end(); |
| 215 ++iter) { |
| 216 attachment_downloader_->DownloadAttachment( |
| 217 *iter, |
| 218 base::Bind(&AttachmentServiceImpl::DownloadDone, |
| 219 weak_ptr_factory_.GetWeakPtr(), |
| 220 state, |
| 221 *iter)); |
| 222 ; |
| 223 } |
111 } | 224 } |
112 | 225 |
113 void AttachmentServiceImpl::DropDone(const DropCallback& callback, | 226 void AttachmentServiceImpl::DropDone(const DropCallback& callback, |
114 const AttachmentStore::Result& result) { | 227 const AttachmentStore::Result& result) { |
115 AttachmentService::DropResult drop_result = | 228 AttachmentService::DropResult drop_result = |
116 AttachmentService::DROP_UNSPECIFIED_ERROR; | 229 AttachmentService::DROP_UNSPECIFIED_ERROR; |
117 if (result == AttachmentStore::SUCCESS) { | 230 if (result == AttachmentStore::SUCCESS) { |
118 drop_result = AttachmentService::DROP_SUCCESS; | 231 drop_result = AttachmentService::DROP_SUCCESS; |
119 } | 232 } |
120 // TODO(maniscalco): Deal with case where an error occurred (bug 361251). | 233 // TODO(maniscalco): Deal with case where an error occurred (bug 361251). |
(...skipping 17 matching lines...) Expand all Loading... |
138 const AttachmentUploader::UploadResult& result, | 251 const AttachmentUploader::UploadResult& result, |
139 const AttachmentId& attachment_id) { | 252 const AttachmentId& attachment_id) { |
140 // TODO(pavely): crbug/372622: Deal with UploadAttachment failures. | 253 // TODO(pavely): crbug/372622: Deal with UploadAttachment failures. |
141 if (result != AttachmentUploader::UPLOAD_SUCCESS) | 254 if (result != AttachmentUploader::UPLOAD_SUCCESS) |
142 return; | 255 return; |
143 if (delegate_) { | 256 if (delegate_) { |
144 delegate_->OnAttachmentUploaded(attachment_id); | 257 delegate_->OnAttachmentUploaded(attachment_id); |
145 } | 258 } |
146 } | 259 } |
147 | 260 |
| 261 void AttachmentServiceImpl::DownloadDone( |
| 262 const scoped_refptr<GetOrDownloadState>& state, |
| 263 const AttachmentId& attachment_id, |
| 264 const AttachmentDownloader::DownloadResult& result, |
| 265 scoped_ptr<Attachment> attachment) { |
| 266 if (result == AttachmentDownloader::DOWNLOAD_SUCCESS) { |
| 267 state->AddAttachment(*attachment.get()); |
| 268 } else { |
| 269 state->AddUnavailableAttachmentId(attachment_id); |
| 270 } |
| 271 } |
| 272 |
148 } // namespace syncer | 273 } // namespace syncer |
OLD | NEW |