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 "chrome/browser/chromeos/drive/drive_resource_metadata.h" | 5 #include "chrome/browser/chromeos/drive/drive_resource_metadata.h" |
6 | 6 |
7 #include <leveldb/db.h> | 7 #include <leveldb/db.h> |
8 #include <stack> | 8 #include <stack> |
9 #include <utility> | 9 #include <utility> |
10 | 10 |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
108 void DriveResourceMetadata::ClearRoot() { | 108 void DriveResourceMetadata::ClearRoot() { |
109 if (!root_.get()) | 109 if (!root_.get()) |
110 return; | 110 return; |
111 | 111 |
112 // The root is not yet initialized. | 112 // The root is not yet initialized. |
113 if (root_->resource_id().empty()) | 113 if (root_->resource_id().empty()) |
114 return; | 114 return; |
115 | 115 |
116 // Note that children have a reference to root_, | 116 // Note that children have a reference to root_, |
117 // so we need to delete them here. | 117 // so we need to delete them here. |
118 RemoveDirectoryChildren(root_.get()); | 118 RemoveDirectoryChildren(root_->resource_id()); |
119 RemoveEntryFromResourceMap(root_->resource_id()); | 119 RemoveEntryFromResourceMap(root_->resource_id()); |
120 DCHECK(resource_map_.empty()); | 120 DCHECK(resource_map_.empty()); |
121 // The resource_map_ should be empty here, but to make sure for non-Debug | 121 // The resource_map_ should be empty here, but to make sure for non-Debug |
122 // build. | 122 // build. |
123 resource_map_.clear(); | 123 resource_map_.clear(); |
124 root_.reset(); | 124 root_.reset(); |
125 } | 125 } |
126 | 126 |
127 void DriveResourceMetadata::GetLargestChangestamp( | 127 void DriveResourceMetadata::GetLargestChangestamp( |
128 const GetChangestampCallback& callback) { | 128 const GetChangestampCallback& callback) { |
(...skipping 25 matching lines...) Expand all Loading... | |
154 } | 154 } |
155 | 155 |
156 DriveEntryProto* destination = FindEntryByPathSync(directory_path); | 156 DriveEntryProto* destination = FindEntryByPathSync(directory_path); |
157 base::FilePath moved_file_path; | 157 base::FilePath moved_file_path; |
158 DriveFileError error = DRIVE_FILE_ERROR_FAILED; | 158 DriveFileError error = DRIVE_FILE_ERROR_FAILED; |
159 if (!destination) { | 159 if (!destination) { |
160 error = DRIVE_FILE_ERROR_NOT_FOUND; | 160 error = DRIVE_FILE_ERROR_NOT_FOUND; |
161 } else if (!destination->file_info().is_directory()) { | 161 } else if (!destination->file_info().is_directory()) { |
162 error = DRIVE_FILE_ERROR_NOT_A_DIRECTORY; | 162 error = DRIVE_FILE_ERROR_NOT_A_DIRECTORY; |
163 } else { | 163 } else { |
164 DriveEntryProto* parent = entry->parent_resource_id().empty() ? NULL : | 164 DriveEntryProto* parent = entry->parent_resource_id().empty() ? NULL : |
kinaba
2013/03/15 05:48:08
Now, empty parent_resource_id means it is the root
hashimoto
2013/03/15 06:40:23
Changed to return DRIVE_FILE_ERROR_INVALID_OPERATI
| |
165 GetEntryByResourceId(entry->parent_resource_id()); | 165 GetEntryByResourceId(entry->parent_resource_id()); |
166 if (parent && parent->file_info().is_directory()) | 166 if (parent && parent->file_info().is_directory()) |
kinaba
2013/03/15 05:48:08
Similarly, non directory parent is a bug.
I think
hashimoto
2013/03/15 06:40:23
Now we no longer need to get parent.
Removed.
| |
167 DetachEntryFromDirectory(parent, entry); | 167 DetachEntryFromDirectory(entry->resource_id()); |
168 | 168 |
169 AddEntryToDirectory(destination, entry); | 169 entry->set_parent_resource_id(destination->resource_id()); |
170 moved_file_path = GetFilePath(*entry); | 170 AddEntryToDirectory(entry); |
171 moved_file_path = GetFilePath(entry->resource_id()); | |
171 error = DRIVE_FILE_OK; | 172 error = DRIVE_FILE_OK; |
172 } | 173 } |
173 DVLOG(1) << "MoveEntryToDirectory " << moved_file_path.value(); | 174 DVLOG(1) << "MoveEntryToDirectory " << moved_file_path.value(); |
174 base::MessageLoopProxy::current()->PostTask( | 175 base::MessageLoopProxy::current()->PostTask( |
175 FROM_HERE, base::Bind(callback, error, moved_file_path)); | 176 FROM_HERE, base::Bind(callback, error, moved_file_path)); |
176 } | 177 } |
177 | 178 |
178 void DriveResourceMetadata::RenameEntry( | 179 void DriveResourceMetadata::RenameEntry( |
179 const base::FilePath& file_path, | 180 const base::FilePath& file_path, |
180 const base::FilePath::StringType& new_name, | 181 const base::FilePath::StringType& new_name, |
181 const FileMoveCallback& callback) { | 182 const FileMoveCallback& callback) { |
182 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 183 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
183 DCHECK(!file_path.empty()); | 184 DCHECK(!file_path.empty()); |
184 DCHECK(!new_name.empty()); | 185 DCHECK(!new_name.empty()); |
185 DCHECK(!callback.is_null()); | 186 DCHECK(!callback.is_null()); |
186 | 187 |
187 DVLOG(1) << "RenameEntry " << file_path.value() << " to " << new_name; | 188 DVLOG(1) << "RenameEntry " << file_path.value() << " to " << new_name; |
188 DriveEntryProto* entry = FindEntryByPathSync(file_path); | 189 DriveEntryProto* entry = FindEntryByPathSync(file_path); |
189 if (!entry) { | 190 if (!entry) { |
190 PostFileMoveCallbackError(callback, DRIVE_FILE_ERROR_NOT_FOUND); | 191 PostFileMoveCallbackError(callback, DRIVE_FILE_ERROR_NOT_FOUND); |
191 return; | 192 return; |
192 } | 193 } |
193 | 194 |
194 if (new_name == file_path.BaseName().value()) { | 195 if (new_name == file_path.BaseName().value()) { |
195 PostFileMoveCallbackError(callback, DRIVE_FILE_ERROR_EXISTS); | 196 PostFileMoveCallbackError(callback, DRIVE_FILE_ERROR_EXISTS); |
196 return; | 197 return; |
197 } | 198 } |
198 | 199 |
199 entry->set_title(new_name); | 200 entry->set_title(new_name); |
200 | |
201 DriveEntryProto* parent = GetEntryByResourceId(entry->parent_resource_id()); | |
202 DCHECK(parent); | |
203 // After changing the title of the entry, call MoveEntryToDirectory to | 201 // After changing the title of the entry, call MoveEntryToDirectory to |
204 // remove the entry from its parent directory and then add it back in order to | 202 // remove the entry from its parent directory and then add it back in order to |
205 // go through the file name de-duplication. | 203 // go through the file name de-duplication. |
206 // TODO(achuith/satorux/zel): This code is fragile. The title has been | 204 // TODO(achuith/satorux/zel): This code is fragile. The title has been |
207 // changed, but not the file_name. MoveEntryToDirectory calls RemoveChild to | 205 // changed, but not the file_name. MoveEntryToDirectory calls RemoveChild to |
208 // remove the child based on the old file_name, and then re-adds the child by | 206 // remove the child based on the old file_name, and then re-adds the child by |
209 // first assigning the new title to file_name. http://crbug.com/30157 | 207 // first assigning the new title to file_name. http://crbug.com/30157 |
210 MoveEntryToDirectory(file_path, GetFilePath(*parent), callback); | 208 MoveEntryToDirectory(file_path, |
209 GetFilePath(entry->parent_resource_id()), callback); | |
211 } | 210 } |
212 | 211 |
213 void DriveResourceMetadata::RemoveEntry(const std::string& resource_id, | 212 void DriveResourceMetadata::RemoveEntry(const std::string& resource_id, |
214 const FileMoveCallback& callback) { | 213 const FileMoveCallback& callback) { |
215 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 214 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
216 DCHECK(!callback.is_null()); | 215 DCHECK(!callback.is_null()); |
217 | 216 |
218 // Disallow deletion of root. | 217 // Disallow deletion of root. |
219 if (resource_id == root_->resource_id()) { | 218 if (resource_id == root_->resource_id()) { |
220 PostFileMoveCallbackError(callback, DRIVE_FILE_ERROR_ACCESS_DENIED); | 219 PostFileMoveCallbackError(callback, DRIVE_FILE_ERROR_ACCESS_DENIED); |
221 return; | 220 return; |
222 } | 221 } |
223 | 222 |
224 DriveEntryProto* entry = GetEntryByResourceId(resource_id); | 223 DriveEntryProto* entry = GetEntryByResourceId(resource_id); |
225 if (!entry) { | 224 if (!entry) { |
226 PostFileMoveCallbackError(callback, DRIVE_FILE_ERROR_NOT_FOUND); | 225 PostFileMoveCallbackError(callback, DRIVE_FILE_ERROR_NOT_FOUND); |
227 return; | 226 return; |
228 } | 227 } |
229 | 228 |
230 DriveEntryProto* parent = GetEntryByResourceId(entry->parent_resource_id()); | 229 const base::FilePath parent_file_path = |
231 DCHECK(parent && parent->file_info().is_directory()); | 230 GetFilePath(entry->parent_resource_id()); |
232 | 231 RemoveDirectoryChild(entry->resource_id()); |
233 RemoveDirectoryChild(parent, entry); | |
234 base::MessageLoopProxy::current()->PostTask( | 232 base::MessageLoopProxy::current()->PostTask( |
235 FROM_HERE, | 233 FROM_HERE, |
236 base::Bind(callback, DRIVE_FILE_OK, GetFilePath(*parent))); | 234 base::Bind(callback, DRIVE_FILE_OK, parent_file_path)); |
237 } | 235 } |
238 | 236 |
239 bool DriveResourceMetadata::AddEntryToResourceMap(DriveEntryProto* entry) { | 237 bool DriveResourceMetadata::AddEntryToResourceMap(DriveEntryProto* entry) { |
240 DVLOG(1) << "AddEntryToResourceMap " << entry->resource_id(); | 238 DVLOG(1) << "AddEntryToResourceMap " << entry->resource_id(); |
241 DCHECK(!entry->resource_id().empty()); | 239 DCHECK(!entry->resource_id().empty()); |
242 std::pair<ResourceMap::iterator, bool> ret = | 240 std::pair<ResourceMap::iterator, bool> ret = |
243 resource_map_.insert(std::make_pair(entry->resource_id(), entry)); | 241 resource_map_.insert(std::make_pair(entry->resource_id(), entry)); |
244 DCHECK(ret.second); // resource_id did not previously exist in the map. | 242 DCHECK(ret.second); // resource_id did not previously exist in the map. |
245 return ret.second; | 243 return ret.second; |
246 } | 244 } |
247 | 245 |
248 void DriveResourceMetadata::RemoveEntryFromResourceMap( | 246 void DriveResourceMetadata::RemoveEntryFromResourceMap( |
249 const std::string& resource_id) { | 247 const std::string& resource_id) { |
250 DVLOG(1) << "RemoveEntryFromResourceMap " << resource_id; | 248 DVLOG(1) << "RemoveEntryFromResourceMap " << resource_id; |
251 DCHECK(!resource_id.empty()); | 249 DCHECK(!resource_id.empty()); |
252 size_t ret = resource_map_.erase(resource_id); | 250 size_t ret = resource_map_.erase(resource_id); |
253 DCHECK_EQ(1u, ret); // resource_id was found in the map. | 251 DCHECK_EQ(1u, ret); // resource_id was found in the map. |
254 } | 252 } |
255 | 253 |
256 DriveEntryProto* DriveResourceMetadata::FindEntryByPathSync( | 254 DriveEntryProto* DriveResourceMetadata::FindEntryByPathSync( |
257 const base::FilePath& file_path) { | 255 const base::FilePath& file_path) { |
258 if (file_path == GetFilePath(*root_)) | 256 if (file_path == GetFilePath(root_->resource_id())) |
259 return root_.get(); | 257 return root_.get(); |
260 | 258 |
261 std::vector<base::FilePath::StringType> components; | 259 std::vector<base::FilePath::StringType> components; |
262 file_path.GetComponents(&components); | 260 file_path.GetComponents(&components); |
263 DriveEntryProto* current_dir = root_.get(); | 261 DriveEntryProto* current_dir = root_.get(); |
264 | 262 |
265 for (size_t i = 1; i < components.size() && current_dir; ++i) { | 263 for (size_t i = 1; i < components.size() && current_dir; ++i) { |
266 std::string resource_id = FindDirectoryChild(current_dir, components[i]); | 264 std::string resource_id = FindDirectoryChild(current_dir->resource_id(), |
265 components[i]); | |
267 if (resource_id.empty()) | 266 if (resource_id.empty()) |
268 return NULL; | 267 return NULL; |
269 | 268 |
270 DriveEntryProto* entry = GetEntryByResourceId(resource_id); | 269 DriveEntryProto* entry = GetEntryByResourceId(resource_id); |
271 DCHECK(entry); | 270 DCHECK(entry); |
272 | 271 |
273 if (i == components.size() - 1) // Last component. | 272 if (i == components.size() - 1) // Last component. |
274 return entry; | 273 return entry; |
275 if (!entry->file_info().is_directory()) | 274 if (!entry->file_info().is_directory()) |
276 return NULL; | 275 return NULL; |
(...skipping 16 matching lines...) Expand all Loading... | |
293 DCHECK(!callback.is_null()); | 292 DCHECK(!callback.is_null()); |
294 | 293 |
295 scoped_ptr<DriveEntryProto> entry_proto; | 294 scoped_ptr<DriveEntryProto> entry_proto; |
296 DriveFileError error = DRIVE_FILE_ERROR_FAILED; | 295 DriveFileError error = DRIVE_FILE_ERROR_FAILED; |
297 base::FilePath drive_file_path; | 296 base::FilePath drive_file_path; |
298 | 297 |
299 DriveEntryProto* entry = GetEntryByResourceId(resource_id); | 298 DriveEntryProto* entry = GetEntryByResourceId(resource_id); |
300 if (entry) { | 299 if (entry) { |
301 entry_proto.reset(new DriveEntryProto(*entry)); | 300 entry_proto.reset(new DriveEntryProto(*entry)); |
302 error = DRIVE_FILE_OK; | 301 error = DRIVE_FILE_OK; |
303 drive_file_path = GetFilePath(*entry); | 302 drive_file_path = GetFilePath(entry->resource_id()); |
304 } else { | 303 } else { |
305 error = DRIVE_FILE_ERROR_NOT_FOUND; | 304 error = DRIVE_FILE_ERROR_NOT_FOUND; |
306 } | 305 } |
307 | 306 |
308 base::MessageLoopProxy::current()->PostTask( | 307 base::MessageLoopProxy::current()->PostTask( |
309 FROM_HERE, | 308 FROM_HERE, |
310 base::Bind(callback, error, drive_file_path, base::Passed(&entry_proto))); | 309 base::Bind(callback, error, drive_file_path, base::Passed(&entry_proto))); |
311 } | 310 } |
312 | 311 |
313 void DriveResourceMetadata::GetEntryInfoByPath( | 312 void DriveResourceMetadata::GetEntryInfoByPath( |
(...skipping 22 matching lines...) Expand all Loading... | |
336 const base::FilePath& path, | 335 const base::FilePath& path, |
337 const ReadDirectoryCallback& callback) { | 336 const ReadDirectoryCallback& callback) { |
338 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 337 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
339 DCHECK(!callback.is_null()); | 338 DCHECK(!callback.is_null()); |
340 | 339 |
341 scoped_ptr<DriveEntryProtoVector> entries; | 340 scoped_ptr<DriveEntryProtoVector> entries; |
342 DriveFileError error = DRIVE_FILE_ERROR_FAILED; | 341 DriveFileError error = DRIVE_FILE_ERROR_FAILED; |
343 | 342 |
344 DriveEntryProto* entry = FindEntryByPathSync(path); | 343 DriveEntryProto* entry = FindEntryByPathSync(path); |
345 if (entry && entry->file_info().is_directory()) { | 344 if (entry && entry->file_info().is_directory()) { |
346 entries = DirectoryChildrenToProtoVector(entry); | 345 entries = DirectoryChildrenToProtoVector(entry->resource_id()); |
347 error = DRIVE_FILE_OK; | 346 error = DRIVE_FILE_OK; |
348 } else if (entry && !entry->file_info().is_directory()) { | 347 } else if (entry && !entry->file_info().is_directory()) { |
349 error = DRIVE_FILE_ERROR_NOT_A_DIRECTORY; | 348 error = DRIVE_FILE_ERROR_NOT_A_DIRECTORY; |
350 } else { | 349 } else { |
351 error = DRIVE_FILE_ERROR_NOT_FOUND; | 350 error = DRIVE_FILE_ERROR_NOT_FOUND; |
352 } | 351 } |
353 | 352 |
354 base::MessageLoopProxy::current()->PostTask( | 353 base::MessageLoopProxy::current()->PostTask( |
355 FROM_HERE, | 354 FROM_HERE, |
356 base::Bind(callback, error, base::Passed(&entries))); | 355 base::Bind(callback, error, base::Passed(&entries))); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
389 // Reject incompatible input. | 388 // Reject incompatible input. |
390 if (entry->file_info().is_directory() != | 389 if (entry->file_info().is_directory() != |
391 entry_proto.file_info().is_directory()) { | 390 entry_proto.file_info().is_directory()) { |
392 PostGetEntryInfoWithFilePathCallbackError( | 391 PostGetEntryInfoWithFilePathCallbackError( |
393 callback, DRIVE_FILE_ERROR_INVALID_OPERATION); | 392 callback, DRIVE_FILE_ERROR_INVALID_OPERATION); |
394 return; | 393 return; |
395 } | 394 } |
396 | 395 |
397 // Update data. | 396 // Update data. |
398 if (entry != root_.get()) { | 397 if (entry != root_.get()) { |
399 DriveEntryProto* old_parent = GetDirectory(entry->parent_resource_id()); | |
400 DriveEntryProto* new_parent = | 398 DriveEntryProto* new_parent = |
401 GetDirectory(entry_proto.parent_resource_id()); | 399 GetDirectory(entry_proto.parent_resource_id()); |
402 | 400 |
403 if (!old_parent || !new_parent) { | 401 if (!new_parent) { |
404 PostGetEntryInfoWithFilePathCallbackError( | 402 PostGetEntryInfoWithFilePathCallbackError( |
405 callback, DRIVE_FILE_ERROR_NOT_FOUND); | 403 callback, DRIVE_FILE_ERROR_NOT_FOUND); |
406 return; | 404 return; |
407 } | 405 } |
408 | 406 |
409 // Remove from the old parent, update the entry, and add it to the new | 407 // Remove from the old parent, update the entry, and add it to the new |
410 // parent. The order matters here. FromProto() could remove suffix like | 408 // parent. The order matters here. FromProto() could remove suffix like |
411 // "(2)" from entries with duplicate names. If FromProto() is first | 409 // "(2)" from entries with duplicate names. If FromProto() is first |
412 // called, RemoveChild() won't work correctly because of the missing | 410 // called, RemoveChild() won't work correctly because of the missing |
413 // suffix. | 411 // suffix. |
414 DetachEntryFromDirectory(old_parent, entry); | 412 DetachEntryFromDirectory(entry->resource_id()); |
415 // Note that it's safe to update the directory entry with | 413 // Note that it's safe to update the directory entry with |
416 // DriveEntry::FromProto() as it won't clear children. | 414 // DriveEntry::FromProto() as it won't clear children. |
417 *entry = CreateEntryWithProperBaseName(entry_proto); | 415 *entry = CreateEntryWithProperBaseName(entry_proto); |
418 AddEntryToDirectory(new_parent, entry); // Transfers ownership. | 416 entry->set_parent_resource_id(new_parent->resource_id()); |
kinaba
2013/03/15 05:48:08
Is this set_parent necessary?
At this point |entry
hashimoto
2013/03/15 06:40:23
Excellent catch.
Removed.
| |
417 AddEntryToDirectory(entry); // Transfers ownership. | |
419 } else { | 418 } else { |
420 // root has no parent. | 419 // root has no parent. |
421 *entry = CreateEntryWithProperBaseName(entry_proto); | 420 *entry = CreateEntryWithProperBaseName(entry_proto); |
422 } | 421 } |
423 | 422 |
424 DVLOG(1) << "RefreshEntry " << GetFilePath(*entry).value(); | 423 DVLOG(1) << "RefreshEntry " << GetFilePath(entry->resource_id()).value(); |
425 // Note that base_name is not the same for new_entry and entry_proto. | 424 // Note that base_name is not the same for new_entry and entry_proto. |
426 scoped_ptr<DriveEntryProto> result_entry_proto(new DriveEntryProto(*entry)); | 425 scoped_ptr<DriveEntryProto> result_entry_proto(new DriveEntryProto(*entry)); |
427 base::MessageLoopProxy::current()->PostTask( | 426 base::MessageLoopProxy::current()->PostTask( |
428 FROM_HERE, | 427 FROM_HERE, |
429 base::Bind(callback, | 428 base::Bind(callback, |
430 DRIVE_FILE_OK, | 429 DRIVE_FILE_OK, |
431 GetFilePath(*entry), | 430 GetFilePath(entry->resource_id()), |
432 base::Passed(&result_entry_proto))); | 431 base::Passed(&result_entry_proto))); |
433 } | 432 } |
434 | 433 |
435 void DriveResourceMetadata::RefreshDirectory( | 434 void DriveResourceMetadata::RefreshDirectory( |
436 const DirectoryFetchInfo& directory_fetch_info, | 435 const DirectoryFetchInfo& directory_fetch_info, |
437 const DriveEntryProtoMap& entry_proto_map, | 436 const DriveEntryProtoMap& entry_proto_map, |
438 const FileMoveCallback& callback) { | 437 const FileMoveCallback& callback) { |
439 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 438 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
440 DCHECK(!callback.is_null()); | 439 DCHECK(!callback.is_null()); |
441 DCHECK(!directory_fetch_info.empty()); | 440 DCHECK(!directory_fetch_info.empty()); |
(...skipping 28 matching lines...) Expand all Loading... | |
470 // crbug.com/193525. | 469 // crbug.com/193525. |
471 if (entry_proto.parent_resource_id() != | 470 if (entry_proto.parent_resource_id() != |
472 directory_fetch_info.resource_id()) { | 471 directory_fetch_info.resource_id()) { |
473 DVLOG(1) << "Wrong-parent entry rejected: " << entry_proto.resource_id(); | 472 DVLOG(1) << "Wrong-parent entry rejected: " << entry_proto.resource_id(); |
474 continue; | 473 continue; |
475 } | 474 } |
476 | 475 |
477 DriveEntryProto* existing_entry = | 476 DriveEntryProto* existing_entry = |
478 GetEntryByResourceId(entry_proto.resource_id()); | 477 GetEntryByResourceId(entry_proto.resource_id()); |
479 if (existing_entry) { | 478 if (existing_entry) { |
480 DriveEntryProto* old_parent = | |
481 GetDirectory(existing_entry->parent_resource_id()); | |
482 DCHECK(old_parent && old_parent->file_info().is_directory()); | |
483 // See the comment in RefreshEntry() for why the existing entry is | 479 // See the comment in RefreshEntry() for why the existing entry is |
484 // updated in this way. | 480 // updated in this way. |
485 DetachEntryFromDirectory(old_parent, existing_entry); | 481 DetachEntryFromDirectory(existing_entry->resource_id()); |
486 *existing_entry = CreateEntryWithProperBaseName(entry_proto); | 482 *existing_entry = CreateEntryWithProperBaseName(entry_proto); |
487 AddEntryToDirectory(directory, existing_entry); | 483 AddEntryToDirectory(existing_entry); |
488 } else { // New entry. | 484 } else { // New entry. |
489 // A new directory will have changestamp of zero, so the directory will | 485 // A new directory will have changestamp of zero, so the directory will |
490 // be "fast-fetched". See crbug.com/178348 for details. | 486 // be "fast-fetched". See crbug.com/178348 for details. |
491 scoped_ptr<DriveEntryProto> new_entry( | 487 scoped_ptr<DriveEntryProto> new_entry( |
492 new DriveEntryProto(CreateEntryWithProperBaseName(entry_proto))); | 488 new DriveEntryProto(CreateEntryWithProperBaseName(entry_proto))); |
493 AddEntryToDirectory(directory, new_entry.release()); | 489 AddEntryToDirectory(new_entry.release()); |
494 } | 490 } |
495 } | 491 } |
496 | 492 |
497 // Go through the existing entries and remove deleted entries. | 493 // Go through the existing entries and remove deleted entries. |
498 scoped_ptr<DriveEntryProtoVector> entries = | 494 scoped_ptr<DriveEntryProtoVector> entries = |
499 DirectoryChildrenToProtoVector(directory); | 495 DirectoryChildrenToProtoVector(directory->resource_id()); |
500 for (size_t i = 0; i < entries->size(); ++i) { | 496 for (size_t i = 0; i < entries->size(); ++i) { |
501 const DriveEntryProto& entry_proto = entries->at(i); | 497 const DriveEntryProto& entry_proto = entries->at(i); |
502 if (entry_proto_map.count(entry_proto.resource_id()) == 0) { | 498 if (entry_proto_map.count(entry_proto.resource_id()) == 0) |
503 DriveEntryProto* entry = GetEntryByResourceId(entry_proto.resource_id()); | 499 RemoveDirectoryChild(entry_proto.resource_id()); |
504 RemoveDirectoryChild(directory, entry); | |
505 } | |
506 } | 500 } |
507 | 501 |
508 base::MessageLoopProxy::current()->PostTask( | 502 base::MessageLoopProxy::current()->PostTask( |
509 FROM_HERE, | 503 FROM_HERE, |
510 base::Bind(callback, DRIVE_FILE_OK, GetFilePath(*directory))); | 504 base::Bind(callback, DRIVE_FILE_OK, |
505 GetFilePath(directory->resource_id()))); | |
511 } | 506 } |
512 | 507 |
513 void DriveResourceMetadata::AddEntry(const DriveEntryProto& entry_proto, | 508 void DriveResourceMetadata::AddEntry(const DriveEntryProto& entry_proto, |
514 const FileMoveCallback& callback) { | 509 const FileMoveCallback& callback) { |
515 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 510 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
516 DCHECK(!callback.is_null()); | 511 DCHECK(!callback.is_null()); |
517 | 512 |
518 DriveEntryProto* parent = GetDirectory(entry_proto.parent_resource_id()); | 513 DriveEntryProto* parent = GetDirectory(entry_proto.parent_resource_id()); |
519 if (!parent) { | 514 if (!parent) { |
520 PostFileMoveCallbackError(callback, DRIVE_FILE_ERROR_NOT_FOUND); | 515 PostFileMoveCallbackError(callback, DRIVE_FILE_ERROR_NOT_FOUND); |
521 return; | 516 return; |
522 } | 517 } |
523 | 518 |
524 DriveEntryProto* added_entry = | 519 DriveEntryProto* added_entry = |
525 new DriveEntryProto(CreateEntryWithProperBaseName(entry_proto)); | 520 new DriveEntryProto(CreateEntryWithProperBaseName(entry_proto)); |
526 AddEntryToDirectory(parent, added_entry); // Transfers ownership. | 521 AddEntryToDirectory(added_entry); // Transfers ownership. |
527 base::MessageLoopProxy::current()->PostTask( | 522 base::MessageLoopProxy::current()->PostTask( |
528 FROM_HERE, | 523 FROM_HERE, |
529 base::Bind(callback, DRIVE_FILE_OK, GetFilePath(*added_entry))); | 524 base::Bind(callback, DRIVE_FILE_OK, |
525 GetFilePath(added_entry->resource_id()))); | |
530 } | 526 } |
531 | 527 |
532 DriveEntryProto* DriveResourceMetadata::GetDirectory( | 528 DriveEntryProto* DriveResourceMetadata::GetDirectory( |
533 const std::string& resource_id) { | 529 const std::string& resource_id) { |
534 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 530 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
535 DCHECK(!resource_id.empty()); | 531 DCHECK(!resource_id.empty()); |
536 | 532 |
537 DriveEntryProto* entry = GetEntryByResourceId(resource_id); | 533 DriveEntryProto* entry = GetEntryByResourceId(resource_id); |
538 return entry && entry->file_info().is_directory() ? entry : NULL; | 534 return entry && entry->file_info().is_directory() ? entry : NULL; |
539 } | 535 } |
540 | 536 |
541 base::FilePath DriveResourceMetadata::GetFilePath( | 537 base::FilePath DriveResourceMetadata::GetFilePath( |
542 const DriveEntryProto& entry) { | 538 const std::string& resource_id) { |
539 DriveEntryProto* entry = GetEntryByResourceId(resource_id); | |
540 DCHECK(entry); | |
543 base::FilePath path; | 541 base::FilePath path; |
544 DriveEntryProto* parent = entry.parent_resource_id().empty() ? NULL : | 542 if (!entry->parent_resource_id().empty()) |
545 GetEntryByResourceId(entry.parent_resource_id()); | 543 path = GetFilePath(entry->parent_resource_id()); |
546 if (parent) | 544 path = path.Append(entry->base_name()); |
547 path = GetFilePath(*parent); | |
548 path = path.Append(entry.base_name()); | |
549 return path; | 545 return path; |
550 } | 546 } |
551 | 547 |
552 void DriveResourceMetadata::GetChildDirectories( | 548 void DriveResourceMetadata::GetChildDirectories( |
553 const std::string& resource_id, | 549 const std::string& resource_id, |
554 const GetChildDirectoriesCallback& changed_dirs_callback) { | 550 const GetChildDirectoriesCallback& changed_dirs_callback) { |
555 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 551 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
556 DCHECK(!changed_dirs_callback.is_null()); | 552 DCHECK(!changed_dirs_callback.is_null()); |
557 | 553 |
558 std::set<base::FilePath> changed_directories; | 554 std::set<base::FilePath> changed_directories; |
559 DriveEntryProto* entry = GetEntryByResourceId(resource_id); | 555 DriveEntryProto* entry = GetEntryByResourceId(resource_id); |
560 DriveEntryProto* directory = | 556 DriveEntryProto* directory = |
561 entry && entry->file_info().is_directory() ? entry : NULL; | 557 entry && entry->file_info().is_directory() ? entry : NULL; |
562 if (directory) | 558 if (directory) |
563 GetDescendantDirectoryPaths(*directory, &changed_directories); | 559 GetDescendantDirectoryPaths(directory->resource_id(), &changed_directories); |
564 | 560 |
565 base::MessageLoopProxy::current()->PostTask( | 561 base::MessageLoopProxy::current()->PostTask( |
566 FROM_HERE, | 562 FROM_HERE, |
567 base::Bind(changed_dirs_callback, changed_directories)); | 563 base::Bind(changed_dirs_callback, changed_directories)); |
568 } | 564 } |
569 | 565 |
570 void DriveResourceMetadata::GetDescendantDirectoryPaths( | 566 void DriveResourceMetadata::GetDescendantDirectoryPaths( |
571 const DriveEntryProto& directory, | 567 const std::string& directory_resource_id, |
572 std::set<base::FilePath>* child_directories) { | 568 std::set<base::FilePath>* child_directories) { |
573 DCHECK(directory.file_info().is_directory()); | 569 const ChildMap& children = child_maps_[directory_resource_id]; |
574 const ChildMap& children = child_maps_[directory.resource_id()]; | |
575 for (ChildMap::const_iterator iter = children.begin(); | 570 for (ChildMap::const_iterator iter = children.begin(); |
576 iter != children.end(); ++iter) { | 571 iter != children.end(); ++iter) { |
577 DriveEntryProto* entry = GetEntryByResourceId(iter->second); | 572 DriveEntryProto* entry = GetEntryByResourceId(iter->second); |
578 if (entry && entry->file_info().is_directory()) { | 573 if (entry && entry->file_info().is_directory()) { |
579 child_directories->insert(GetFilePath(*entry)); | 574 child_directories->insert(GetFilePath(entry->resource_id())); |
580 GetDescendantDirectoryPaths(*entry, child_directories); | 575 GetDescendantDirectoryPaths(entry->resource_id(), child_directories); |
581 } | 576 } |
582 } | 577 } |
583 } | 578 } |
584 | 579 |
585 void DriveResourceMetadata::RemoveAll(const base::Closure& callback) { | 580 void DriveResourceMetadata::RemoveAll(const base::Closure& callback) { |
586 RemoveDirectoryChildren(root_.get()); | 581 RemoveDirectoryChildren(root_->resource_id()); |
587 base::MessageLoopProxy::current()->PostTask(FROM_HERE, callback); | 582 base::MessageLoopProxy::current()->PostTask(FROM_HERE, callback); |
588 } | 583 } |
589 | 584 |
590 void DriveResourceMetadata::SerializeToString(std::string* serialized_proto) { | 585 void DriveResourceMetadata::SerializeToString(std::string* serialized_proto) { |
591 DriveRootDirectoryProto proto; | 586 DriveRootDirectoryProto proto; |
592 DirectoryToProto(root_.get(), proto.mutable_drive_directory()); | 587 DirectoryToProto(root_->resource_id(), proto.mutable_drive_directory()); |
593 proto.set_largest_changestamp(largest_changestamp_); | 588 proto.set_largest_changestamp(largest_changestamp_); |
594 proto.set_version(kProtoVersion); | 589 proto.set_version(kProtoVersion); |
595 | 590 |
596 const bool ok = proto.SerializeToString(serialized_proto); | 591 const bool ok = proto.SerializeToString(serialized_proto); |
597 DCHECK(ok); | 592 DCHECK(ok); |
598 } | 593 } |
599 | 594 |
600 bool DriveResourceMetadata::ParseFromString( | 595 bool DriveResourceMetadata::ParseFromString( |
601 const std::string& serialized_proto) { | 596 const std::string& serialized_proto) { |
602 DriveRootDirectoryProto proto; | 597 DriveRootDirectoryProto proto; |
603 if (!proto.ParseFromString(serialized_proto)) | 598 if (!proto.ParseFromString(serialized_proto)) |
604 return false; | 599 return false; |
605 | 600 |
606 if (proto.version() != kProtoVersion) { | 601 if (proto.version() != kProtoVersion) { |
607 LOG(ERROR) << "Incompatible proto detected (incompatible version): " | 602 LOG(ERROR) << "Incompatible proto detected (incompatible version): " |
608 << proto.version(); | 603 << proto.version(); |
609 return false; | 604 return false; |
610 } | 605 } |
611 | 606 |
612 // An old proto file might not have per-directory changestamps. Add them if | 607 // An old proto file might not have per-directory changestamps. Add them if |
613 // needed. | 608 // needed. |
614 const DriveDirectoryProto& root = proto.drive_directory(); | 609 const DriveDirectoryProto& root = proto.drive_directory(); |
615 if (!root.drive_entry().directory_specific_info().has_changestamp()) { | 610 if (!root.drive_entry().directory_specific_info().has_changestamp()) { |
616 AddPerDirectoryChangestamps(proto.mutable_drive_directory(), | 611 AddPerDirectoryChangestamps(proto.mutable_drive_directory(), |
617 proto.largest_changestamp()); | 612 proto.largest_changestamp()); |
618 } | 613 } |
619 | 614 |
620 ProtoToDirectory(proto.drive_directory(), root_.get()); | 615 if (proto.drive_directory().drive_entry().resource_id() != |
616 root_->resource_id()) { | |
617 LOG(ERROR) << "Incompatible proto detected (incompatible root ID): " | |
618 << proto.drive_directory().drive_entry().resource_id(); | |
619 return false; | |
620 } | |
621 | |
622 ProtoToDirectory(proto.drive_directory()); | |
621 | 623 |
622 loaded_ = true; | 624 loaded_ = true; |
623 largest_changestamp_ = proto.largest_changestamp(); | 625 largest_changestamp_ = proto.largest_changestamp(); |
624 | 626 |
625 return true; | 627 return true; |
626 } | 628 } |
627 | 629 |
628 void DriveResourceMetadata::GetEntryInfoPairByPathsAfterGetFirst( | 630 void DriveResourceMetadata::GetEntryInfoPairByPathsAfterGetFirst( |
629 const base::FilePath& first_path, | 631 const base::FilePath& first_path, |
630 const base::FilePath& second_path, | 632 const base::FilePath& second_path, |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
665 DCHECK(!callback.is_null()); | 667 DCHECK(!callback.is_null()); |
666 DCHECK(result.get()); | 668 DCHECK(result.get()); |
667 | 669 |
668 result->second.path = second_path; | 670 result->second.path = second_path; |
669 result->second.error = error; | 671 result->second.error = error; |
670 result->second.proto = entry_proto.Pass(); | 672 result->second.proto = entry_proto.Pass(); |
671 | 673 |
672 callback.Run(result.Pass()); | 674 callback.Run(result.Pass()); |
673 } | 675 } |
674 | 676 |
675 void DriveResourceMetadata::AddEntryToDirectory(DriveEntryProto* directory, | 677 void DriveResourceMetadata::AddEntryToDirectory(DriveEntryProto* entry) { |
676 DriveEntryProto* entry) { | |
677 DCHECK(directory->file_info().is_directory()); | |
678 DCHECK(entry->parent_resource_id().empty() || | |
679 entry->parent_resource_id() == directory->resource_id()); | |
680 | |
681 // Try to add the entry to resource map. | 678 // Try to add the entry to resource map. |
682 if (!AddEntryToResourceMap(entry)) { | 679 if (!AddEntryToResourceMap(entry)) { |
683 LOG(WARNING) << "Duplicate resource=" << entry->resource_id() | 680 LOG(WARNING) << "Duplicate resource=" << entry->resource_id() |
684 << ", title=" << entry->title(); | 681 << ", title=" << entry->title(); |
685 return; | 682 return; |
686 } | 683 } |
687 | 684 |
688 // The entry name may have been changed due to prior name de-duplication. | 685 // The entry name may have been changed due to prior name de-duplication. |
689 // We need to first restore the file name based on the title before going | 686 // We need to first restore the file name based on the title before going |
690 // through name de-duplication again when it is added to another directory. | 687 // through name de-duplication again when it is added to another directory. |
691 SetBaseNameFromTitle(entry); | 688 SetBaseNameFromTitle(entry); |
692 | 689 |
693 // Do file name de-duplication - find files with the same name and | 690 // Do file name de-duplication - find files with the same name and |
694 // append a name modifier to the name. | 691 // append a name modifier to the name. |
695 int modifier = 1; | 692 int modifier = 1; |
696 base::FilePath full_file_name(entry->base_name()); | 693 base::FilePath full_file_name(entry->base_name()); |
697 const std::string extension = full_file_name.Extension(); | 694 const std::string extension = full_file_name.Extension(); |
698 const std::string file_name = full_file_name.RemoveExtension().value(); | 695 const std::string file_name = full_file_name.RemoveExtension().value(); |
699 while (!FindDirectoryChild(directory, full_file_name.value()).empty()) { | 696 while (!FindDirectoryChild(entry->parent_resource_id(), |
697 full_file_name.value()).empty()) { | |
700 if (!extension.empty()) { | 698 if (!extension.empty()) { |
701 full_file_name = base::FilePath(base::StringPrintf("%s (%d)%s", | 699 full_file_name = base::FilePath(base::StringPrintf("%s (%d)%s", |
702 file_name.c_str(), | 700 file_name.c_str(), |
703 ++modifier, | 701 ++modifier, |
704 extension.c_str())); | 702 extension.c_str())); |
705 } else { | 703 } else { |
706 full_file_name = base::FilePath(base::StringPrintf("%s (%d)", | 704 full_file_name = base::FilePath(base::StringPrintf("%s (%d)", |
707 file_name.c_str(), | 705 file_name.c_str(), |
708 ++modifier)); | 706 ++modifier)); |
709 } | 707 } |
710 } | 708 } |
711 entry->set_base_name(full_file_name.value()); | 709 entry->set_base_name(full_file_name.value()); |
712 | 710 |
713 // Setup child and parent links. | 711 // Setup child and parent links. |
714 child_maps_[directory->resource_id()].insert( | 712 child_maps_[entry->parent_resource_id()].insert( |
715 std::make_pair(entry->base_name(), entry->resource_id())); | 713 std::make_pair(entry->base_name(), entry->resource_id())); |
716 entry->set_parent_resource_id(directory->resource_id()); | |
717 } | 714 } |
718 | 715 |
719 void DriveResourceMetadata::RemoveDirectoryChild(DriveEntryProto* directory, | 716 void DriveResourceMetadata::RemoveDirectoryChild( |
720 DriveEntryProto* entry) { | 717 const std::string& child_resource_id) { |
721 DCHECK(directory->file_info().is_directory()); | 718 DriveEntryProto* entry = GetEntryByResourceId(child_resource_id); |
722 DetachEntryFromDirectory(directory, entry); | 719 DCHECK(entry); |
720 DetachEntryFromDirectory(child_resource_id); | |
723 if (entry->file_info().is_directory()) | 721 if (entry->file_info().is_directory()) |
724 RemoveDirectoryChildren(entry); | 722 RemoveDirectoryChildren(child_resource_id); |
725 delete entry; | 723 delete entry; |
726 } | 724 } |
727 | 725 |
728 std::string DriveResourceMetadata::FindDirectoryChild( | 726 std::string DriveResourceMetadata::FindDirectoryChild( |
729 DriveEntryProto* directory, | 727 const std::string& directory_resource_id, |
730 const base::FilePath::StringType& file_name) { | 728 const base::FilePath::StringType& file_name) { |
731 DCHECK(directory->file_info().is_directory()); | 729 const ChildMap& children = child_maps_[directory_resource_id]; |
732 const ChildMap& children = child_maps_[directory->resource_id()]; | |
733 DriveResourceMetadata::ChildMap::const_iterator iter = | 730 DriveResourceMetadata::ChildMap::const_iterator iter = |
734 children.find(file_name); | 731 children.find(file_name); |
735 if (iter != children.end()) | 732 if (iter != children.end()) |
736 return iter->second; | 733 return iter->second; |
737 return std::string(); | 734 return std::string(); |
738 } | 735 } |
739 | 736 |
740 void DriveResourceMetadata::DetachEntryFromDirectory( | 737 void DriveResourceMetadata::DetachEntryFromDirectory( |
741 DriveEntryProto* directory, | 738 const std::string& child_resource_id) { |
742 DriveEntryProto* entry) { | 739 DriveEntryProto* entry = GetEntryByResourceId(child_resource_id); |
743 DCHECK(directory->file_info().is_directory()); | |
744 DCHECK(entry); | 740 DCHECK(entry); |
745 | 741 |
746 const std::string& base_name(entry->base_name()); | 742 const std::string& base_name(entry->base_name()); |
747 // entry must be present in this directory. | 743 // entry must be present in this directory. |
748 DCHECK_EQ(entry->resource_id(), FindDirectoryChild(directory, base_name)); | 744 DCHECK_EQ(entry->resource_id(), |
745 FindDirectoryChild(entry->parent_resource_id(), base_name)); | |
749 // Remove entry from resource map first. | 746 // Remove entry from resource map first. |
750 RemoveEntryFromResourceMap(entry->resource_id()); | 747 RemoveEntryFromResourceMap(entry->resource_id()); |
751 | 748 |
752 // Then delete it from tree. | 749 // Then delete it from tree. |
753 child_maps_[directory->resource_id()].erase(base_name); | 750 child_maps_[entry->parent_resource_id()].erase(base_name); |
754 | 751 |
755 entry->set_parent_resource_id(std::string()); | 752 entry->set_parent_resource_id(std::string()); |
756 } | 753 } |
757 | 754 |
758 void DriveResourceMetadata::RemoveDirectoryChildren( | 755 void DriveResourceMetadata::RemoveDirectoryChildren( |
759 DriveEntryProto* directory) { | 756 const std::string& directory_resource_id) { |
760 DCHECK(directory->file_info().is_directory()); | |
761 DriveResourceMetadata::ChildMap* children = | 757 DriveResourceMetadata::ChildMap* children = |
762 &child_maps_[directory->resource_id()]; | 758 &child_maps_[directory_resource_id]; |
763 for (DriveResourceMetadata::ChildMap::iterator iter = children->begin(); | 759 for (DriveResourceMetadata::ChildMap::iterator iter = children->begin(); |
764 iter != children->end(); ++iter) { | 760 iter != children->end(); ++iter) { |
765 DriveEntryProto* child = GetEntryByResourceId(iter->second); | 761 DriveEntryProto* child = GetEntryByResourceId(iter->second); |
766 DCHECK(child); | 762 DCHECK(child); |
767 // Remove directories recursively. | 763 // Remove directories recursively. |
768 if (child->file_info().is_directory()) | 764 if (child->file_info().is_directory()) |
769 RemoveDirectoryChildren(child); | 765 RemoveDirectoryChildren(child->resource_id()); |
770 | 766 |
771 RemoveEntryFromResourceMap(iter->second); | 767 RemoveEntryFromResourceMap(iter->second); |
772 delete child; | 768 delete child; |
773 } | 769 } |
774 child_maps_.erase(directory->resource_id()); | 770 child_maps_.erase(directory_resource_id); |
775 } | 771 } |
776 | 772 |
777 void DriveResourceMetadata::ProtoToDirectory(const DriveDirectoryProto& proto, | 773 void DriveResourceMetadata::ProtoToDirectory(const DriveDirectoryProto& proto) { |
778 DriveEntryProto* directory) { | |
779 DCHECK(proto.drive_entry().file_info().is_directory()); | 774 DCHECK(proto.drive_entry().file_info().is_directory()); |
780 DCHECK(!proto.drive_entry().has_file_specific_info()); | 775 DCHECK(!proto.drive_entry().has_file_specific_info()); |
781 | 776 |
777 DriveEntryProto* directory = | |
778 GetEntryByResourceId(proto.drive_entry().resource_id()); | |
779 // Allocate a new DriveEntryProto when missing. | |
780 if (!directory) { | |
781 // No need to care about root missing case. | |
kinaba
2013/03/15 05:48:08
Inversely, do we need to care about non-root exist
hashimoto
2013/03/15 06:40:23
Added a DCHECK(child_maps_[proto.drive_entry().res
| |
782 DCHECK(!proto.drive_entry().parent_resource_id().empty()); | |
783 directory = new DriveEntryProto; | |
784 } | |
785 | |
786 // Set entry properties. | |
782 *directory = CreateEntryWithProperBaseName(proto.drive_entry()); | 787 *directory = CreateEntryWithProperBaseName(proto.drive_entry()); |
783 | 788 |
789 // Become a child of the parent. | |
790 if (!directory->parent_resource_id().empty()) | |
791 AddEntryToDirectory(directory); // Transfer ownership. | |
kinaba
2013/03/15 05:48:08
If the "Allocate a new DriveEntryProto when missin
hashimoto
2013/03/15 06:40:23
Moved directory allocation to under the for loop f
| |
792 | |
793 // Add child files. | |
784 for (int i = 0; i < proto.child_files_size(); ++i) { | 794 for (int i = 0; i < proto.child_files_size(); ++i) { |
785 scoped_ptr<DriveEntryProto> file(new DriveEntryProto( | 795 scoped_ptr<DriveEntryProto> file(new DriveEntryProto( |
786 CreateEntryWithProperBaseName(proto.child_files(i)))); | 796 CreateEntryWithProperBaseName(proto.child_files(i)))); |
787 AddEntryToDirectory(directory, file.release()); | 797 DCHECK_EQ(directory->resource_id(), file->parent_resource_id()); |
798 AddEntryToDirectory(file.release()); | |
788 } | 799 } |
800 // Add child directories recursively. | |
789 for (int i = 0; i < proto.child_directories_size(); ++i) { | 801 for (int i = 0; i < proto.child_directories_size(); ++i) { |
790 scoped_ptr<DriveEntryProto> child_dir(new DriveEntryProto); | 802 DCHECK_EQ(directory->resource_id(), |
791 ProtoToDirectory(proto.child_directories(i), child_dir.get()); | 803 proto.child_directories(i).drive_entry().parent_resource_id()); |
792 AddEntryToDirectory(directory, child_dir.release()); | 804 ProtoToDirectory(proto.child_directories(i)); |
793 } | 805 } |
794 } | 806 } |
795 | 807 |
796 void DriveResourceMetadata::DirectoryToProto(DriveEntryProto* directory, | 808 void DriveResourceMetadata::DirectoryToProto( |
797 DriveDirectoryProto* proto) { | 809 const std::string& directory_resource_id, |
810 DriveDirectoryProto* proto) { | |
811 DriveEntryProto* directory = GetEntryByResourceId(directory_resource_id); | |
812 DCHECK(directory); | |
798 *proto->mutable_drive_entry() = *directory; | 813 *proto->mutable_drive_entry() = *directory; |
799 DCHECK(proto->drive_entry().file_info().is_directory()); | 814 DCHECK(proto->drive_entry().file_info().is_directory()); |
800 | 815 |
801 const ChildMap& children = child_maps_[directory->resource_id()]; | 816 const ChildMap& children = child_maps_[directory_resource_id]; |
802 for (ChildMap::const_iterator iter = children.begin(); | 817 for (ChildMap::const_iterator iter = children.begin(); |
803 iter != children.end(); ++iter) { | 818 iter != children.end(); ++iter) { |
804 DriveEntryProto* entry = GetEntryByResourceId(iter->second); | 819 DriveEntryProto* entry = GetEntryByResourceId(iter->second); |
805 DCHECK(entry); | 820 DCHECK(entry); |
806 if (entry->file_info().is_directory()) | 821 if (entry->file_info().is_directory()) |
807 DirectoryToProto(entry, proto->add_child_directories()); | 822 DirectoryToProto(entry->resource_id(), proto->add_child_directories()); |
808 else | 823 else |
809 *proto->add_child_files() = *entry; | 824 *proto->add_child_files() = *entry; |
810 } | 825 } |
811 } | 826 } |
812 | 827 |
813 scoped_ptr<DriveEntryProtoVector> | 828 scoped_ptr<DriveEntryProtoVector> |
814 DriveResourceMetadata::DirectoryChildrenToProtoVector( | 829 DriveResourceMetadata::DirectoryChildrenToProtoVector( |
815 DriveEntryProto* directory) { | 830 const std::string& directory_resource_id) { |
816 DCHECK(directory->file_info().is_directory()); | |
817 scoped_ptr<DriveEntryProtoVector> entries(new DriveEntryProtoVector); | 831 scoped_ptr<DriveEntryProtoVector> entries(new DriveEntryProtoVector); |
818 const ChildMap& children = child_maps_[directory->resource_id()]; | 832 const ChildMap& children = child_maps_[directory_resource_id]; |
819 for (ChildMap::const_iterator iter = children.begin(); | 833 for (ChildMap::const_iterator iter = children.begin(); |
820 iter != children.end(); ++iter) { | 834 iter != children.end(); ++iter) { |
821 const DriveEntryProto& proto = *GetEntryByResourceId(iter->second); | 835 const DriveEntryProto* child = GetEntryByResourceId(iter->second); |
822 entries->push_back(proto); | 836 DCHECK(child); |
837 entries->push_back(*child); | |
823 } | 838 } |
824 return entries.Pass(); | 839 return entries.Pass(); |
825 } | 840 } |
826 | 841 |
827 } // namespace drive | 842 } // namespace drive |
OLD | NEW |