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 DCHECK(components->at(0) == "gdata" && components->at(1) == ".search"); |
| 493 |
| 494 FilePath::StringType resource_id; |
| 495 FilePath::StringType file_name; |
| 496 util::ParseSearchFileName((*components)[3], &resource_id, &file_name); |
| 497 if (resource_id.empty() || file_name.empty()) |
| 498 return false; |
| 499 |
| 500 GDataEntry* file_entry = GetEntryByResourceId(resource_id); |
| 501 if (!file_entry) |
| 502 return false; |
| 503 |
| 504 // If |file_path| is indeed search file path, we should continue search from |
| 505 // its parent directory. We have to ammend |components| to be relative to |
| 506 // the |current_dir| (including the dir itself). |
| 507 // We continue the search with the entrie's parent instead of the entry itself |
| 508 // to make sure that the file with id |resource_id| really has the name |
| 509 // |file_name|. |
| 510 DCHECK(file_entry->parent()); |
| 511 *current_dir = file_entry->parent(); |
| 512 |
| 513 if ((*current_dir)->parent()) { |
| 514 *directory_path = (*current_dir)->parent()->GetFilePath(); |
| 515 } else { |
| 516 *directory_path = FilePath(); |
| 517 } |
| 518 |
| 519 // Remove "gdata/.search" from path. |
| 520 components->erase(components->begin(), components->begin() + 2); |
| 521 (*components)[0] = (*current_dir)->file_name(); |
| 522 (*components)[1] = file_name; |
| 523 return true; |
| 524 } |
| 525 |
477 void GDataRootDirectory::FindEntryByPath( | 526 void GDataRootDirectory::FindEntryByPath( |
478 const FilePath& file_path, | 527 const FilePath& file_path, |
479 FindEntryDelegate* delegate) { | 528 FindEntryDelegate* delegate) { |
480 // GDataFileSystem has already locked. | 529 // GDataFileSystem has already locked. |
481 DCHECK(delegate); | 530 DCHECK(delegate); |
482 | 531 |
483 std::vector<FilePath::StringType> components; | 532 std::vector<FilePath::StringType> components; |
484 file_path.GetComponents(&components); | 533 file_path.GetComponents(&components); |
485 | 534 |
486 GDataDirectory* current_dir = this; | 535 GDataDirectory* current_dir = this; |
487 FilePath directory_path; | 536 FilePath directory_path; |
| 537 |
| 538 util::GDataSearchPathType path_type = |
| 539 util::GetSearchPathStatusForPathComponents(components); |
| 540 |
| 541 if (path_type == util::GDATA_SEARCH_PATH_ROOT || |
| 542 path_type == util::GDATA_SEARCH_PATH_QUERY) { |
| 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 |