Disable view source for Developer Tools.
[chromium-blink-merge.git] / chrome / browser / chromeos / drive / sync / remove_performer.cc
blob2769547525a96791567d0c85669a057f9433cd0c
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_observer.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/sync/entry_revert_performer.h"
14 #include "content/public/browser/browser_thread.h"
16 using content::BrowserThread;
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::OperationObserver* observer,
52 JobScheduler* scheduler,
53 ResourceMetadata* metadata)
54 : blocking_task_runner_(blocking_task_runner),
55 observer_(observer),
56 scheduler_(scheduler),
57 metadata_(metadata),
58 entry_revert_performer_(new EntryRevertPerformer(blocking_task_runner,
59 observer,
60 scheduler,
61 metadata)),
62 weak_ptr_factory_(this) {
63 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
66 RemovePerformer::~RemovePerformer() {
67 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
70 void RemovePerformer::Remove(const std::string& local_id,
71 const FileOperationCallback& callback) {
72 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
73 DCHECK(!callback.is_null());
75 ResourceEntry* entry = new ResourceEntry;
76 base::PostTaskAndReplyWithResult(
77 blocking_task_runner_.get(),
78 FROM_HERE,
79 base::Bind(&ResourceMetadata::GetResourceEntryById,
80 base::Unretained(metadata_),
81 local_id,
82 entry),
83 base::Bind(&RemovePerformer::RemoveAfterGetResourceEntry,
84 weak_ptr_factory_.GetWeakPtr(),
85 callback,
86 base::Owned(entry)));
89 void RemovePerformer::RemoveAfterGetResourceEntry(
90 const FileOperationCallback& callback,
91 const ResourceEntry* entry,
92 FileError error) {
93 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
94 DCHECK(!callback.is_null());
96 if (error != FILE_ERROR_OK) {
97 callback.Run(error);
98 return;
101 // To match with the behavior of drive.google.com:
102 // Removal of shared entries under MyDrive is just removing from the parent.
103 // The entry will stay in shared-with-me (in other words, in "drive/other".)
105 // TODO(kinaba): to be more precise, we might be better to branch by whether
106 // or not the current account is an owner of the file. The code below is
107 // written under the assumption that |shared_with_me| coincides with that.
108 if (entry->shared_with_me()) {
109 UnparentResource(callback, entry->resource_id(), entry->local_id());
110 } else {
111 // Otherwise try sending the entry to trash.
112 TrashResource(callback, entry->resource_id(), entry->local_id());
116 void RemovePerformer::TrashResource(const FileOperationCallback& callback,
117 const std::string& resource_id,
118 const std::string& local_id) {
119 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
120 DCHECK(!callback.is_null());
122 scheduler_->TrashResource(
123 resource_id,
124 ClientContext(BACKGROUND),
125 base::Bind(&RemovePerformer::TrashResourceAfterUpdateRemoteState,
126 weak_ptr_factory_.GetWeakPtr(), callback, local_id));
129 void RemovePerformer::TrashResourceAfterUpdateRemoteState(
130 const FileOperationCallback& callback,
131 const std::string& local_id,
132 google_apis::GDataErrorCode status) {
133 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
134 DCHECK(!callback.is_null());
136 if (status == google_apis::HTTP_FORBIDDEN) {
137 // Editing this entry is not allowed, revert local changes.
138 entry_revert_performer_->RevertEntry(local_id, callback);
139 observer_->OnDriveSyncError(
140 file_system::DRIVE_SYNC_ERROR_DELETE_WITHOUT_PERMISSION, local_id);
141 return;
144 FileError error = GDataToFileError(status);
145 if (error == FILE_ERROR_NOT_FOUND) { // Remove local entry when not found.
146 RemoveEntryOnUIThread(blocking_task_runner_.get(), metadata_, local_id,
147 callback);
148 return;
151 // Now we're done. If the entry is trashed on the server, it'll be also
152 // deleted locally on the next update.
153 callback.Run(error);
156 void RemovePerformer::UnparentResource(
157 const FileOperationCallback& callback,
158 const std::string& resource_id,
159 const std::string& local_id) {
160 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
161 DCHECK(!callback.is_null());
163 scheduler_->GetResourceEntry(
164 resource_id,
165 ClientContext(BACKGROUND),
166 base::Bind(&RemovePerformer::UnparentResourceAfterGetResourceEntry,
167 weak_ptr_factory_.GetWeakPtr(), callback, local_id));
170 void RemovePerformer::UnparentResourceAfterGetResourceEntry(
171 const FileOperationCallback& callback,
172 const std::string& local_id,
173 google_apis::GDataErrorCode status,
174 scoped_ptr<google_apis::ResourceEntry> resource_entry) {
175 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
176 DCHECK(!callback.is_null());
178 FileError error = GDataToFileError(status);
179 if (error == FILE_ERROR_NOT_FOUND) { // Remove local entry when not found.
180 RemoveEntryOnUIThread(blocking_task_runner_.get(), metadata_, local_id,
181 callback);
182 return;
185 if (error != FILE_ERROR_OK) {
186 callback.Run(error);
187 return;
190 ResourceEntry entry;
191 std::string parent_resource_id;
192 if (!ConvertToResourceEntry(*resource_entry, &entry, &parent_resource_id)) {
193 callback.Run(FILE_ERROR_NOT_A_FILE);
194 return;
197 if (!entry.shared_with_me()) {
198 // shared_with_me() has changed on the server.
199 UnparentResourceAfterUpdateRemoteState(callback, local_id,
200 google_apis::HTTP_CONFLICT);
201 return;
204 if (parent_resource_id.empty()) {
205 // This entry is unparented already.
206 UnparentResourceAfterUpdateRemoteState(callback, local_id,
207 google_apis::HTTP_NO_CONTENT);
208 return;
211 scheduler_->RemoveResourceFromDirectory(
212 parent_resource_id,
213 entry.resource_id(),
214 ClientContext(BACKGROUND),
215 base::Bind(&RemovePerformer::UnparentResourceAfterUpdateRemoteState,
216 weak_ptr_factory_.GetWeakPtr(), callback, local_id));
219 void RemovePerformer::UnparentResourceAfterUpdateRemoteState(
220 const FileOperationCallback& callback,
221 const std::string& local_id,
222 google_apis::GDataErrorCode status) {
223 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
224 DCHECK(!callback.is_null());
226 FileError error = GDataToFileError(status);
227 if (error != FILE_ERROR_OK) {
228 callback.Run(error);
229 return;
232 base::PostTaskAndReplyWithResult(
233 blocking_task_runner_.get(),
234 FROM_HERE,
235 base::Bind(&UpdateLocalStateAfterUnparent, metadata_, local_id),
236 callback);
239 } // namespace internal
240 } // namespace drive