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> | |
8 | |
9 #include "base/utf_string_conversions.h" | 7 #include "base/utf_string_conversions.h" |
10 #include "base/platform_file.h" | 8 #include "base/platform_file.h" |
11 #include "base/stringprintf.h" | 9 #include "base/stringprintf.h" |
12 #include "base/string_util.h" | 10 #include "base/string_util.h" |
13 #include "chrome/browser/chromeos/gdata/find_entry_delegate.h" | 11 #include "chrome/browser/chromeos/gdata/find_entry_delegate.h" |
14 #include "chrome/browser/chromeos/gdata/gdata.pb.h" | 12 #include "chrome/browser/chromeos/gdata/gdata.pb.h" |
15 #include "chrome/browser/chromeos/gdata/gdata_parser.h" | 13 #include "chrome/browser/chromeos/gdata/gdata_parser.h" |
| 14 #include "chrome/browser/chromeos/gdata/gdata_util.h" |
16 #include "net/base/escape.h" | 15 #include "net/base/escape.h" |
17 | 16 |
18 namespace gdata { | 17 namespace gdata { |
19 namespace { | 18 namespace { |
20 | 19 |
21 const char kSlash[] = "/"; | 20 const char kSlash[] = "/"; |
22 const char kEscapedSlash[] = "\xE2\x88\x95"; | 21 const char kEscapedSlash[] = "\xE2\x88\x95"; |
23 const FilePath::CharType kGDataRootDirectory[] = FILE_PATH_LITERAL("gdata"); | 22 const FilePath::CharType kGDataRootDirectory[] = FILE_PATH_LITERAL("gdata"); |
24 | 23 |
25 std::string CacheSubDirectoryTypeToString( | 24 std::string CacheSubDirectoryTypeToString( |
(...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
288 } | 287 } |
289 entry->set_file_name(full_file_name.value()); | 288 entry->set_file_name(full_file_name.value()); |
290 | 289 |
291 DVLOG(1) << "AddEntry: dir = " << GetFilePath().value() | 290 DVLOG(1) << "AddEntry: dir = " << GetFilePath().value() |
292 << ", file = " + entry->file_name() | 291 << ", file = " + entry->file_name() |
293 << ", parent resource = " << entry->parent_resource_id() | 292 << ", parent resource = " << entry->parent_resource_id() |
294 << ", resource = " + entry->resource_id(); | 293 << ", resource = " + entry->resource_id(); |
295 | 294 |
296 | 295 |
297 // Add entry to resource map. | 296 // Add entry to resource map. |
298 root_->AddEntryToResourceMap(entry); | 297 if (root_) |
| 298 root_->AddEntryToResourceMap(entry); |
| 299 |
299 // Setup child and parent links. | 300 // Setup child and parent links. |
300 AddChild(entry); | 301 AddChild(entry); |
301 entry->SetParent(this); | 302 entry->SetParent(this); |
302 } | 303 } |
303 | 304 |
304 bool GDataDirectory::TakeEntry(GDataEntry* entry) { | 305 bool GDataDirectory::TakeEntry(GDataEntry* entry) { |
305 DCHECK(entry); | 306 DCHECK(entry); |
306 DCHECK(entry->parent()); | 307 DCHECK(entry->parent()); |
307 | 308 |
308 entry->parent()->RemoveChild(entry); | 309 entry->parent()->RemoveChild(entry); |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
367 DCHECK(entry); | 368 DCHECK(entry); |
368 | 369 |
369 const std::string file_name(entry->file_name()); | 370 const std::string file_name(entry->file_name()); |
370 GDataEntry* found_entry = FindChild(file_name); | 371 GDataEntry* found_entry = FindChild(file_name); |
371 if (!found_entry) | 372 if (!found_entry) |
372 return false; | 373 return false; |
373 | 374 |
374 DCHECK_EQ(entry, found_entry); | 375 DCHECK_EQ(entry, found_entry); |
375 | 376 |
376 // Remove entry from resource map first. | 377 // Remove entry from resource map first. |
377 root_->RemoveEntryFromResourceMap(entry); | 378 if (root_) |
| 379 root_->RemoveEntryFromResourceMap(entry); |
378 | 380 |
379 // Then delete it from tree. | 381 // Then delete it from tree. |
380 child_files_.erase(file_name); | 382 child_files_.erase(file_name); |
381 child_directories_.erase(file_name); | 383 child_directories_.erase(file_name); |
382 | 384 |
383 return true; | 385 return true; |
384 } | 386 } |
385 | 387 |
386 void GDataDirectory::RemoveChildren() { | 388 void GDataDirectory::RemoveChildren() { |
387 // Remove child files first. | 389 // Remove child files first. |
388 for (GDataFileCollection::const_iterator iter = child_files_.begin(); | 390 for (GDataFileCollection::const_iterator iter = child_files_.begin(); |
389 iter != child_files_.end(); ++iter) { | 391 iter != child_files_.end(); ++iter) { |
390 root_->RemoveEntryFromResourceMap(iter->second); | 392 if (root_) |
| 393 root_->RemoveEntryFromResourceMap(iter->second); |
391 } | 394 } |
392 STLDeleteValues(&child_files_); | 395 STLDeleteValues(&child_files_); |
393 child_files_.clear(); | 396 child_files_.clear(); |
394 | 397 |
395 for (GDataDirectoryCollection::iterator iter = child_directories_.begin(); | 398 for (GDataDirectoryCollection::iterator iter = child_directories_.begin(); |
396 iter != child_directories_.end(); ++iter) { | 399 iter != child_directories_.end(); ++iter) { |
397 GDataDirectory* dir = iter->second; | 400 GDataDirectory* dir = iter->second; |
398 // Remove directories recursively. | 401 // Remove directories recursively. |
399 dir->RemoveChildren(); | 402 dir->RemoveChildren(); |
400 root_->RemoveEntryFromResourceMap(dir); | 403 if (root_) |
| 404 root_->RemoveEntryFromResourceMap(dir); |
401 } | 405 } |
402 STLDeleteValues(&child_directories_); | 406 STLDeleteValues(&child_directories_); |
403 child_directories_.clear(); | 407 child_directories_.clear(); |
404 } | 408 } |
405 | 409 |
406 // GDataRootDirectory::CacheEntry struct implementation. | 410 // GDataRootDirectory::CacheEntry struct implementation. |
407 | 411 |
408 std::string GDataRootDirectory::CacheEntry::ToString() const { | 412 std::string GDataRootDirectory::CacheEntry::ToString() const { |
409 std::vector<std::string> cache_states; | 413 std::vector<std::string> cache_states; |
410 if (GDataFile::IsCachePresent(cache_state)) | 414 if (GDataFile::IsCachePresent(cache_state)) |
411 cache_states.push_back("present"); | 415 cache_states.push_back("present"); |
412 if (GDataFile::IsCachePinned(cache_state)) | 416 if (GDataFile::IsCachePinned(cache_state)) |
413 cache_states.push_back("pinned"); | 417 cache_states.push_back("pinned"); |
414 if (GDataFile::IsCacheDirty(cache_state)) | 418 if (GDataFile::IsCacheDirty(cache_state)) |
415 cache_states.push_back("dirty"); | 419 cache_states.push_back("dirty"); |
416 | 420 |
417 return base::StringPrintf("md5=%s, subdir=%s, cache_state=%s", | 421 return base::StringPrintf("md5=%s, subdir=%s, cache_state=%s", |
418 md5.c_str(), | 422 md5.c_str(), |
419 CacheSubDirectoryTypeToString(sub_dir_type).c_str(), | 423 CacheSubDirectoryTypeToString(sub_dir_type).c_str(), |
420 JoinString(cache_states, ',').c_str()); | 424 JoinString(cache_states, ',').c_str()); |
421 } | 425 } |
422 | 426 |
423 // GDataRootDirectory class implementation. | 427 // GDataRootDirectory class implementation. |
424 | 428 |
425 GDataRootDirectory::GDataRootDirectory() | 429 GDataRootDirectory::GDataRootDirectory() |
426 : ALLOW_THIS_IN_INITIALIZER_LIST(GDataDirectory(NULL, this)), | 430 : ALLOW_THIS_IN_INITIALIZER_LIST(GDataDirectory(NULL, this)), |
| 431 fake_search_directory_(new GDataDirectory(NULL, NULL)), |
427 largest_changestamp_(0), serialized_size_(0) { | 432 largest_changestamp_(0), serialized_size_(0) { |
428 title_ = kGDataRootDirectory; | 433 title_ = kGDataRootDirectory; |
429 SetFileNameFromTitle(); | 434 SetFileNameFromTitle(); |
430 } | 435 } |
431 | 436 |
432 GDataRootDirectory::~GDataRootDirectory() { | 437 GDataRootDirectory::~GDataRootDirectory() { |
433 STLDeleteValues(&cache_map_); | 438 STLDeleteValues(&cache_map_); |
434 cache_map_.clear(); | 439 cache_map_.clear(); |
435 | 440 |
436 resource_map_.clear(); | 441 resource_map_.clear(); |
437 } | 442 } |
438 | 443 |
439 GDataRootDirectory* GDataRootDirectory::AsGDataRootDirectory() { | 444 GDataRootDirectory* GDataRootDirectory::AsGDataRootDirectory() { |
440 return this; | 445 return this; |
441 } | 446 } |
442 | 447 |
443 void GDataRootDirectory::AddEntryToResourceMap(GDataEntry* entry) { | 448 void GDataRootDirectory::AddEntryToResourceMap(GDataEntry* entry) { |
444 // GDataFileSystem has already locked. | 449 // GDataFileSystem has already locked. |
445 DVLOG(1) << "AddEntryToResourceMap " << entry->resource_id(); | 450 DVLOG(1) << "AddEntryToResourceMap " << entry->resource_id(); |
446 resource_map_.insert(std::make_pair(entry->resource_id(), entry)); | 451 resource_map_.insert(std::make_pair(entry->resource_id(), entry)); |
447 } | 452 } |
448 | 453 |
449 void GDataRootDirectory::RemoveEntryFromResourceMap(GDataEntry* entry) { | 454 void GDataRootDirectory::RemoveEntryFromResourceMap(GDataEntry* entry) { |
450 // GDataFileSystem has already locked. | 455 // GDataFileSystem has already locked. |
451 resource_map_.erase(entry->resource_id()); | 456 resource_map_.erase(entry->resource_id()); |
452 } | 457 } |
453 | 458 |
| 459 bool GDataRootDirectory::ModifyFindEntryParamsForSearchPath( |
| 460 const FilePath& file_path, |
| 461 std::vector<FilePath::StringType>* components, |
| 462 GDataDirectory** current_dir, |
| 463 FilePath* directory_path) { |
| 464 DCHECK(current_dir); |
| 465 DCHECK(components); |
| 466 // |components| should contain at least 4 members. |
| 467 // "gdata", ".search", query_name and query_result_name. Additionally, |
| 468 // if query result is a directory, it may contain subdirectories and files, |
| 469 // in which case the number of components may be bigger than 4. |
| 470 DCHECK_GT(components->size(), 3u); |
| 471 DCHECK(components->at(0) == "gdata" && components->at(1) == ".search"); |
| 472 |
| 473 FilePath::StringType resource_id; |
| 474 FilePath::StringType file_name; |
| 475 if (!util::ParseSearchFileName((*components)[3], &resource_id, &file_name)) |
| 476 return false; |
| 477 |
| 478 GDataEntry* file_entry = GetEntryByResourceId(resource_id); |
| 479 if (!file_entry) |
| 480 return false; |
| 481 |
| 482 // We should continue search from the entry's parent dir (|current_dir|), so |
| 483 // we have to ammend |components| to be relative to the |current_dir| |
| 484 // (including the dir itself). |
| 485 // We continue the search with the entry's parent instead of the entry itself |
| 486 // to make sure that the returned file really has the name |file_name|. Note |
| 487 // that we may end up with finding an entry even if entry with |resource_id| |
| 488 // has a name different from |file_name|. This is intended, and enables us to |
| 489 // test that new file name is unique (in file manager) when renaming the |
| 490 // entry. |
| 491 DCHECK(file_entry->parent()); |
| 492 *current_dir = file_entry->parent(); |
| 493 |
| 494 if ((*current_dir)->parent()) { |
| 495 *directory_path = (*current_dir)->parent()->GetFilePath(); |
| 496 } else { |
| 497 *directory_path = FilePath(); |
| 498 } |
| 499 |
| 500 // Remove "gdata/.search" from path. |
| 501 components->erase(components->begin(), components->begin() + 2); |
| 502 (*components)[0] = (*current_dir)->file_name(); |
| 503 (*components)[1] = file_name; |
| 504 return true; |
| 505 } |
| 506 |
454 void GDataRootDirectory::FindEntryByPath( | 507 void GDataRootDirectory::FindEntryByPath( |
455 const FilePath& file_path, | 508 const FilePath& file_path, |
456 FindEntryDelegate* delegate) { | 509 FindEntryDelegate* delegate) { |
457 // GDataFileSystem has already locked. | 510 // GDataFileSystem has already locked. |
458 DCHECK(delegate); | 511 DCHECK(delegate); |
459 | 512 |
460 std::vector<FilePath::StringType> components; | 513 std::vector<FilePath::StringType> components; |
461 file_path.GetComponents(&components); | 514 file_path.GetComponents(&components); |
462 | 515 |
463 GDataDirectory* current_dir = this; | 516 GDataDirectory* current_dir = this; |
464 FilePath directory_path; | 517 FilePath directory_path; |
| 518 |
| 519 util::GDataSearchPathType path_type = |
| 520 util::GetSearchPathStatusForPathComponents(components); |
| 521 |
| 522 if (path_type == util::GDATA_SEARCH_PATH_ROOT || |
| 523 path_type == util::GDATA_SEARCH_PATH_QUERY) { |
| 524 delegate->OnDone(base::PLATFORM_FILE_OK, file_path.DirName(), |
| 525 fake_search_directory_.get()); |
| 526 return; |
| 527 } |
| 528 |
| 529 // If the path is under search path, we have to modify paremeters for finding |
| 530 // the entry. |
| 531 if (path_type != util::GDATA_SEARCH_PATH_INVALID) { |
| 532 if (!ModifyFindEntryParamsForSearchPath(file_path, |
| 533 &components, ¤t_dir, &directory_path)) { |
| 534 delegate->OnDone(base::PLATFORM_FILE_ERROR_NOT_FOUND, FilePath(), NULL); |
| 535 return; |
| 536 } |
| 537 } |
| 538 |
465 for (size_t i = 0; i < components.size() && current_dir; i++) { | 539 for (size_t i = 0; i < components.size() && current_dir; i++) { |
466 directory_path = directory_path.Append(current_dir->file_name()); | 540 directory_path = directory_path.Append(current_dir->file_name()); |
467 | 541 |
468 // Last element must match, if not last then it must be a directory. | 542 // Last element must match, if not last then it must be a directory. |
469 if (i == components.size() - 1) { | 543 if (i == components.size() - 1) { |
470 if (current_dir->file_name() == components[i]) | 544 if (current_dir->file_name() == components[i]) { |
471 delegate->OnDone(base::PLATFORM_FILE_OK, directory_path, current_dir); | 545 delegate->OnDone(base::PLATFORM_FILE_OK, directory_path, current_dir); |
472 else | 546 } else { |
473 delegate->OnDone(base::PLATFORM_FILE_ERROR_NOT_FOUND, FilePath(), NULL); | 547 delegate->OnDone(base::PLATFORM_FILE_ERROR_NOT_FOUND, FilePath(), NULL); |
474 | 548 } |
475 return; | 549 return; |
476 } | 550 } |
477 | 551 |
478 // Not the last part of the path, search for the next segment. | 552 // Not the last part of the path, search for the next segment. |
479 GDataEntry* entry = current_dir->FindChild(components[i + 1]); | 553 GDataEntry* entry = current_dir->FindChild(components[i + 1]); |
480 if (!entry) { | 554 if (!entry) { |
481 delegate->OnDone(base::PLATFORM_FILE_ERROR_NOT_FOUND, FilePath(), NULL); | 555 delegate->OnDone(base::PLATFORM_FILE_ERROR_NOT_FOUND, FilePath(), NULL); |
482 return; | 556 return; |
483 } | 557 } |
484 | 558 |
(...skipping 314 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
799 bool ok = proto->ParseFromString(serialized_proto); | 873 bool ok = proto->ParseFromString(serialized_proto); |
800 if (ok) { | 874 if (ok) { |
801 FromProto(*proto.get()); | 875 FromProto(*proto.get()); |
802 set_origin(FROM_CACHE); | 876 set_origin(FROM_CACHE); |
803 set_refresh_time(base::Time::Now()); | 877 set_refresh_time(base::Time::Now()); |
804 } | 878 } |
805 return ok; | 879 return ok; |
806 } | 880 } |
807 | 881 |
808 } // namespace gdata | 882 } // namespace gdata |
OLD | NEW |