OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 // Lookup the entry. |
149 // Deleted file/directory. | 144 resource_metadata_->GetEntryInfoByResourceId( |
150 DVLOG(1) << "Removing file " << entry->base_name(); | 145 entry_proto.resource_id(), |
151 if (old_entry) | 146 base::Bind(&DriveFeedProcessor::ContinueApplyEntryProto, |
152 RemoveEntryFromParent(old_entry); | 147 weak_ptr_factory_.GetWeakPtr(), |
153 } else if (old_entry) { | 148 entry_proto)); |
154 // Change or move of existing entry. | 149 } |
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 | 150 |
159 // Move children files over if we are dealing with directories. | 151 void DriveFeedProcessor::ContinueApplyEntryProto( |
160 if (old_entry->AsDriveDirectory() && entry->AsDriveDirectory()) { | 152 const DriveEntryProto& entry_proto, |
161 entry->AsDriveDirectory()->TakeOverEntries( | 153 DriveFileError error, |
162 old_entry->AsDriveDirectory()); | 154 const FilePath& file_path, |
155 scoped_ptr<DriveEntryProto> old_entry_proto) { | |
156 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
157 | |
158 if (error == DRIVE_FILE_OK) { | |
159 if (entry_proto.deleted()) { | |
160 // Deleted file/directory. | |
161 RemoveEntryFromParent(entry_proto, file_path); | |
162 } else { | |
163 // Entry exists and needs to be refreshed. | |
164 RefreshEntryProto(entry_proto, file_path); | |
163 } | 165 } |
166 } else if (error == DRIVE_FILE_ERROR_NOT_FOUND && !entry_proto.deleted()) { | |
167 // Adding a new entry. | |
168 AddEntryToParent(entry_proto); | |
169 } else { | |
170 // Continue. | |
171 ApplyNextEntryProtoAsync(); | |
172 } | |
173 } | |
164 | 174 |
165 // Remove the old instance of this entry. | 175 void DriveFeedProcessor::RefreshEntryProto(const DriveEntryProto& entry_proto, |
166 RemoveEntryFromParent(old_entry); | 176 const FilePath& file_path) { |
177 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
167 | 178 |
168 // Add to parent. | 179 resource_metadata_->RefreshEntryProto( |
169 AddEntryToParent(entry.release()); | 180 entry_proto, |
170 } else { | 181 base::Bind(&DriveFeedProcessor::NotifyForRefreshEntryProto, |
171 // Adding a new file. | 182 weak_ptr_factory_.GetWeakPtr(), |
172 AddEntryToParent(entry.release()); | 183 file_path)); |
184 } | |
185 | |
186 void DriveFeedProcessor::NotifyForRefreshEntryProto( | |
187 const FilePath& old_file_path, | |
188 DriveFileError error, | |
189 const FilePath& file_path, | |
190 scoped_ptr<DriveEntryProto> entry_proto) { | |
191 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
192 | |
193 DVLOG(1) << "NotifyForRefreshEntryProto " << file_path.value(); | |
194 if (error == DRIVE_FILE_OK) { | |
195 // Notify old parent. | |
196 changed_dirs_.insert(old_file_path.DirName()); | |
197 | |
198 // Notify new parent. | |
199 changed_dirs_.insert(file_path.DirName()); | |
200 | |
201 // Notify self if entry is a directory. | |
202 if (!entry_proto->has_file_specific_info()) { | |
satorux1
2012/11/19 01:24:24
The following would be a bit clearer:
entry_proto
| |
203 // Notify new self. | |
204 changed_dirs_.insert(file_path); | |
205 // Notify old self. | |
206 changed_dirs_.insert(old_file_path); | |
207 } | |
173 } | 208 } |
174 | 209 |
175 // Process the next DriveEntryProto from the map. | |
176 ApplyNextEntryProtoAsync(); | 210 ApplyNextEntryProtoAsync(); |
177 } | 211 } |
178 | 212 |
179 void DriveFeedProcessor::AddEntryToParent( | 213 void DriveFeedProcessor::AddEntryToParent(const DriveEntryProto& entry_proto) { |
180 DriveEntry* entry) { | 214 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
215 | |
216 resource_metadata_->AddEntryToParent(entry_proto, | |
217 base::Bind(&DriveFeedProcessor::NotifyForAddEntryToParent, | |
218 weak_ptr_factory_.GetWeakPtr(), | |
219 !entry_proto.has_file_specific_info())); | |
satorux1
2012/11/19 01:24:24
ditto. please check other places too.
| |
220 } | |
221 | |
222 void DriveFeedProcessor::NotifyForAddEntryToParent(bool is_directory, | |
223 DriveFileError error, | |
224 const FilePath& file_path) { | |
225 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
226 | |
227 DVLOG(1) << "NotifyForAddEntryToParent " << file_path.value(); | |
228 if (error == DRIVE_FILE_OK) { | |
229 // Notify if a directory has been created. | |
230 if (is_directory) | |
231 changed_dirs_.insert(file_path); | |
232 | |
233 // Notify parent. | |
234 changed_dirs_.insert(file_path.DirName()); | |
235 } | |
236 | |
237 ApplyNextEntryProtoAsync(); | |
238 } | |
239 | |
240 | |
241 void DriveFeedProcessor::RemoveEntryFromParent( | |
242 const DriveEntryProto& entry_proto, | |
243 const FilePath& file_path) { | |
244 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
245 DCHECK(!file_path.empty()); | |
246 | |
247 if (entry_proto.has_file_specific_info()) { | |
248 // No children if entry is a file. | |
249 OnGetChildrenForRemove(entry_proto, | |
250 file_path, | |
251 std::set<FilePath>()); | |
252 } else { | |
253 // If entry is a directory, notify its children. | |
254 resource_metadata_->GetChildDirectories( | |
255 entry_proto.resource_id(), | |
256 base::Bind(&DriveFeedProcessor::OnGetChildrenForRemove, | |
257 weak_ptr_factory_.GetWeakPtr(), | |
258 entry_proto, | |
259 file_path)); | |
260 } | |
261 } | |
262 | |
263 void DriveFeedProcessor::OnGetChildrenForRemove( | |
264 const DriveEntryProto& entry_proto, | |
265 const FilePath& file_path, | |
266 const std::set<FilePath>& changed_directories) { | |
267 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
268 DCHECK(!file_path.empty()); | |
269 | |
270 resource_metadata_->RemoveEntryFromParent( | |
271 entry_proto.resource_id(), | |
272 base::Bind(&DriveFeedProcessor::NotifyForRemoveEntryFromParent, | |
273 weak_ptr_factory_.GetWeakPtr(), | |
274 !entry_proto.has_file_specific_info(), | |
275 file_path, | |
276 changed_directories)); | |
277 } | |
278 | |
279 void DriveFeedProcessor::NotifyForRemoveEntryFromParent( | |
280 bool is_directory, | |
281 const FilePath& file_path, | |
282 const std::set<FilePath>& changed_directories, | |
283 DriveFileError error, | |
284 const FilePath& parent_path) { | |
285 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
286 | |
287 DVLOG(1) << "NotifyForRemoveEntryFromParent " << file_path.value(); | |
288 if (error == DRIVE_FILE_OK) { | |
289 // Notify parent. | |
290 changed_dirs_.insert(parent_path); | |
291 | |
292 // Notify children, if any. | |
293 changed_dirs_.insert(changed_directories.begin(), | |
294 changed_directories.end()); | |
295 | |
296 // If entry is a directory, notify self. | |
297 if (is_directory) | |
298 changed_dirs_.insert(file_path); | |
299 } | |
300 | |
301 // Continue. | |
302 ApplyNextEntryProtoAsync(); | |
303 } | |
304 | |
305 void DriveFeedProcessor::AddEntryToParentDeprecated(DriveEntry* entry) { | |
181 DriveDirectory* parent = ResolveParent(entry); | 306 DriveDirectory* parent = ResolveParent(entry); |
182 | 307 |
183 if (!parent) { // Orphan. | 308 if (!parent) { // Orphan. |
184 delete entry; | 309 delete entry; |
185 return; | 310 return; |
186 } | 311 } |
187 parent->AddEntry(entry); | 312 parent->AddEntry(entry); |
188 | 313 |
189 // Notify this directory that has been created. | 314 // Notify this directory that has been created. |
190 if (entry->AsDriveDirectory()) | 315 if (entry->AsDriveDirectory()) |
191 changed_dirs_.insert(entry->GetFilePath()); | 316 changed_dirs_.insert(entry->GetFilePath()); |
192 | 317 |
193 // Notify |parent| only if it already exists by checking if it is attached to | 318 // 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 | 319 // 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. | 320 // exist here if it is about to be created later in the same feed. |
196 if (parent->parent() || parent == resource_metadata_->root()) | 321 if (parent->parent() || parent == resource_metadata_->root()) |
197 changed_dirs_.insert(parent->GetFilePath()); | 322 changed_dirs_.insert(parent->GetFilePath()); |
198 } | 323 } |
199 | 324 |
200 void DriveFeedProcessor::RemoveEntryFromParent( | 325 void DriveFeedProcessor::RemoveEntryFromParent(DriveEntry* entry) { |
201 DriveEntry* entry) { | |
202 DriveDirectory* parent = entry->parent(); | 326 DriveDirectory* parent = entry->parent(); |
203 if (!parent) { | 327 if (!parent) { |
204 NOTREACHED(); | 328 NOTREACHED(); |
205 return; | 329 return; |
206 } | 330 } |
207 | 331 |
208 DriveDirectory* dir = entry->AsDriveDirectory(); | 332 DriveDirectory* dir = entry->AsDriveDirectory(); |
209 if (dir) { | 333 // Notify all children of entry, if entry is a directory. |
210 // We need to notify all children of entry if entry is a directory. | 334 if (dir) |
211 dir->GetChildDirectoryPaths(&changed_dirs_); | 335 dir->GetChildDirectoryPaths(&changed_dirs_); |
212 // Besides children, notify this removed directory too. | |
213 changed_dirs_.insert(dir->GetFilePath()); | |
214 } | |
215 | 336 |
216 parent->RemoveEntry(entry); | 337 parent->RemoveEntry(entry); |
217 | 338 |
218 // Notify parent. | 339 // Notify parent. |
219 changed_dirs_.insert(parent->GetFilePath()); | 340 changed_dirs_.insert(parent->GetFilePath()); |
220 } | 341 } |
221 | 342 |
222 DriveDirectory* DriveFeedProcessor::ResolveParent( | 343 DriveDirectory* DriveFeedProcessor::ResolveParent(DriveEntry* new_entry) { |
223 DriveEntry* new_entry) { | |
224 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 344 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
225 | 345 |
226 const std::string& parent_resource_id = new_entry->parent_resource_id(); | 346 const std::string& parent_resource_id = new_entry->parent_resource_id(); |
227 if (parent_resource_id.empty()) { | 347 if (parent_resource_id.empty()) { |
228 DVLOG(1) << "Root parent for " << new_entry->base_name(); | 348 DVLOG(1) << "Root parent for " << new_entry->base_name(); |
229 return resource_metadata_->root(); | 349 return resource_metadata_->root(); |
230 } | 350 } |
231 | 351 |
232 DriveEntry* parent = | 352 DriveEntry* parent = |
233 resource_metadata_->GetEntryByResourceId(parent_resource_id); | 353 resource_metadata_->GetEntryByResourceId(parent_resource_id); |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
281 } | 401 } |
282 } | 402 } |
283 | 403 |
284 void DriveFeedProcessor::Clear() { | 404 void DriveFeedProcessor::Clear() { |
285 entry_proto_map_.clear(); | 405 entry_proto_map_.clear(); |
286 changed_dirs_.clear(); | 406 changed_dirs_.clear(); |
287 on_complete_callback_.Reset(); | 407 on_complete_callback_.Reset(); |
288 } | 408 } |
289 | 409 |
290 } // namespace drive | 410 } // namespace drive |
OLD | NEW |