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/gdata/gdata_files.h" | 5 #include "chrome/browser/chromeos/gdata/gdata_files.h" |
6 | 6 |
7 #include <vector> | 7 #include <vector> |
8 | 8 |
9 #include "base/utf_string_conversions.h" | 9 #include "base/utf_string_conversions.h" |
10 #include "base/platform_file.h" | 10 #include "base/platform_file.h" |
11 #include "base/stringprintf.h" | 11 #include "base/stringprintf.h" |
12 #include "base/string_util.h" | 12 #include "base/string_util.h" |
13 #include "chrome/browser/chromeos/gdata/find_entry_delegate.h" | 13 #include "chrome/browser/chromeos/gdata/find_entry_delegate.h" |
14 #include "chrome/browser/chromeos/gdata/gdata.pb.h" | 14 #include "chrome/browser/chromeos/gdata/gdata.pb.h" |
15 #include "chrome/browser/chromeos/gdata/gdata_parser.h" | 15 #include "chrome/browser/chromeos/gdata/gdata_parser.h" |
16 #include "chrome/browser/chromeos/gdata/gdata_util.h" | |
16 #include "net/base/escape.h" | 17 #include "net/base/escape.h" |
17 | 18 |
18 namespace gdata { | 19 namespace gdata { |
19 namespace { | 20 namespace { |
20 | 21 |
21 // Content refresh time. | 22 // Content refresh time. |
22 #ifndef NDEBUG | 23 #ifndef NDEBUG |
23 const int kRefreshTimeInSec = 10; | 24 const int kRefreshTimeInSec = 10; |
24 #else | 25 #else |
25 const int kRefreshTimeInSec = 5*60; | 26 const int kRefreshTimeInSec = 5*60; |
(...skipping 285 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
311 } | 312 } |
312 entry->set_file_name(full_file_name.value()); | 313 entry->set_file_name(full_file_name.value()); |
313 | 314 |
314 DVLOG(1) << "AddEntry: dir = " << GetFilePath().value() | 315 DVLOG(1) << "AddEntry: dir = " << GetFilePath().value() |
315 << ", file = " + entry->file_name() | 316 << ", file = " + entry->file_name() |
316 << ", parent resource = " << entry->parent_resource_id() | 317 << ", parent resource = " << entry->parent_resource_id() |
317 << ", resource = " + entry->resource_id(); | 318 << ", resource = " + entry->resource_id(); |
318 | 319 |
319 | 320 |
320 // Add entry to resource map. | 321 // Add entry to resource map. |
321 root_->AddEntryToResourceMap(entry); | 322 if (root_) |
323 root_->AddEntryToResourceMap(entry); | |
324 | |
322 // Setup child and parent links. | 325 // Setup child and parent links. |
323 AddChild(entry); | 326 AddChild(entry); |
324 entry->SetParent(this); | 327 entry->SetParent(this); |
325 } | 328 } |
326 | 329 |
327 bool GDataDirectory::TakeEntry(GDataEntry* entry) { | 330 bool GDataDirectory::TakeEntry(GDataEntry* entry) { |
328 DCHECK(entry); | 331 DCHECK(entry); |
329 DCHECK(entry->parent()); | 332 DCHECK(entry->parent()); |
330 | 333 |
331 entry->parent()->RemoveChild(entry); | 334 entry->parent()->RemoveChild(entry); |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
390 DCHECK(entry); | 393 DCHECK(entry); |
391 | 394 |
392 const std::string file_name(entry->file_name()); | 395 const std::string file_name(entry->file_name()); |
393 GDataEntry* found_entry = FindChild(file_name); | 396 GDataEntry* found_entry = FindChild(file_name); |
394 if (!found_entry) | 397 if (!found_entry) |
395 return false; | 398 return false; |
396 | 399 |
397 DCHECK_EQ(entry, found_entry); | 400 DCHECK_EQ(entry, found_entry); |
398 | 401 |
399 // Remove entry from resource map first. | 402 // Remove entry from resource map first. |
400 root_->RemoveEntryFromResourceMap(entry); | 403 if (root_) |
404 root_->RemoveEntryFromResourceMap(entry); | |
401 | 405 |
402 // Then delete it from tree. | 406 // Then delete it from tree. |
403 child_files_.erase(file_name); | 407 child_files_.erase(file_name); |
404 child_directories_.erase(file_name); | 408 child_directories_.erase(file_name); |
405 | 409 |
406 return true; | 410 return true; |
407 } | 411 } |
408 | 412 |
409 void GDataDirectory::RemoveChildren() { | 413 void GDataDirectory::RemoveChildren() { |
410 // Remove child files first. | 414 // Remove child files first. |
411 for (GDataFileCollection::const_iterator iter = child_files_.begin(); | 415 for (GDataFileCollection::const_iterator iter = child_files_.begin(); |
412 iter != child_files_.end(); ++iter) { | 416 iter != child_files_.end(); ++iter) { |
413 root_->RemoveEntryFromResourceMap(iter->second); | 417 if (root_) |
418 root_->RemoveEntryFromResourceMap(iter->second); | |
414 } | 419 } |
415 STLDeleteValues(&child_files_); | 420 STLDeleteValues(&child_files_); |
416 child_files_.clear(); | 421 child_files_.clear(); |
417 | 422 |
418 for (GDataDirectoryCollection::iterator iter = child_directories_.begin(); | 423 for (GDataDirectoryCollection::iterator iter = child_directories_.begin(); |
419 iter != child_directories_.end(); ++iter) { | 424 iter != child_directories_.end(); ++iter) { |
420 GDataDirectory* dir = iter->second; | 425 GDataDirectory* dir = iter->second; |
421 // Remove directories recursively. | 426 // Remove directories recursively. |
422 dir->RemoveChildren(); | 427 dir->RemoveChildren(); |
423 root_->RemoveEntryFromResourceMap(dir); | 428 if (root_) |
429 root_->RemoveEntryFromResourceMap(dir); | |
424 } | 430 } |
425 STLDeleteValues(&child_directories_); | 431 STLDeleteValues(&child_directories_); |
426 child_directories_.clear(); | 432 child_directories_.clear(); |
427 } | 433 } |
428 | 434 |
429 // GDataRootDirectory::CacheEntry struct implementation. | 435 // GDataRootDirectory::CacheEntry struct implementation. |
430 | 436 |
431 std::string GDataRootDirectory::CacheEntry::ToString() const { | 437 std::string GDataRootDirectory::CacheEntry::ToString() const { |
432 std::vector<std::string> cache_states; | 438 std::vector<std::string> cache_states; |
433 if (GDataFile::IsCachePresent(cache_state)) | 439 if (GDataFile::IsCachePresent(cache_state)) |
434 cache_states.push_back("present"); | 440 cache_states.push_back("present"); |
435 if (GDataFile::IsCachePinned(cache_state)) | 441 if (GDataFile::IsCachePinned(cache_state)) |
436 cache_states.push_back("pinned"); | 442 cache_states.push_back("pinned"); |
437 if (GDataFile::IsCacheDirty(cache_state)) | 443 if (GDataFile::IsCacheDirty(cache_state)) |
438 cache_states.push_back("dirty"); | 444 cache_states.push_back("dirty"); |
439 | 445 |
440 return base::StringPrintf("md5=%s, subdir=%s, cache_state=%s", | 446 return base::StringPrintf("md5=%s, subdir=%s, cache_state=%s", |
441 md5.c_str(), | 447 md5.c_str(), |
442 CacheSubDirectoryTypeToString(sub_dir_type).c_str(), | 448 CacheSubDirectoryTypeToString(sub_dir_type).c_str(), |
443 JoinString(cache_states, ',').c_str()); | 449 JoinString(cache_states, ',').c_str()); |
444 } | 450 } |
445 | 451 |
446 // GDataRootDirectory class implementation. | 452 // GDataRootDirectory class implementation. |
447 | 453 |
448 GDataRootDirectory::GDataRootDirectory() | 454 GDataRootDirectory::GDataRootDirectory() |
449 : ALLOW_THIS_IN_INITIALIZER_LIST(GDataDirectory(NULL, this)), | 455 : ALLOW_THIS_IN_INITIALIZER_LIST(GDataDirectory(NULL, this)), |
456 fake_search_directory_(new GDataDirectory(NULL, NULL)), | |
450 largest_changestamp_(0), serialized_size_(0) { | 457 largest_changestamp_(0), serialized_size_(0) { |
451 title_ = kGDataRootDirectory; | 458 title_ = kGDataRootDirectory; |
452 SetFileNameFromTitle(); | 459 SetFileNameFromTitle(); |
453 } | 460 } |
454 | 461 |
455 GDataRootDirectory::~GDataRootDirectory() { | 462 GDataRootDirectory::~GDataRootDirectory() { |
456 STLDeleteValues(&cache_map_); | 463 STLDeleteValues(&cache_map_); |
457 cache_map_.clear(); | 464 cache_map_.clear(); |
458 | 465 |
459 resource_map_.clear(); | 466 resource_map_.clear(); |
460 } | 467 } |
461 | 468 |
462 GDataRootDirectory* GDataRootDirectory::AsGDataRootDirectory() { | 469 GDataRootDirectory* GDataRootDirectory::AsGDataRootDirectory() { |
463 return this; | 470 return this; |
464 } | 471 } |
465 | 472 |
466 void GDataRootDirectory::AddEntryToResourceMap(GDataEntry* entry) { | 473 void GDataRootDirectory::AddEntryToResourceMap(GDataEntry* entry) { |
467 // GDataFileSystem has already locked. | 474 // GDataFileSystem has already locked. |
468 DVLOG(1) << "AddEntryToResourceMap " << entry->resource_id(); | 475 DVLOG(1) << "AddEntryToResourceMap " << entry->resource_id(); |
469 resource_map_.insert(std::make_pair(entry->resource_id(), entry)); | 476 resource_map_.insert(std::make_pair(entry->resource_id(), entry)); |
470 } | 477 } |
471 | 478 |
472 void GDataRootDirectory::RemoveEntryFromResourceMap(GDataEntry* entry) { | 479 void GDataRootDirectory::RemoveEntryFromResourceMap(GDataEntry* entry) { |
473 // GDataFileSystem has already locked. | 480 // GDataFileSystem has already locked. |
474 resource_map_.erase(entry->resource_id()); | 481 resource_map_.erase(entry->resource_id()); |
475 } | 482 } |
476 | 483 |
484 bool GDataRootDirectory::ModifyFindEntryParamsIfSearchPath( | |
485 const FilePath& file_path, | |
486 std::vector<FilePath::StringType>* components, | |
487 GDataDirectory** current_dir, | |
488 FilePath* directory_path) { | |
489 DCHECK(current_dir); | |
490 DCHECK(components); | |
491 DCHECK(components->size() > 3); | |
492 | |
493 FilePath::StringType resource_id; | |
494 FilePath::StringType file_name; | |
495 util::ParseSearchFileName((*components)[3], &resource_id, &file_name); | |
zel
2012/05/03 22:57:56
DCHECK that |components| starts with [ "gdata", "s
tbarzic
2012/05/03 23:56:17
Done.
| |
496 if (resource_id.empty() || file_name.empty()) | |
497 return false; | |
498 | |
499 GDataEntry* file_entry = GetEntryByResourceId(resource_id); | |
500 if (!file_entry) | |
501 return false; | |
502 | |
503 // If |file_path| is indeed search file path, we should continue search from | |
504 // its parent directory. We have to ammend |components| to be relative to | |
505 // the |current_dir| (including the dir itself). | |
506 // We continue the search with the entrie's parent instead of the entry itself | |
507 // to make sure that the file with id |resource_id| really has the name | |
508 // |file_name|. | |
509 DCHECK(file_entry->parent()); | |
510 *current_dir = file_entry->parent(); | |
511 | |
512 if ((*current_dir)->parent()) { | |
513 *directory_path = (*current_dir)->parent()->GetFilePath(); | |
514 } else { | |
515 *directory_path = FilePath(); | |
516 } | |
517 | |
518 // Remove "gdata/.search" from path. | |
519 components->erase(components->begin(), components->begin() + 2); | |
520 (*components)[0] = (*current_dir)->file_name(); | |
521 (*components)[1] = file_name; | |
522 return true; | |
523 } | |
524 | |
477 void GDataRootDirectory::FindEntryByPath( | 525 void GDataRootDirectory::FindEntryByPath( |
478 const FilePath& file_path, | 526 const FilePath& file_path, |
479 FindEntryDelegate* delegate) { | 527 FindEntryDelegate* delegate) { |
480 // GDataFileSystem has already locked. | 528 // GDataFileSystem has already locked. |
481 DCHECK(delegate); | 529 DCHECK(delegate); |
482 | 530 |
483 std::vector<FilePath::StringType> components; | 531 std::vector<FilePath::StringType> components; |
484 file_path.GetComponents(&components); | 532 file_path.GetComponents(&components); |
485 | 533 |
486 GDataDirectory* current_dir = this; | 534 GDataDirectory* current_dir = this; |
487 FilePath directory_path; | 535 FilePath directory_path; |
536 | |
537 util::GDataSearchPathType path_type = | |
538 util::GetSearchPathStatusForPathComponents(components); | |
539 | |
540 if (path_type == util::GDATA_SEARCH_PATH_ROOT || | |
541 path_type == util::GDATA_SEARCH_PATH_QUERY) { | |
542 fake_search_directory_->set_file_name(file_path.BaseName().value()); | |
tbarzic
2012/05/03 23:56:17
don't really need this
| |
543 delegate->OnDone(base::PLATFORM_FILE_OK, file_path.DirName(), | |
544 fake_search_directory_.get()); | |
545 return; | |
546 | |
547 } | |
548 | |
549 // If the path is under search path, we have to modify paremeters for finding | |
550 // the entry. | |
551 if (path_type != util::GDATA_SEARCH_PATH_INVALID) { | |
552 if (!ModifyFindEntryParamsIfSearchPath(file_path, &components, ¤t_dir, | |
553 &directory_path)) { | |
554 delegate->OnDone(base::PLATFORM_FILE_ERROR_NOT_FOUND, FilePath(), NULL); | |
555 return; | |
556 } | |
557 } | |
558 | |
488 for (size_t i = 0; i < components.size() && current_dir; i++) { | 559 for (size_t i = 0; i < components.size() && current_dir; i++) { |
489 directory_path = directory_path.Append(current_dir->file_name()); | 560 directory_path = directory_path.Append(current_dir->file_name()); |
490 | 561 |
491 // Last element must match, if not last then it must be a directory. | 562 // Last element must match, if not last then it must be a directory. |
492 if (i == components.size() - 1) { | 563 if (i == components.size() - 1) { |
493 if (current_dir->file_name() == components[i]) | 564 if (current_dir->file_name() == components[i]) { |
494 delegate->OnDone(base::PLATFORM_FILE_OK, directory_path, current_dir); | 565 delegate->OnDone(base::PLATFORM_FILE_OK, directory_path, current_dir); |
495 else | 566 } else { |
496 delegate->OnDone(base::PLATFORM_FILE_ERROR_NOT_FOUND, FilePath(), NULL); | 567 delegate->OnDone(base::PLATFORM_FILE_ERROR_NOT_FOUND, FilePath(), NULL); |
497 | 568 } |
498 return; | 569 return; |
499 } | 570 } |
500 | 571 |
501 // Not the last part of the path, search for the next segment. | 572 // Not the last part of the path, search for the next segment. |
502 GDataEntry* entry = current_dir->FindChild(components[i + 1]); | 573 GDataEntry* entry = current_dir->FindChild(components[i + 1]); |
503 if (!entry) { | 574 if (!entry) { |
504 delegate->OnDone(base::PLATFORM_FILE_ERROR_NOT_FOUND, FilePath(), NULL); | 575 delegate->OnDone(base::PLATFORM_FILE_ERROR_NOT_FOUND, FilePath(), NULL); |
505 return; | 576 return; |
506 } | 577 } |
507 | 578 |
(...skipping 314 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
822 bool ok = proto->ParseFromString(serialized_proto); | 893 bool ok = proto->ParseFromString(serialized_proto); |
823 if (ok) { | 894 if (ok) { |
824 FromProto(*proto.get()); | 895 FromProto(*proto.get()); |
825 set_origin(FROM_CACHE); | 896 set_origin(FROM_CACHE); |
826 set_refresh_time(base::Time::Now()); | 897 set_refresh_time(base::Time::Now()); |
827 } | 898 } |
828 return ok; | 899 return ok; |
829 } | 900 } |
830 | 901 |
831 } // namespace gdata | 902 } // namespace gdata |
OLD | NEW |