Revert of Add button to add new FSP services to Files app. (patchset #8 id:140001...
[chromium-blink-merge.git] / chrome / browser / chromeos / drive / sync / remove_performer.cc
blobdb1a34a544b1807bba2969d21e61f93f658ca226
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/drive.pb.h"
9 #include "chrome/browser/chromeos/drive/file_system/operation_delegate.h"
10 #include "chrome/browser/chromeos/drive/file_system_util.h"
11 #include "chrome/browser/chromeos/drive/job_scheduler.h"
12 #include "chrome/browser/chromeos/drive/resource_entry_conversion.h"
13 #include "chrome/browser/chromeos/drive/resource_metadata.h"
14 #include "chrome/browser/chromeos/drive/sync/entry_revert_performer.h"
15 #include "chrome/browser/drive/drive_api_util.h"
16 #include "content/public/browser/browser_thread.h"
17 #include "google_apis/drive/drive_api_parser.h"
19 using content::BrowserThread;
21 namespace drive {
22 namespace internal {
24 namespace {
26 // Updates local metadata and after remote unparenting.
27 FileError UpdateLocalStateAfterUnparent(ResourceMetadata* metadata,
28 const std::string& local_id) {
29 ResourceEntry entry;
30 FileError error = metadata->GetResourceEntryById(local_id, &entry);
31 if (error != FILE_ERROR_OK)
32 return error;
33 entry.set_parent_local_id(util::kDriveOtherDirLocalId);
34 return metadata->RefreshEntry(entry);
37 // Utility function to run ResourceMetadata::RemoveEntry from UI thread.
38 void RemoveEntryOnUIThread(base::SequencedTaskRunner* blocking_task_runner,
39 ResourceMetadata* metadata,
40 const std::string& local_id,
41 const FileOperationCallback& callback) {
42 base::PostTaskAndReplyWithResult(
43 blocking_task_runner,
44 FROM_HERE,
45 base::Bind(&ResourceMetadata::RemoveEntry,
46 base::Unretained(metadata), local_id),
47 callback);
50 } // namespace
52 RemovePerformer::RemovePerformer(
53 base::SequencedTaskRunner* blocking_task_runner,
54 file_system::OperationDelegate* delegate,
55 JobScheduler* scheduler,
56 ResourceMetadata* metadata)
57 : blocking_task_runner_(blocking_task_runner),
58 delegate_(delegate),
59 scheduler_(scheduler),
60 metadata_(metadata),
61 entry_revert_performer_(new EntryRevertPerformer(blocking_task_runner,
62 delegate,
63 scheduler,
64 metadata)),
65 weak_ptr_factory_(this) {
66 DCHECK_CURRENTLY_ON(BrowserThread::UI);
69 RemovePerformer::~RemovePerformer() {
70 DCHECK_CURRENTLY_ON(BrowserThread::UI);
73 // Returns |entry| corresponding to |local_id|.
74 // Adding to that, removes the entry when it does not exist on the server.
75 FileError TryToRemoveLocally(ResourceMetadata* metadata,
76 const std::string& local_id,
77 ResourceEntry* entry) {
78 FileError error = metadata->GetResourceEntryById(local_id, entry);
79 if (error != FILE_ERROR_OK || !entry->resource_id().empty())
80 return error;
81 return metadata->RemoveEntry(local_id);
84 void RemovePerformer::Remove(const std::string& local_id,
85 const ClientContext& context,
86 const FileOperationCallback& callback) {
87 DCHECK_CURRENTLY_ON(BrowserThread::UI);
88 DCHECK(!callback.is_null());
90 ResourceEntry* entry = new ResourceEntry;
91 base::PostTaskAndReplyWithResult(
92 blocking_task_runner_.get(),
93 FROM_HERE,
94 base::Bind(&TryToRemoveLocally, metadata_, local_id, entry),
95 base::Bind(&RemovePerformer::RemoveAfterGetResourceEntry,
96 weak_ptr_factory_.GetWeakPtr(),
97 context,
98 callback,
99 base::Owned(entry)));
102 void RemovePerformer::RemoveAfterGetResourceEntry(
103 const ClientContext& context,
104 const FileOperationCallback& callback,
105 const ResourceEntry* entry,
106 FileError error) {
107 DCHECK_CURRENTLY_ON(BrowserThread::UI);
108 DCHECK(!callback.is_null());
110 if (error != FILE_ERROR_OK || entry->resource_id().empty()) {
111 callback.Run(error);
112 return;
115 // To match with the behavior of drive.google.com:
116 // Removal of shared entries under MyDrive is just removing from the parent.
117 // The entry will stay in shared-with-me (in other words, in "drive/other".)
119 // TODO(kinaba): to be more precise, we might be better to branch by whether
120 // or not the current account is an owner of the file. The code below is
121 // written under the assumption that |shared_with_me| coincides with that.
122 if (entry->shared_with_me()) {
123 UnparentResource(context, callback, entry->resource_id(),
124 entry->local_id());
125 } else {
126 // Otherwise try sending the entry to trash.
127 TrashResource(context, callback, entry->resource_id(), entry->local_id());
131 void RemovePerformer::TrashResource(const ClientContext& context,
132 const FileOperationCallback& callback,
133 const std::string& resource_id,
134 const std::string& local_id) {
135 DCHECK_CURRENTLY_ON(BrowserThread::UI);
136 DCHECK(!callback.is_null());
138 scheduler_->TrashResource(
139 resource_id,
140 context,
141 base::Bind(&RemovePerformer::TrashResourceAfterUpdateRemoteState,
142 weak_ptr_factory_.GetWeakPtr(), context, callback, local_id));
145 void RemovePerformer::TrashResourceAfterUpdateRemoteState(
146 const ClientContext& context,
147 const FileOperationCallback& callback,
148 const std::string& local_id,
149 google_apis::DriveApiErrorCode status) {
150 DCHECK_CURRENTLY_ON(BrowserThread::UI);
151 DCHECK(!callback.is_null());
153 if (status == google_apis::HTTP_FORBIDDEN) {
154 // Editing this entry is not allowed, revert local changes.
155 entry_revert_performer_->RevertEntry(local_id, context, callback);
156 delegate_->OnDriveSyncError(
157 file_system::DRIVE_SYNC_ERROR_DELETE_WITHOUT_PERMISSION, local_id);
158 return;
161 FileError error = GDataToFileError(status);
162 if (error == FILE_ERROR_NOT_FOUND) { // Remove local entry when not found.
163 RemoveEntryOnUIThread(blocking_task_runner_.get(), metadata_, local_id,
164 callback);
165 return;
168 // Now we're done. If the entry is trashed on the server, it'll be also
169 // deleted locally on the next update.
170 callback.Run(error);
173 void RemovePerformer::UnparentResource(const ClientContext& context,
174 const FileOperationCallback& callback,
175 const std::string& resource_id,
176 const std::string& local_id) {
177 DCHECK_CURRENTLY_ON(BrowserThread::UI);
178 DCHECK(!callback.is_null());
180 scheduler_->GetFileResource(
181 resource_id,
182 context,
183 base::Bind(&RemovePerformer::UnparentResourceAfterGetFileResource,
184 weak_ptr_factory_.GetWeakPtr(), context, callback, local_id));
187 void RemovePerformer::UnparentResourceAfterGetFileResource(
188 const ClientContext& context,
189 const FileOperationCallback& callback,
190 const std::string& local_id,
191 google_apis::DriveApiErrorCode status,
192 scoped_ptr<google_apis::FileResource> file_resource) {
193 DCHECK_CURRENTLY_ON(BrowserThread::UI);
194 DCHECK(!callback.is_null());
196 FileError error = GDataToFileError(status);
197 if (error == FILE_ERROR_NOT_FOUND) { // Remove local entry when not found.
198 RemoveEntryOnUIThread(blocking_task_runner_.get(), metadata_, local_id,
199 callback);
200 return;
203 if (error != FILE_ERROR_OK) {
204 callback.Run(error);
205 return;
208 ResourceEntry entry;
209 std::string parent_resource_id;
210 if (!ConvertFileResourceToResourceEntry(*file_resource, &entry,
211 &parent_resource_id)) {
212 callback.Run(FILE_ERROR_NOT_A_FILE);
213 return;
216 if (!entry.shared_with_me()) {
217 // shared_with_me() has changed on the server.
218 UnparentResourceAfterUpdateRemoteState(callback, local_id,
219 google_apis::HTTP_CONFLICT);
220 return;
223 if (parent_resource_id.empty()) {
224 // This entry is unparented already.
225 UnparentResourceAfterUpdateRemoteState(callback, local_id,
226 google_apis::HTTP_NO_CONTENT);
227 return;
230 scheduler_->RemoveResourceFromDirectory(
231 parent_resource_id,
232 entry.resource_id(),
233 context,
234 base::Bind(&RemovePerformer::UnparentResourceAfterUpdateRemoteState,
235 weak_ptr_factory_.GetWeakPtr(), callback, local_id));
238 void RemovePerformer::UnparentResourceAfterUpdateRemoteState(
239 const FileOperationCallback& callback,
240 const std::string& local_id,
241 google_apis::DriveApiErrorCode status) {
242 DCHECK_CURRENTLY_ON(BrowserThread::UI);
243 DCHECK(!callback.is_null());
245 FileError error = GDataToFileError(status);
246 if (error != FILE_ERROR_OK) {
247 callback.Run(error);
248 return;
251 base::PostTaskAndReplyWithResult(
252 blocking_task_runner_.get(),
253 FROM_HERE,
254 base::Bind(&UpdateLocalStateAfterUnparent, metadata_, local_id),
255 callback);
258 } // namespace internal
259 } // namespace drive