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

Side by Side Diff: chrome/browser/chromeos/drive/drive_feed_processor.cc

Issue 11293247: Make DriveFeedProcessor asynchronous. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: unittests and satorux feedback Created 8 years, 1 month 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 <utility> 5 #include <utility>
6 6
7 #include "base/metrics/histogram.h" 7 #include "base/metrics/histogram.h"
8 #include "chrome/browser/chromeos/drive/document_entry_conversion.h" 8 #include "chrome/browser/chromeos/drive/document_entry_conversion.h"
9 #include "chrome/browser/chromeos/drive/drive_feed_processor.h" 9 #include "chrome/browser/chromeos/drive/drive_feed_processor.h"
10 #include "chrome/browser/chromeos/drive/drive_files.h" 10 #include "chrome/browser/chromeos/drive/drive_files.h"
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
94 // Go through all entries generated by the feed and apply them to the local 94 // Go through all entries generated by the feed and apply them to the local
95 // snapshot of the file system. 95 // snapshot of the file system.
96 ApplyNextEntryProtoAsync(); 96 ApplyNextEntryProtoAsync();
97 } 97 }
98 98
99 void DriveFeedProcessor::ApplyNextEntryProtoAsync() { 99 void DriveFeedProcessor::ApplyNextEntryProtoAsync() {
100 base::MessageLoopProxy::current()->PostTask( 100 base::MessageLoopProxy::current()->PostTask(
101 FROM_HERE, 101 FROM_HERE,
102 base::Bind(&DriveFeedProcessor::ApplyNextEntryProto, 102 base::Bind(&DriveFeedProcessor::ApplyNextEntryProto,
103 weak_ptr_factory_.GetWeakPtr())); 103 weak_ptr_factory_.GetWeakPtr()));
104
105 } 104 }
106 105
107 void DriveFeedProcessor::ApplyNextEntryProto() { 106 void DriveFeedProcessor::ApplyNextEntryProto() {
108 DCHECK(!on_complete_callback_.is_null()); 107 DCHECK(!on_complete_callback_.is_null());
109 108
110 if (entry_proto_map_.empty()) { 109 if (entry_proto_map_.empty()) {
111 // All entries have been processed. 110 // All entries have been processed.
112 on_complete_callback_.Run(); 111 on_complete_callback_.Run();
113 return; 112 return;
114 } 113 }
(...skipping 17 matching lines...) Expand all
132 weak_ptr_factory_.GetWeakPtr(), 131 weak_ptr_factory_.GetWeakPtr(),
133 parent_it)); 132 parent_it));
134 } else { 133 } else {
135 // Erase the entry so the deleted entry won't be referenced. 134 // Erase the entry so the deleted entry won't be referenced.
136 entry_proto_map_.erase(it); 135 entry_proto_map_.erase(it);
137 ApplyEntryProto(entry_proto); 136 ApplyEntryProto(entry_proto);
138 } 137 }
139 } 138 }
140 139
141 void DriveFeedProcessor::ApplyEntryProto(const DriveEntryProto& entry_proto) { 140 void DriveFeedProcessor::ApplyEntryProto(const DriveEntryProto& entry_proto) {
142 scoped_ptr<DriveEntry> entry = 141 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
143 resource_metadata_->CreateDriveEntryFromProto(entry_proto);
144 DCHECK(entry.get());
145 DriveEntry* old_entry =
146 resource_metadata_->GetEntryByResourceId(entry->resource_id());
147 142
148 if (entry->is_deleted()) { 143 // Deleted file/directory.
149 // Deleted file/directory. 144 if (entry_proto.deleted()) {
150 DVLOG(1) << "Removing file " << entry->base_name(); 145 DVLOG(1) << "RemoveEntryFromParent " << entry_proto.base_name();
151 if (old_entry) 146 RemoveEntryFromParent(entry_proto.resource_id());
152 RemoveEntryFromParent(old_entry); 147 return;
153 } else if (old_entry) {
154 // Change or move of existing entry.
155 // Please note that entry rename is just a special case of change here
156 // since name is just one of the properties that can change.
157 DVLOG(1) << "Changed file " << entry->base_name();
158
159 // Move children files over if we are dealing with directories.
160 if (old_entry->AsDriveDirectory() && entry->AsDriveDirectory()) {
161 entry->AsDriveDirectory()->TakeOverEntries(
162 old_entry->AsDriveDirectory());
163 }
164
165 // Remove the old instance of this entry.
166 RemoveEntryFromParent(old_entry);
167
168 // Add to parent.
169 AddEntryToParent(entry.release());
170 } else {
171 // Adding a new file.
172 AddEntryToParent(entry.release());
173 } 148 }
174 149
175 // Process the next DriveEntryProto from the map. 150 resource_metadata_->GetEntryInfoByResourceId(entry_proto.resource_id(),
151 base::Bind(&DriveFeedProcessor::ContinueApplyEntryProto,
152 weak_ptr_factory_.GetWeakPtr(),
153 entry_proto));
154 }
155
156 void DriveFeedProcessor::ContinueApplyEntryProto(
157 const DriveEntryProto& entry_proto,
158 DriveFileError error,
159 const FilePath& drive_file_path,
160 scoped_ptr<DriveEntryProto> old_entry_proto) {
161 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
162
163 if (error == DRIVE_FILE_OK) {
164 // Entry exists and needs to be refreshed.
165 RefreshEntryProto(entry_proto);
166 } else {
167 // Adding a new entry.
168 AddEntryToParent(entry_proto);
169 }
170 }
171
172 void DriveFeedProcessor::RefreshEntryProto(const DriveEntryProto& entry_proto) {
173 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
174
175 // Get all directories to be notified.
176 resource_metadata_->GetChangedDirectories(
177 entry_proto.resource_id(),
178 base::Bind(&DriveFeedProcessor::ContinueRefreshEntryProto,
179 weak_ptr_factory_.GetWeakPtr(),
180 entry_proto));
181 }
182
183 void DriveFeedProcessor::ContinueRefreshEntryProto(
184 const DriveEntryProto& entry_proto,
185 const std::set<FilePath>& changed_directories) {
186 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
187
188 resource_metadata_->RefreshEntryProto(
189 entry_proto,
190 base::Bind(&DriveFeedProcessor::NotifyForRefreshEntryProto,
191 weak_ptr_factory_.GetWeakPtr(),
192 changed_directories));
193 }
194
195 void DriveFeedProcessor::NotifyForRefreshEntryProto(
196 const std::set<FilePath>& changed_directories,
197 DriveFileError error,
198 const FilePath& file_path,
199 scoped_ptr<DriveEntryProto> entry_proto) {
200 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
201
202 DVLOG(1) << "NotifyForRefreshEntryProto " << file_path.value();
203 if (error == DRIVE_FILE_OK) {
204 // Notify old children, old self and parent of old self.
205 changed_dirs_.insert(changed_directories.begin(),
206 changed_directories.end());
207
208 // Notify new parent.
209 changed_dirs_.insert(file_path.DirName());
210
211 // Notify new self.
212 if (!entry_proto->has_file_specific_info())
213 changed_dirs_.insert(file_path);
214 }
215
176 ApplyNextEntryProtoAsync(); 216 ApplyNextEntryProtoAsync();
177 } 217 }
178 218
179 void DriveFeedProcessor::AddEntryToParent( 219 void DriveFeedProcessor::AddEntryToParent(const DriveEntryProto& entry_proto) {
180 DriveEntry* entry) { 220 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
221
222 resource_metadata_->AddEntryToParent(entry_proto,
223 base::Bind(&DriveFeedProcessor::NotifyForAddEntryToParent,
224 weak_ptr_factory_.GetWeakPtr(),
225 !entry_proto.has_file_specific_info()));
226 }
227
228 void DriveFeedProcessor::NotifyForAddEntryToParent(bool is_directory,
229 DriveFileError error,
230 const FilePath& file_path) {
231 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
232
233 DVLOG(1) << "NotifyForAddEntryToParent " << file_path.value();
234 if (error == DRIVE_FILE_OK) {
235 // Notify if a directory has been created.
236 if (is_directory)
237 changed_dirs_.insert(file_path);
238
239 // Notify parent.
240 changed_dirs_.insert(file_path.DirName());
241 }
242
243 ApplyNextEntryProtoAsync();
244 }
245
246
247 void DriveFeedProcessor::RemoveEntryFromParent(const std::string& resource_id) {
248 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
249
250 // We need to notify all children of entry if entry is a directory.
251 resource_metadata_->GetChangedDirectories(
252 resource_id,
253 base::Bind(&DriveFeedProcessor::ContinueRemoveEntryFromParent,
254 weak_ptr_factory_.GetWeakPtr(),
255 resource_id));
256 }
257
258 void DriveFeedProcessor::ContinueRemoveEntryFromParent(
259 const std::string& resource_id,
260 const std::set<FilePath>& changed_directories) {
261 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
262
263 resource_metadata_->RemoveEntryFromParent(
264 resource_id,
265 base::Bind(&DriveFeedProcessor::NotifyForRemoveEntryFromParent,
266 weak_ptr_factory_.GetWeakPtr(),
267 changed_directories));
268 }
269
270 void DriveFeedProcessor::NotifyForRemoveEntryFromParent(
271 const std::set<FilePath>& changed_directories,
272 DriveFileError error,
273 const FilePath& file_path) {
274 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
275
276 if (error == DRIVE_FILE_OK) {
277 changed_dirs_.insert(changed_directories.begin(),
278 changed_directories.end());
279 }
280 ApplyNextEntryProtoAsync();
281 }
282
283 void DriveFeedProcessor::AddEntryToParent(DriveEntry* entry) {
181 DriveDirectory* parent = ResolveParent(entry); 284 DriveDirectory* parent = ResolveParent(entry);
182 285
183 if (!parent) { // Orphan. 286 if (!parent) { // Orphan.
184 delete entry; 287 delete entry;
185 return; 288 return;
186 } 289 }
187 parent->AddEntry(entry); 290 parent->AddEntry(entry);
188 291
189 // Notify this directory that has been created. 292 // Notify this directory that has been created.
190 if (entry->AsDriveDirectory()) 293 if (entry->AsDriveDirectory())
191 changed_dirs_.insert(entry->GetFilePath()); 294 changed_dirs_.insert(entry->GetFilePath());
192 295
193 // Notify |parent| only if it already exists by checking if it is attached to 296 // Notify |parent| only if it already exists by checking if it is attached to
194 // the tree (has parent) or if it is root. The parent of |parent| may not 297 // the tree (has parent) or if it is root. The parent of |parent| may not
195 // exist here if it is about to be created later in the same feed. 298 // exist here if it is about to be created later in the same feed.
196 if (parent->parent() || parent == resource_metadata_->root()) 299 if (parent->parent() || parent == resource_metadata_->root())
197 changed_dirs_.insert(parent->GetFilePath()); 300 changed_dirs_.insert(parent->GetFilePath());
198 } 301 }
199 302
200 void DriveFeedProcessor::RemoveEntryFromParent( 303 void DriveFeedProcessor::RemoveEntryFromParent(DriveEntry* entry) {
201 DriveEntry* entry) {
202 DriveDirectory* parent = entry->parent(); 304 DriveDirectory* parent = entry->parent();
203 if (!parent) { 305 if (!parent) {
204 NOTREACHED(); 306 NOTREACHED();
205 return; 307 return;
206 } 308 }
207 309
208 DriveDirectory* dir = entry->AsDriveDirectory(); 310 DriveDirectory* dir = entry->AsDriveDirectory();
209 if (dir) { 311 if (dir)
210 // We need to notify all children of entry if entry is a directory. 312 // We need to notify all children of entry if entry is a directory.
211 dir->GetChildDirectoryPaths(&changed_dirs_); 313 dir->GetChildDirectoryPaths(&changed_dirs_);
212 // Besides children, notify this removed directory too.
213 changed_dirs_.insert(dir->GetFilePath());
214 }
215 314
216 parent->RemoveEntry(entry); 315 parent->RemoveEntry(entry);
217 316
218 // Notify parent. 317 // Notify parent.
219 changed_dirs_.insert(parent->GetFilePath()); 318 changed_dirs_.insert(parent->GetFilePath());
220 } 319 }
221 320
222 DriveDirectory* DriveFeedProcessor::ResolveParent( 321 DriveDirectory* DriveFeedProcessor::ResolveParent(DriveEntry* new_entry) {
223 DriveEntry* new_entry) {
224 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 322 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
225 323
226 const std::string& parent_resource_id = new_entry->parent_resource_id(); 324 const std::string& parent_resource_id = new_entry->parent_resource_id();
227 if (parent_resource_id.empty()) { 325 if (parent_resource_id.empty()) {
228 DVLOG(1) << "Root parent for " << new_entry->base_name(); 326 DVLOG(1) << "Root parent for " << new_entry->base_name();
229 return resource_metadata_->root(); 327 return resource_metadata_->root();
230 } 328 }
231 329
232 DriveEntry* parent = 330 DriveEntry* parent =
233 resource_metadata_->GetEntryByResourceId(parent_resource_id); 331 resource_metadata_->GetEntryByResourceId(parent_resource_id);
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
281 } 379 }
282 } 380 }
283 381
284 void DriveFeedProcessor::Clear() { 382 void DriveFeedProcessor::Clear() {
285 entry_proto_map_.clear(); 383 entry_proto_map_.clear();
286 changed_dirs_.clear(); 384 changed_dirs_.clear();
287 on_complete_callback_.Reset(); 385 on_complete_callback_.Reset();
288 } 386 }
289 387
290 } // namespace drive 388 } // namespace drive
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698