Update broken references to image assets
[chromium-blink-merge.git] / chrome / browser / chromeos / drive / sync / remove_performer.cc
blob63245cd3c89b7ccd747ac2dd017c145c607ac162
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/chromeos/drive/sync/remove_performer.h"
7 #include "base/sequenced_task_runner.h"
8 #include "chrome/browser/chromeos/drive/file_system/operation_delegate.h"
9 #include "chrome/browser/chromeos/drive/sync/entry_revert_performer.h"
10 #include "components/drive/drive.pb.h"
11 #include "components/drive/drive_api_util.h"
12 #include "components/drive/file_system_core_util.h"
13 #include "components/drive/job_scheduler.h"
14 #include "components/drive/resource_entry_conversion.h"
15 #include "components/drive/resource_metadata.h"
16 #include "google_apis/drive/drive_api_parser.h"
18 namespace drive {
19 namespace internal {
21 namespace {
23 // Updates local metadata and after remote unparenting.
24 FileError UpdateLocalStateAfterUnparent(ResourceMetadata* metadata,
25 const std::string& local_id) {
26 ResourceEntry entry;
27 FileError error = metadata->GetResourceEntryById(local_id, &entry);
28 if (error != FILE_ERROR_OK)
29 return error;
30 entry.set_parent_local_id(util::kDriveOtherDirLocalId);
31 return metadata->RefreshEntry(entry);
34 // Utility function to run ResourceMetadata::RemoveEntry from UI thread.
35 void RemoveEntryOnUIThread(base::SequencedTaskRunner* blocking_task_runner,
36 ResourceMetadata* metadata,
37 const std::string& local_id,
38 const FileOperationCallback& callback) {
39 base::PostTaskAndReplyWithResult(
40 blocking_task_runner,
41 FROM_HERE,
42 base::Bind(&ResourceMetadata::RemoveEntry,
43 base::Unretained(metadata), local_id),
44 callback);
47 } // namespace
49 RemovePerformer::RemovePerformer(
50 base::SequencedTaskRunner* blocking_task_runner,
51 file_system::OperationDelegate* delegate,
52 JobScheduler* scheduler,
53 ResourceMetadata* metadata)
54 : blocking_task_runner_(blocking_task_runner),
55 delegate_(delegate),
56 scheduler_(scheduler),
57 metadata_(metadata),
58 entry_revert_performer_(new EntryRevertPerformer(blocking_task_runner,
59 delegate,
60 scheduler,
61 metadata)),
62 weak_ptr_factory_(this) {
65 RemovePerformer::~RemovePerformer() {
66 DCHECK(thread_checker_.CalledOnValidThread());
69 // Returns |entry| corresponding to |local_id|.
70 // Adding to that, removes the entry when it does not exist on the server.
71 FileError TryToRemoveLocally(ResourceMetadata* metadata,
72 const std::string& local_id,
73 ResourceEntry* entry) {
74 FileError error = metadata->GetResourceEntryById(local_id, entry);
75 if (error != FILE_ERROR_OK || !entry->resource_id().empty())
76 return error;
77 return metadata->RemoveEntry(local_id);
80 void RemovePerformer::Remove(const std::string& local_id,
81 const ClientContext& context,
82 const FileOperationCallback& callback) {
83 DCHECK(thread_checker_.CalledOnValidThread());
84 DCHECK(!callback.is_null());
86 ResourceEntry* entry = new ResourceEntry;
87 base::PostTaskAndReplyWithResult(
88 blocking_task_runner_.get(),
89 FROM_HERE,
90 base::Bind(&TryToRemoveLocally, metadata_, local_id, entry),
91 base::Bind(&RemovePerformer::RemoveAfterGetResourceEntry,
92 weak_ptr_factory_.GetWeakPtr(),
93 context,
94 callback,
95 base::Owned(entry)));
98 void RemovePerformer::RemoveAfterGetResourceEntry(
99 const ClientContext& context,
100 const FileOperationCallback& callback,
101 const ResourceEntry* entry,
102 FileError error) {
103 DCHECK(thread_checker_.CalledOnValidThread());
104 DCHECK(!callback.is_null());
106 if (error != FILE_ERROR_OK || entry->resource_id().empty()) {
107 callback.Run(error);
108 return;
111 // To match with the behavior of drive.google.com:
112 // Removal of shared entries under MyDrive is just removing from the parent.
113 // The entry will stay in shared-with-me (in other words, in "drive/other".)
115 // TODO(kinaba): to be more precise, we might be better to branch by whether
116 // or not the current account is an owner of the file. The code below is
117 // written under the assumption that |shared_with_me| coincides with that.
118 if (entry->shared_with_me()) {
119 UnparentResource(context, callback, entry->resource_id(),
120 entry->local_id());
121 } else {
122 // Otherwise try sending the entry to trash.
123 TrashResource(context, callback, entry->resource_id(), entry->local_id());
127 void RemovePerformer::TrashResource(const ClientContext& context,
128 const FileOperationCallback& callback,
129 const std::string& resource_id,
130 const std::string& local_id) {
131 DCHECK(thread_checker_.CalledOnValidThread());
132 DCHECK(!callback.is_null());
134 scheduler_->TrashResource(
135 resource_id,
136 context,
137 base::Bind(&RemovePerformer::TrashResourceAfterUpdateRemoteState,
138 weak_ptr_factory_.GetWeakPtr(), context, callback, local_id));
141 void RemovePerformer::TrashResourceAfterUpdateRemoteState(
142 const ClientContext& context,
143 const FileOperationCallback& callback,
144 const std::string& local_id,
145 google_apis::DriveApiErrorCode status) {
146 DCHECK(thread_checker_.CalledOnValidThread());
147 DCHECK(!callback.is_null());
149 if (status == google_apis::HTTP_FORBIDDEN) {
150 // Editing this entry is not allowed, revert local changes.
151 entry_revert_performer_->RevertEntry(local_id, context, callback);
152 delegate_->OnDriveSyncError(
153 file_system::DRIVE_SYNC_ERROR_DELETE_WITHOUT_PERMISSION, local_id);
154 return;
157 FileError error = GDataToFileError(status);
158 if (error == FILE_ERROR_NOT_FOUND) { // Remove local entry when not found.
159 RemoveEntryOnUIThread(blocking_task_runner_.get(), metadata_, local_id,
160 callback);
161 return;
164 // Now we're done. If the entry is trashed on the server, it'll be also
165 // deleted locally on the next update.
166 callback.Run(error);
169 void RemovePerformer::UnparentResource(const ClientContext& context,
170 const FileOperationCallback& callback,
171 const std::string& resource_id,
172 const std::string& local_id) {
173 DCHECK(thread_checker_.CalledOnValidThread());
174 DCHECK(!callback.is_null());
176 scheduler_->GetFileResource(
177 resource_id,
178 context,
179 base::Bind(&RemovePerformer::UnparentResourceAfterGetFileResource,
180 weak_ptr_factory_.GetWeakPtr(), context, callback, local_id));
183 void RemovePerformer::UnparentResourceAfterGetFileResource(
184 const ClientContext& context,
185 const FileOperationCallback& callback,
186 const std::string& local_id,
187 google_apis::DriveApiErrorCode status,
188 scoped_ptr<google_apis::FileResource> file_resource) {
189 DCHECK(thread_checker_.CalledOnValidThread());
190 DCHECK(!callback.is_null());
192 FileError error = GDataToFileError(status);
193 if (error == FILE_ERROR_NOT_FOUND) { // Remove local entry when not found.
194 RemoveEntryOnUIThread(blocking_task_runner_.get(), metadata_, local_id,
195 callback);
196 return;
199 if (error != FILE_ERROR_OK) {
200 callback.Run(error);
201 return;
204 ResourceEntry entry;
205 std::string parent_resource_id;
206 if (!ConvertFileResourceToResourceEntry(*file_resource, &entry,
207 &parent_resource_id)) {
208 callback.Run(FILE_ERROR_NOT_A_FILE);
209 return;
212 if (!entry.shared_with_me()) {
213 // shared_with_me() has changed on the server.
214 UnparentResourceAfterUpdateRemoteState(callback, local_id,
215 google_apis::HTTP_CONFLICT);
216 return;
219 if (parent_resource_id.empty()) {
220 // This entry is unparented already.
221 UnparentResourceAfterUpdateRemoteState(callback, local_id,
222 google_apis::HTTP_NO_CONTENT);
223 return;
226 scheduler_->RemoveResourceFromDirectory(
227 parent_resource_id,
228 entry.resource_id(),
229 context,
230 base::Bind(&RemovePerformer::UnparentResourceAfterUpdateRemoteState,
231 weak_ptr_factory_.GetWeakPtr(), callback, local_id));
234 void RemovePerformer::UnparentResourceAfterUpdateRemoteState(
235 const FileOperationCallback& callback,
236 const std::string& local_id,
237 google_apis::DriveApiErrorCode status) {
238 DCHECK(thread_checker_.CalledOnValidThread());
239 DCHECK(!callback.is_null());
241 FileError error = GDataToFileError(status);
242 if (error != FILE_ERROR_OK) {
243 callback.Run(error);
244 return;
247 base::PostTaskAndReplyWithResult(
248 blocking_task_runner_.get(),
249 FROM_HERE,
250 base::Bind(&UpdateLocalStateAfterUnparent, metadata_, local_id),
251 callback);
254 } // namespace internal
255 } // namespace drive