Chromium Code Reviews| 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/platform_file.h" | 9 #include "base/platform_file.h" |
| 10 #include "base/string_util.h" | 10 #include "base/string_util.h" |
| 11 #include "base/stringprintf.h" | 11 #include "base/stringprintf.h" |
| 12 #include "base/sequenced_task_runner.h" | |
| 12 #include "base/utf_string_conversions.h" | 13 #include "base/utf_string_conversions.h" |
| 13 #include "chrome/browser/chromeos/gdata/gdata.pb.h" | 14 #include "chrome/browser/chromeos/gdata/gdata.pb.h" |
| 14 #include "chrome/browser/chromeos/gdata/gdata_util.h" | 15 #include "chrome/browser/chromeos/gdata/gdata_util.h" |
| 15 #include "chrome/browser/chromeos/gdata/gdata_wapi_parser.h" | 16 #include "chrome/browser/chromeos/gdata/gdata_wapi_parser.h" |
| 17 #include "content/public/browser/browser_thread.h" | |
| 16 #include "net/base/escape.h" | 18 #include "net/base/escape.h" |
| 17 | 19 |
| 20 using content::BrowserThread; | |
| 21 | |
| 18 namespace gdata { | 22 namespace gdata { |
| 19 namespace { | 23 namespace { |
| 20 | 24 |
| 21 const char kSlash[] = "/"; | 25 const char kSlash[] = "/"; |
| 22 const char kEscapedSlash[] = "\xE2\x88\x95"; | 26 const char kEscapedSlash[] = "\xE2\x88\x95"; |
| 23 | 27 |
| 24 // Extracts resource_id out of edit url. | 28 // Extracts resource_id out of edit url. |
| 25 std::string ExtractResourceId(const GURL& url) { | 29 std::string ExtractResourceId(const GURL& url) { |
| 26 return net::UnescapeURLComponent(url.ExtractFileName(), | 30 return net::UnescapeURLComponent(url.ExtractFileName(), |
| 27 net::UnescapeRule::URL_SPECIAL_CHARS); | 31 net::UnescapeRule::URL_SPECIAL_CHARS); |
| (...skipping 402 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 430 if (directory_service_) | 434 if (directory_service_) |
| 431 directory_service_->RemoveEntryFromResourceMap(dir); | 435 directory_service_->RemoveEntryFromResourceMap(dir); |
| 432 } | 436 } |
| 433 STLDeleteValues(&child_directories_); | 437 STLDeleteValues(&child_directories_); |
| 434 child_directories_.clear(); | 438 child_directories_.clear(); |
| 435 } | 439 } |
| 436 | 440 |
| 437 // GDataDirectoryService class implementation. | 441 // GDataDirectoryService class implementation. |
| 438 | 442 |
| 439 GDataDirectoryService::GDataDirectoryService() | 443 GDataDirectoryService::GDataDirectoryService() |
| 440 : serialized_size_(0), | 444 : blocking_task_runner_(NULL), |
| 445 serialized_size_(0), | |
| 441 largest_changestamp_(0), | 446 largest_changestamp_(0), |
| 442 origin_(UNINITIALIZED) { | 447 origin_(UNINITIALIZED) { |
| 443 root_.reset(new GDataDirectory(NULL, this)); | 448 root_.reset(new GDataDirectory(NULL, this)); |
| 444 root_->set_title(kGDataRootDirectory); | 449 root_->set_title(kGDataRootDirectory); |
| 445 root_->SetBaseNameFromTitle(); | 450 root_->SetBaseNameFromTitle(); |
| 446 root_->set_resource_id(kGDataRootDirectoryResourceId); | 451 root_->set_resource_id(kGDataRootDirectoryResourceId); |
| 447 AddEntryToResourceMap(root_.get()); | 452 AddEntryToResourceMap(root_.get()); |
| 448 } | 453 } |
| 449 | 454 |
| 450 GDataDirectoryService::~GDataDirectoryService() { | 455 GDataDirectoryService::~GDataDirectoryService() { |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 529 | 534 |
| 530 void GDataDirectoryService::RefreshFile(scoped_ptr<GDataFile> fresh_file) { | 535 void GDataDirectoryService::RefreshFile(scoped_ptr<GDataFile> fresh_file) { |
| 531 DCHECK(fresh_file.get()); | 536 DCHECK(fresh_file.get()); |
| 532 | 537 |
| 533 // Need to get a reference here because Passed() could get evaluated first. | 538 // Need to get a reference here because Passed() could get evaluated first. |
| 534 const std::string& resource_id = fresh_file->resource_id(); | 539 const std::string& resource_id = fresh_file->resource_id(); |
| 535 GetEntryByResourceIdAsync(resource_id, | 540 GetEntryByResourceIdAsync(resource_id, |
| 536 base::Bind(&RefreshFileInternal, base::Passed(&fresh_file))); | 541 base::Bind(&RefreshFileInternal, base::Passed(&fresh_file))); |
| 537 } | 542 } |
| 538 | 543 |
| 544 void GDataDirectoryService::InitFromDB( | |
| 545 const FilePath& db_path, | |
| 546 base::SequencedTaskRunner* blocking_task_runner) { | |
| 547 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 548 DCHECK(!db_path.empty()); | |
| 549 DCHECK(blocking_task_runner); | |
| 550 | |
| 551 db_path_ = db_path; | |
| 552 blocking_task_runner_ = blocking_task_runner; | |
| 553 | |
| 554 SerializedMap* serialized_resources(new SerializedMap); | |
| 555 blocking_task_runner_->PostTaskAndReply( | |
| 556 FROM_HERE, | |
| 557 base::Bind(&GDataDirectoryService::ReadFromDBOnBlockingThread, | |
| 558 base::Unretained(this), | |
| 559 db_path, | |
| 560 serialized_resources), | |
| 561 base::Bind(&GDataDirectoryService::InitResourceMapOnUIThread, | |
| 562 base::Unretained(this), | |
|
hashimoto
2012/07/24 08:41:51
Is this Unretained safe?
satorux1
2012/07/24 16:30:34
should use WeakPtr here.
| |
| 563 base::Owned(serialized_resources))); | |
|
satorux1
2012/07/24 16:30:34
Seems to me that initialization from the DB is sig
| |
| 564 } | |
| 565 | |
| 566 void GDataDirectoryService::ReadFromDBOnBlockingThread( | |
| 567 const FilePath& db_path, | |
| 568 SerializedMap* serialized_resources) { | |
| 569 DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread()); | |
| 570 InitDBOnBlockingThread(db_path); | |
| 571 | |
| 572 if (serialized_resources) { | |
| 573 scoped_ptr<leveldb::Iterator> iter(level_db_->NewIterator( | |
| 574 leveldb::ReadOptions())); | |
| 575 for (iter->SeekToFirst(); iter->Valid(); iter->Next()) { | |
| 576 serialized_resources->insert(std::make_pair(iter->key().ToString(), | |
| 577 iter->value().ToString())); | |
| 578 } | |
| 579 } | |
| 580 } | |
| 581 | |
| 582 void GDataDirectoryService::InitDBOnBlockingThread(const FilePath& db_path) { | |
| 583 DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread()); | |
| 584 DCHECK(!db_path.empty()); | |
| 585 | |
| 586 db_path_ = db_path; | |
| 587 leveldb::DB* level_db = NULL; | |
| 588 leveldb::Options options; | |
| 589 options.create_if_missing = true; | |
| 590 leveldb::Status db_status = leveldb::DB::Open(options, db_path.value(), | |
| 591 &level_db); | |
| 592 DCHECK(level_db); | |
| 593 DCHECK(db_status.ok()); | |
| 594 level_db_.reset(level_db); | |
| 595 } | |
| 596 | |
| 597 void GDataDirectoryService::InitResourceMapOnUIThread( | |
| 598 SerializedMap* serialized_resources) { | |
| 599 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 600 DCHECK(resource_map_.empty()); | |
| 601 | |
| 602 ResourceMap resource_map; | |
| 603 for (SerializedMap::const_iterator iter = serialized_resources->begin(); | |
| 604 iter != serialized_resources->end(); ++iter) { | |
| 605 scoped_ptr<GDataEntry> entry = GDataEntry::FromProtoString(iter->second); | |
| 606 resource_map.insert(std::make_pair(iter->first, entry.release())); | |
| 607 } | |
| 608 | |
| 609 // Fix up parent-child relations. | |
| 610 for (ResourceMap::iterator iter = resource_map.begin(); | |
| 611 iter != resource_map.end(); ++iter) { | |
| 612 GDataEntry* entry = iter->second; | |
| 613 ResourceMap::iterator parent_it = | |
| 614 resource_map.find(entry->parent_resource_id()); | |
| 615 if (parent_it != resource_map.end()) { | |
| 616 GDataDirectory* parent = parent_it->second->AsGDataDirectory(); | |
| 617 if (parent) { | |
| 618 parent->AddEntry(entry); | |
| 619 } else { | |
| 620 NOTREACHED() << "Parent is not a directory " << parent->resource_id(); | |
| 621 } | |
| 622 } else { | |
| 623 NOTREACHED() << "Missing parent id " << entry->parent_resource_id(); | |
| 624 } | |
| 625 } | |
| 626 } | |
| 627 | |
| 628 void GDataDirectoryService::SaveResourceMapToDB() { | |
| 629 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 630 SerializedMap serialized_resources; | |
| 631 for (ResourceMap::const_iterator iter = resource_map_.begin(); | |
| 632 iter != resource_map_.end(); ++iter) { | |
| 633 GDataEntryProto proto; | |
| 634 iter->second->ToProtoFull(&proto); | |
| 635 std::string serialized_string; | |
| 636 const bool ok = proto.SerializeToString(&serialized_string); | |
| 637 DCHECK(ok); | |
| 638 if (ok) { | |
| 639 serialized_resources.insert( | |
| 640 std::make_pair(iter->first, serialized_string)); | |
| 641 } | |
| 642 } | |
| 643 blocking_task_runner_->PostTask( | |
| 644 FROM_HERE, | |
| 645 base::Bind(&GDataDirectoryService::SaveSerializedToDBOnBlockingThread, | |
| 646 base::Unretained(this), | |
| 647 serialized_resources)); | |
| 648 } | |
| 649 | |
| 650 void GDataDirectoryService::SaveSerializedToDBOnBlockingThread( | |
| 651 const SerializedMap& serialized_resources) { | |
| 652 DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread()); | |
| 653 | |
| 654 // Truncate the DB. | |
| 655 level_db_.reset(); | |
| 656 leveldb::DestroyDB(db_path_.value(), leveldb::Options()); | |
| 657 InitDBOnBlockingThread(db_path_); | |
| 658 | |
| 659 for (SerializedMap::const_iterator iter = serialized_resources.begin(); | |
| 660 iter != serialized_resources.end(); ++iter) { | |
| 661 level_db_->Put(leveldb::WriteOptions(), | |
| 662 leveldb::Slice(iter->first), | |
| 663 leveldb::Slice(iter->second)); | |
| 664 } | |
| 665 } | |
| 666 | |
| 539 // Convert to/from proto. | 667 // Convert to/from proto. |
| 540 | 668 |
| 541 // static | 669 // static |
| 542 void GDataEntry::ConvertProtoToPlatformFileInfo( | 670 void GDataEntry::ConvertProtoToPlatformFileInfo( |
| 543 const PlatformFileInfoProto& proto, | 671 const PlatformFileInfoProto& proto, |
| 544 base::PlatformFileInfo* file_info) { | 672 base::PlatformFileInfo* file_info) { |
| 545 file_info->size = proto.size(); | 673 file_info->size = proto.size(); |
| 546 file_info->is_directory = proto.is_directory(); | 674 file_info->is_directory = proto.is_directory(); |
| 547 file_info->is_symbolic_link = proto.is_symbolic_link(); | 675 file_info->is_symbolic_link = proto.is_symbolic_link(); |
| 548 file_info->last_modified = base::Time::FromInternalValue( | 676 file_info->last_modified = base::Time::FromInternalValue( |
| (...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 764 if (!root_->FromProto(proto.gdata_directory())) | 892 if (!root_->FromProto(proto.gdata_directory())) |
| 765 return false; | 893 return false; |
| 766 | 894 |
| 767 origin_ = FROM_CACHE; | 895 origin_ = FROM_CACHE; |
| 768 largest_changestamp_ = proto.largest_changestamp(); | 896 largest_changestamp_ = proto.largest_changestamp(); |
| 769 | 897 |
| 770 return true; | 898 return true; |
| 771 } | 899 } |
| 772 | 900 |
| 773 } // namespace gdata | 901 } // namespace gdata |
| OLD | NEW |