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 // 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 Loading... |
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 |
OLD | NEW |