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

Side by Side Diff: chrome/browser/chromeos/drive/file_system/remove_operation.cc

Issue 68543002: drive: Support offline delete (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Stop modifying local state after server side update Created 7 years 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 "chrome/browser/chromeos/drive/file_system/remove_operation.h" 5 #include "chrome/browser/chromeos/drive/file_system/remove_operation.h"
6 6
7 #include "base/sequenced_task_runner.h" 7 #include "base/sequenced_task_runner.h"
8 #include "chrome/browser/chromeos/drive/drive.pb.h" 8 #include "chrome/browser/chromeos/drive/drive.pb.h"
9 #include "chrome/browser/chromeos/drive/file_cache.h" 9 #include "chrome/browser/chromeos/drive/file_cache.h"
10 #include "chrome/browser/chromeos/drive/file_system/operation_observer.h" 10 #include "chrome/browser/chromeos/drive/file_system/operation_observer.h"
11 #include "chrome/browser/chromeos/drive/file_system_util.h" 11 #include "chrome/browser/chromeos/drive/file_system_util.h"
12 #include "chrome/browser/chromeos/drive/job_scheduler.h" 12 #include "chrome/browser/chromeos/drive/resource_metadata.h"
13 #include "content/public/browser/browser_thread.h" 13 #include "content/public/browser/browser_thread.h"
14 14
15 using content::BrowserThread; 15 using content::BrowserThread;
16 16
17 namespace drive { 17 namespace drive {
18 namespace file_system { 18 namespace file_system {
19 19
20 namespace { 20 namespace {
21 21
22 // Checks local metadata state before requesting remote delete. 22 // Removes cache file and moves the metadata entry to the trash.
23 // |parent_resource_id| is set to the resource ID of the parent directory of 23 FileError UpdateLocalState(internal::ResourceMetadata* metadata,
24 // |path|. If it is a special folder like drive/other, empty string is set. 24 internal::FileCache* cache,
25 // |entry| is the resource entry for the |path|. 25 const base::FilePath& path,
26 FileError CheckLocalState(internal::ResourceMetadata* metadata, 26 bool is_recursive,
27 const base::FilePath& path, 27 std::string* local_id,
28 bool is_recursive, 28 base::FilePath* changed_directory_path) {
29 std::string* parent_resource_id, 29 FileError error = metadata->GetIdByPath(path, local_id);
30 ResourceEntry* entry) {
31 std::string local_id;
32 FileError error = metadata->GetIdByPath(path, &local_id);
33 if (error != FILE_ERROR_OK) 30 if (error != FILE_ERROR_OK)
34 return error; 31 return error;
35 32
36 error = metadata->GetResourceEntryById(local_id, entry); 33 ResourceEntry entry;
34 error = metadata->GetResourceEntryById(*local_id, &entry);
37 if (error != FILE_ERROR_OK) 35 if (error != FILE_ERROR_OK)
38 return error; 36 return error;
39 37
40 if (entry->file_info().is_directory() && !is_recursive) { 38 if (entry.file_info().is_directory() && !is_recursive) {
41 // Check emptiness of the directory. 39 // Check emptiness of the directory.
42 ResourceEntryVector entries; 40 ResourceEntryVector entries;
43 error = metadata->ReadDirectoryByPath(path, &entries); 41 error = metadata->ReadDirectoryByPath(path, &entries);
44 if (error != FILE_ERROR_OK) 42 if (error != FILE_ERROR_OK)
45 return error; 43 return error;
46 if (!entries.empty()) 44 if (!entries.empty())
47 return FILE_ERROR_NOT_EMPTY; 45 return FILE_ERROR_NOT_EMPTY;
48 } 46 }
49 47
50 // Get the resource_id of the parent folder. If it is a special folder that 48 *changed_directory_path = metadata->GetFilePath(*local_id).DirName();
51 // does not have the server side ID, returns an empty string (not an error).
52 if (util::IsSpecialResourceId(entry->parent_local_id())) {
53 *parent_resource_id = "";
54 } else {
55 ResourceEntry parent_entry;
56 error = metadata->GetResourceEntryById(entry->parent_local_id(),
57 &parent_entry);
58 if (error != FILE_ERROR_OK)
59 return error;
60 *parent_resource_id = parent_entry.resource_id();
61 }
62 49
63 return FILE_ERROR_OK; 50 // Move to the trash.
64 } 51 entry.set_parent_local_id(util::kDriveTrashDirLocalId);
65 52 error = metadata->RefreshEntry(entry);
66 // Updates local metadata and cache state after remote delete.
67 FileError UpdateLocalStateAfterDelete(internal::ResourceMetadata* metadata,
68 internal::FileCache* cache,
69 const std::string& local_id,
70 base::FilePath* changed_directory_path) {
71 *changed_directory_path = metadata->GetFilePath(local_id).DirName();
72 FileError error = metadata->RemoveEntry(local_id);
73 if (error != FILE_ERROR_OK) 53 if (error != FILE_ERROR_OK)
74 return error; 54 return error;
75 55
76 error = cache->Remove(local_id); 56 return cache->Remove(*local_id);
77 DLOG_IF(ERROR, error != FILE_ERROR_OK) << "Failed to remove: " << local_id;
78
79 return FILE_ERROR_OK;
80 }
81
82 // Updates local metadata and after remote unparenting.
83 FileError UpdateLocalStateAfterUnparent(
84 internal::ResourceMetadata* metadata,
85 const std::string& local_id,
86 base::FilePath* changed_directory_path) {
87 *changed_directory_path = metadata->GetFilePath(local_id).DirName();
88
89 ResourceEntry entry;
90 FileError error = metadata->GetResourceEntryById(local_id, &entry);
91 if (error != FILE_ERROR_OK)
92 return error;
93 entry.set_parent_local_id(util::kDriveOtherDirLocalId);
94 return metadata->RefreshEntry(entry);
95 } 57 }
96 58
97 } // namespace 59 } // namespace
98 60
99 RemoveOperation::RemoveOperation( 61 RemoveOperation::RemoveOperation(
100 base::SequencedTaskRunner* blocking_task_runner, 62 base::SequencedTaskRunner* blocking_task_runner,
101 OperationObserver* observer, 63 OperationObserver* observer,
102 JobScheduler* scheduler,
103 internal::ResourceMetadata* metadata, 64 internal::ResourceMetadata* metadata,
104 internal::FileCache* cache) 65 internal::FileCache* cache)
105 : blocking_task_runner_(blocking_task_runner), 66 : blocking_task_runner_(blocking_task_runner),
106 observer_(observer), 67 observer_(observer),
107 scheduler_(scheduler),
108 metadata_(metadata), 68 metadata_(metadata),
109 cache_(cache), 69 cache_(cache),
110 weak_ptr_factory_(this) { 70 weak_ptr_factory_(this) {
111 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 71 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
112 } 72 }
113 73
114 RemoveOperation::~RemoveOperation() { 74 RemoveOperation::~RemoveOperation() {
115 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 75 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
116 } 76 }
117 77
118 void RemoveOperation::Remove(const base::FilePath& path, 78 void RemoveOperation::Remove(const base::FilePath& path,
119 bool is_recursive, 79 bool is_recursive,
120 const FileOperationCallback& callback) { 80 const FileOperationCallback& callback) {
121 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 81 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
122 DCHECK(!callback.is_null()); 82 DCHECK(!callback.is_null());
123 83
124 std::string* parent_resource_id = new std::string; 84 std::string* local_id = new std::string;
125 ResourceEntry* entry = new ResourceEntry;
126 base::PostTaskAndReplyWithResult(
127 blocking_task_runner_.get(),
128 FROM_HERE,
129 base::Bind(&CheckLocalState,
130 metadata_,
131 path,
132 is_recursive,
133 parent_resource_id,
134 entry),
135 base::Bind(&RemoveOperation::RemoveAfterCheckLocalState,
136 weak_ptr_factory_.GetWeakPtr(),
137 callback,
138 base::Owned(parent_resource_id),
139 base::Owned(entry)));
140 }
141
142 void RemoveOperation::RemoveAfterCheckLocalState(
143 const FileOperationCallback& callback,
144 const std::string* parent_resource_id,
145 const ResourceEntry* entry,
146 FileError error) {
147 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
148 DCHECK(!callback.is_null());
149
150 if (error != FILE_ERROR_OK) {
151 callback.Run(error);
152 return;
153 }
154
155 // To match with the behavior of drive.google.com:
156 // Removal of shared entries under MyDrive is just removing from the parent.
157 // The entry will stay in shared-with-me (in other words, in "drive/other".)
158 //
159 // TODO(kinaba): to be more precise, we might be better to branch by whether
160 // or not the current account is an owner of the file. The code below is
161 // written under the assumption that |shared_with_me| coincides with that.
162 if (entry->shared_with_me() && !parent_resource_id->empty()) {
163 scheduler_->RemoveResourceFromDirectory(
164 *parent_resource_id,
165 entry->resource_id(),
166 ClientContext(USER_INITIATED),
167 base::Bind(&RemoveOperation::RemoveAfterUpdateRemoteState,
168 weak_ptr_factory_.GetWeakPtr(),
169 callback,
170 base::Bind(&UpdateLocalStateAfterUnparent,
171 metadata_,
172 entry->local_id())));
173 } else {
174 // Otherwise try sending the entry to trash.
175 scheduler_->DeleteResource(
176 entry->resource_id(),
177 ClientContext(USER_INITIATED),
178 base::Bind(&RemoveOperation::RemoveAfterUpdateRemoteState,
179 weak_ptr_factory_.GetWeakPtr(),
180 callback,
181 base::Bind(&UpdateLocalStateAfterDelete,
182 metadata_,
183 cache_,
184 entry->local_id())));
185 }
186 }
187
188 void RemoveOperation::RemoveAfterUpdateRemoteState(
189 const FileOperationCallback& callback,
190 const base::Callback<FileError(base::FilePath*)>& local_update_task,
191 google_apis::GDataErrorCode status) {
192 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
193 DCHECK(!callback.is_null());
194
195 FileError error = GDataToFileError(status);
196 if (error != FILE_ERROR_OK) {
197 callback.Run(error);
198 return;
199 }
200
201 base::FilePath* changed_directory_path = new base::FilePath; 85 base::FilePath* changed_directory_path = new base::FilePath;
202 base::PostTaskAndReplyWithResult( 86 base::PostTaskAndReplyWithResult(
203 blocking_task_runner_.get(), 87 blocking_task_runner_.get(),
204 FROM_HERE, 88 FROM_HERE,
205 base::Bind(local_update_task, changed_directory_path), 89 base::Bind(&UpdateLocalState,
90 metadata_,
91 cache_,
92 path,
93 is_recursive,
94 local_id,
95 changed_directory_path),
206 base::Bind(&RemoveOperation::RemoveAfterUpdateLocalState, 96 base::Bind(&RemoveOperation::RemoveAfterUpdateLocalState,
207 weak_ptr_factory_.GetWeakPtr(), 97 weak_ptr_factory_.GetWeakPtr(),
208 callback, 98 callback,
99 base::Owned(local_id),
209 base::Owned(changed_directory_path))); 100 base::Owned(changed_directory_path)));
210 } 101 }
211 102
212 void RemoveOperation::RemoveAfterUpdateLocalState( 103 void RemoveOperation::RemoveAfterUpdateLocalState(
213 const FileOperationCallback& callback, 104 const FileOperationCallback& callback,
105 const std::string* local_id,
214 const base::FilePath* changed_directory_path, 106 const base::FilePath* changed_directory_path,
215 FileError error) { 107 FileError error) {
216 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 108 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
217 DCHECK(!callback.is_null()); 109 DCHECK(!callback.is_null());
218 110
219 if (error == FILE_ERROR_OK) 111 if (error == FILE_ERROR_OK) {
220 observer_->OnDirectoryChangedByOperation(*changed_directory_path); 112 observer_->OnDirectoryChangedByOperation(*changed_directory_path);
113 observer_->OnEntryRemovedByOperation(*local_id);
114 }
221 115
222 callback.Run(error); 116 callback.Run(error);
223 } 117 }
224 118
225 } // namespace file_system 119 } // namespace file_system
226 } // namespace drive 120 } // namespace drive
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698