| Index: chrome/browser/chromeos/gdata/gdata_files.cc
|
| ===================================================================
|
| --- chrome/browser/chromeos/gdata/gdata_files.cc (revision 134375)
|
| +++ chrome/browser/chromeos/gdata/gdata_files.cc (working copy)
|
| @@ -15,6 +15,7 @@
|
| #include "chrome/browser/chromeos/gdata/gdata_parser.h"
|
| #include "net/base/escape.h"
|
|
|
| +namespace gdata {
|
| namespace {
|
|
|
| // Content refresh time.
|
| @@ -26,20 +27,21 @@
|
|
|
| const char kSlash[] = "/";
|
| const char kEscapedSlash[] = "\xE2\x88\x95";
|
| +const FilePath::CharType kGDataRootDirectory[] = FILE_PATH_LITERAL("gdata");
|
|
|
| std::string CacheSubDirectoryTypeToString(
|
| - gdata::GDataRootDirectory::CacheSubDirectoryType subdir) {
|
| + GDataRootDirectory::CacheSubDirectoryType subdir) {
|
| switch (subdir) {
|
| - case gdata::GDataRootDirectory::CACHE_TYPE_META: return "meta";
|
| - case gdata::GDataRootDirectory::CACHE_TYPE_PINNED: return "pinned";
|
| - case gdata::GDataRootDirectory::CACHE_TYPE_OUTGOING: return "outgoing";
|
| - case gdata::GDataRootDirectory::CACHE_TYPE_PERSISTENT: return "persistent";
|
| - case gdata::GDataRootDirectory::CACHE_TYPE_TMP: return "tmp";
|
| - case gdata::GDataRootDirectory::CACHE_TYPE_TMP_DOWNLOADS:
|
| + case GDataRootDirectory::CACHE_TYPE_META: return "meta";
|
| + case GDataRootDirectory::CACHE_TYPE_PINNED: return "pinned";
|
| + case GDataRootDirectory::CACHE_TYPE_OUTGOING: return "outgoing";
|
| + case GDataRootDirectory::CACHE_TYPE_PERSISTENT: return "persistent";
|
| + case GDataRootDirectory::CACHE_TYPE_TMP: return "tmp";
|
| + case GDataRootDirectory::CACHE_TYPE_TMP_DOWNLOADS:
|
| return "tmp_downloads";
|
| - case gdata::GDataRootDirectory::CACHE_TYPE_TMP_DOCUMENTS:
|
| + case GDataRootDirectory::CACHE_TYPE_TMP_DOCUMENTS:
|
| return "tmp_documents";
|
| - case gdata::GDataRootDirectory::NUM_CACHE_TYPES:
|
| + case GDataRootDirectory::NUM_CACHE_TYPES:
|
| NOTREACHED();
|
| }
|
| NOTREACHED();
|
| @@ -54,14 +56,12 @@
|
|
|
| } // namespace
|
|
|
| -namespace gdata {
|
| -
|
| // GDataEntry class.
|
|
|
| GDataEntry::GDataEntry(GDataDirectory* parent, GDataRootDirectory* root)
|
| - : parent_(parent),
|
| - root_(root),
|
| + : root_(root),
|
| deleted_(false) {
|
| + SetParent(parent);
|
| }
|
|
|
| GDataEntry::~GDataEntry() {
|
| @@ -91,28 +91,25 @@
|
|
|
| FilePath GDataEntry::GetFilePath() const {
|
| FilePath path;
|
| - std::vector<FilePath::StringType> parts;
|
| - for (const GDataEntry* entry = this; entry != NULL; entry = entry->parent_)
|
| - parts.push_back(entry->file_name());
|
| -
|
| - // Paste paths parts back together in reverse order from upward tree
|
| - // traversal.
|
| - for (std::vector<FilePath::StringType>::reverse_iterator iter =
|
| - parts.rbegin();
|
| - iter != parts.rend(); ++iter) {
|
| - path = path.Append(*iter);
|
| - }
|
| + if (parent())
|
| + path = parent()->GetFilePath();
|
| + path = path.Append(file_name());
|
| return path;
|
| }
|
|
|
| +void GDataEntry::SetParent(GDataDirectory* parent) {
|
| + parent_ = parent;
|
| + parent_resource_id_ = parent ? parent->resource_id() : "";
|
| +}
|
| +
|
| void GDataEntry::SetFileNameFromTitle() {
|
| file_name_ = EscapeUtf8FileName(title_);
|
| }
|
|
|
| // static.
|
| GDataEntry* GDataEntry::FromDocumentEntry(GDataDirectory* parent,
|
| - DocumentEntry* doc,
|
| - GDataRootDirectory* root) {
|
| + DocumentEntry* doc,
|
| + GDataRootDirectory* root) {
|
| DCHECK(doc);
|
| if (doc->is_folder())
|
| return GDataDirectory::FromDocumentEntry(parent, doc, root);
|
| @@ -142,7 +139,7 @@
|
|
|
| GDataFile::GDataFile(GDataDirectory* parent, GDataRootDirectory* root)
|
| : GDataEntry(parent, root),
|
| - kind_(gdata::DocumentEntry::UNKNOWN),
|
| + kind_(DocumentEntry::UNKNOWN),
|
| is_hosted_document_(false) {
|
| file_info_.is_directory = false;
|
| }
|
| @@ -164,8 +161,8 @@
|
|
|
| // static.
|
| GDataEntry* GDataFile::FromDocumentEntry(GDataDirectory* parent,
|
| - DocumentEntry* doc,
|
| - GDataRootDirectory* root) {
|
| + DocumentEntry* doc,
|
| + GDataRootDirectory* root) {
|
| DCHECK(doc->is_hosted_document() || doc->is_file());
|
| GDataFile* file = new GDataFile(parent, root);
|
|
|
| @@ -241,8 +238,8 @@
|
|
|
| // static
|
| GDataEntry* GDataDirectory::FromDocumentEntry(GDataDirectory* parent,
|
| - DocumentEntry* doc,
|
| - GDataRootDirectory* root) {
|
| + DocumentEntry* doc,
|
| + GDataRootDirectory* root) {
|
| DCHECK(doc->is_folder());
|
| GDataDirectory* dir = new GDataDirectory(parent, root);
|
| dir->title_ = UTF16ToUTF8(doc->title());
|
| @@ -273,15 +270,6 @@
|
| return dir;
|
| }
|
|
|
| -void GDataDirectory::RemoveChildren() {
|
| - // Remove children from resource map first.
|
| - root_->RemoveEntriesFromResourceMap(children_);
|
| -
|
| - // Then delete and remove the children from tree.
|
| - STLDeleteValues(&children_);
|
| - children_.clear();
|
| -}
|
| -
|
| bool GDataDirectory::NeedsRefresh() const {
|
| // Already refreshing by someone else.
|
| if (origin_ == REFRESHING)
|
| @@ -298,13 +286,18 @@
|
| }
|
|
|
| void GDataDirectory::AddEntry(GDataEntry* entry) {
|
| + // The entry name may have been changed due to prior name de-duplication.
|
| + // We need to first restore the file name based on the title before going
|
| + // through name de-duplication again when it is added to another directory.
|
| + entry->SetFileNameFromTitle();
|
| +
|
| // Do file name de-duplication - find files with the same name and
|
| // append a name modifier to the name.
|
| int max_modifier = 1;
|
| FilePath full_file_name(entry->file_name());
|
| - std::string extension = full_file_name.Extension();
|
| - std::string file_name = full_file_name.RemoveExtension().value();
|
| - while (children_.find(full_file_name.value()) != children_.end()) {
|
| + const std::string extension = full_file_name.Extension();
|
| + const std::string file_name = full_file_name.RemoveExtension().value();
|
| + while (FindChild(full_file_name.value())) {
|
| if (!extension.empty()) {
|
| full_file_name = FilePath(base::StringPrintf("%s (%d)%s",
|
| file_name.c_str(),
|
| @@ -316,76 +309,123 @@
|
| ++max_modifier));
|
| }
|
| }
|
| - if (full_file_name.value() != entry->file_name())
|
| - entry->set_file_name(full_file_name.value());
|
| - children_.insert(std::make_pair(entry->file_name(), entry));
|
| - DVLOG(1) << "Adding: "
|
| - << this->GetFilePath().value()
|
| - << "/" + entry->file_name()
|
| - << ", resource " << entry->parent_resource_id()
|
| - << "/" + entry->resource_id();
|
| + entry->set_file_name(full_file_name.value());
|
|
|
| + DVLOG(1) << "AddEntry: dir = " << GetFilePath().value()
|
| + << ", file = " + entry->file_name()
|
| + << ", parent resource = " << entry->parent_resource_id()
|
| + << ", resource = " + entry->resource_id();
|
| +
|
| +
|
| // Add entry to resource map.
|
| root_->AddEntryToResourceMap(entry);
|
| -
|
| - entry->set_parent(this);
|
| + // Setup child and parent links.
|
| + AddChild(entry);
|
| + entry->SetParent(this);
|
| }
|
|
|
| bool GDataDirectory::TakeEntry(GDataEntry* entry) {
|
| DCHECK(entry);
|
| DCHECK(entry->parent());
|
|
|
| - entry->parent()->RemoveEntryFromChildrenList(entry);
|
| -
|
| - // The entry name may have been changed due to prior name de-duplication.
|
| - // We need to first restore the file name based on the title before going
|
| - // through name de-duplication again when it is added to another directory.
|
| - entry->SetFileNameFromTitle();
|
| + entry->parent()->RemoveChild(entry);
|
| AddEntry(entry);
|
|
|
| return true;
|
| }
|
|
|
| bool GDataDirectory::TakeOverEntries(GDataDirectory* dir) {
|
| - for (GDataFileCollection::iterator iter = dir->children_.begin();
|
| - iter != dir->children_.end(); ++iter) {
|
| - GDataEntry* entry = iter->second;
|
| - entry->SetFileNameFromTitle();
|
| - AddEntry(entry);
|
| + for (GDataFileCollection::iterator iter = dir->child_files_.begin();
|
| + iter != dir->child_files_.end(); ++iter) {
|
| + AddEntry(iter->second);
|
| }
|
| - dir->children_.clear();
|
| + dir->child_files_.clear();
|
| +
|
| + for (GDataDirectoryCollection::iterator iter =
|
| + dir->child_directories_.begin();
|
| + iter != dir->child_directories_.end(); ++iter) {
|
| + AddEntry(iter->second);
|
| + }
|
| + dir->child_directories_.clear();
|
| return true;
|
| }
|
|
|
| bool GDataDirectory::RemoveEntry(GDataEntry* entry) {
|
| DCHECK(entry);
|
|
|
| - if (!RemoveEntryFromChildrenList(entry))
|
| + if (!RemoveChild(entry))
|
| return false;
|
|
|
| delete entry;
|
| return true;
|
| }
|
|
|
| -bool GDataDirectory::RemoveEntryFromChildrenList(GDataEntry* entry) {
|
| +GDataEntry* GDataDirectory::FindChild(
|
| + const FilePath::StringType& file_name) const {
|
| + GDataFileCollection::const_iterator it = child_files_.find(file_name);
|
| + if (it != child_files_.end())
|
| + return it->second;
|
| +
|
| + GDataDirectoryCollection::const_iterator itd =
|
| + child_directories_.find(file_name);
|
| + if (itd != child_directories_.end())
|
| + return itd->second;
|
| +
|
| + return NULL;
|
| +}
|
| +
|
| +void GDataDirectory::AddChild(GDataEntry* entry) {
|
| DCHECK(entry);
|
|
|
| - GDataFileCollection::iterator iter = children_.find(entry->file_name());
|
| - if (iter == children_.end())
|
| + GDataFile* file = entry->AsGDataFile();
|
| + if (file)
|
| + child_files_.insert(std::make_pair(entry->file_name(), file));
|
| +
|
| + GDataDirectory* directory = entry->AsGDataDirectory();
|
| + if (directory)
|
| + child_directories_.insert(std::make_pair(entry->file_name(), directory));
|
| +}
|
| +
|
| +bool GDataDirectory::RemoveChild(GDataEntry* entry) {
|
| + DCHECK(entry);
|
| +
|
| + const std::string file_name(entry->file_name());
|
| + GDataEntry* found_entry = FindChild(file_name);
|
| + if (!found_entry)
|
| return false;
|
|
|
| - DCHECK(iter->second);
|
| - DCHECK_EQ(entry, iter->second);
|
| + DCHECK_EQ(entry, found_entry);
|
|
|
| // Remove entry from resource map first.
|
| root_->RemoveEntryFromResourceMap(entry);
|
|
|
| // Then delete it from tree.
|
| - children_.erase(iter);
|
| + child_files_.erase(file_name);
|
| + child_directories_.erase(file_name);
|
|
|
| return true;
|
| }
|
|
|
| +void GDataDirectory::RemoveChildren() {
|
| + // Remove child files first.
|
| + for (GDataFileCollection::const_iterator iter = child_files_.begin();
|
| + iter != child_files_.end(); ++iter) {
|
| + root_->RemoveEntryFromResourceMap(iter->second);
|
| + }
|
| + STLDeleteValues(&child_files_);
|
| + child_files_.clear();
|
| +
|
| + for (GDataDirectoryCollection::iterator iter = child_directories_.begin();
|
| + iter != child_directories_.end(); ++iter) {
|
| + GDataDirectory* dir = iter->second;
|
| + // Remove directories recursively.
|
| + dir->RemoveChildren();
|
| + root_->RemoveEntryFromResourceMap(dir);
|
| + }
|
| + STLDeleteValues(&child_directories_);
|
| + child_directories_.clear();
|
| +}
|
| +
|
| // GDataRootDirectory::CacheEntry struct implementation.
|
|
|
| std::string GDataRootDirectory::CacheEntry::ToString() const {
|
| @@ -408,6 +448,8 @@
|
| GDataRootDirectory::GDataRootDirectory()
|
| : ALLOW_THIS_IN_INITIALIZER_LIST(GDataDirectory(NULL, this)),
|
| largest_changestamp_(0), serialized_size_(0) {
|
| + title_ = kGDataRootDirectory;
|
| + SetFileNameFromTitle();
|
| }
|
|
|
| GDataRootDirectory::~GDataRootDirectory() {
|
| @@ -423,6 +465,7 @@
|
|
|
| void GDataRootDirectory::AddEntryToResourceMap(GDataEntry* entry) {
|
| // GDataFileSystem has already locked.
|
| + DVLOG(1) << "AddEntryToResourceMap " << entry->resource_id();
|
| resource_map_.insert(std::make_pair(entry->resource_id(), entry));
|
| }
|
|
|
| @@ -431,22 +474,6 @@
|
| resource_map_.erase(entry->resource_id());
|
| }
|
|
|
| -void GDataRootDirectory::RemoveEntriesFromResourceMap(
|
| - const GDataFileCollection& children) {
|
| - // GDataFileSystem has already locked.
|
| - for (GDataFileCollection::const_iterator iter = children.begin();
|
| - iter != children.end(); ++iter) {
|
| - // Recursively call RemoveEntrysFromResourceMap for each directory.
|
| - if (iter->second->AsGDataDirectory()) {
|
| - RemoveEntriesFromResourceMap(
|
| - iter->second->AsGDataDirectory()->children());
|
| - continue;
|
| - }
|
| -
|
| - resource_map_.erase(iter->second->resource_id());
|
| - }
|
| -}
|
| -
|
| void GDataRootDirectory::FindEntryByPath(
|
| const FilePath& file_path,
|
| FindEntryDelegate* delegate) {
|
| @@ -472,22 +499,21 @@
|
| }
|
|
|
| // Not the last part of the path, search for the next segment.
|
| - GDataFileCollection::const_iterator file_iter =
|
| - current_dir->children().find(components[i + 1]);
|
| - if (file_iter == current_dir->children().end()) {
|
| + GDataEntry* entry = current_dir->FindChild(components[i + 1]);
|
| + if (!entry) {
|
| delegate->OnDone(base::PLATFORM_FILE_ERROR_NOT_FOUND, FilePath(), NULL);
|
| return;
|
| }
|
|
|
| // Found file, must be the last segment.
|
| - if (file_iter->second->file_info().is_directory) {
|
| + if (entry->file_info().is_directory) {
|
| // Found directory, continue traversal.
|
| - current_dir = file_iter->second->AsGDataDirectory();
|
| + current_dir = entry->AsGDataDirectory();
|
| } else {
|
| if ((i + 1) == (components.size() - 1)) {
|
| delegate->OnDone(base::PLATFORM_FILE_OK,
|
| directory_path,
|
| - file_iter->second);
|
| + entry);
|
| } else {
|
| delegate->OnDone(base::PLATFORM_FILE_ERROR_NOT_FOUND, FilePath(), NULL);
|
| }
|
| @@ -617,11 +643,12 @@
|
| file_info_.creation_time = base::Time::FromInternalValue(
|
| proto.file_info().creation_time());
|
|
|
| - file_name_ = proto.file_name();
|
| title_ = proto.title();
|
| resource_id_ = proto.resource_id();
|
| + parent_resource_id_ = proto.parent_resource_id();
|
| edit_url_ = GURL(proto.edit_url());
|
| content_url_ = GURL(proto.content_url());
|
| + SetFileNameFromTitle();
|
| }
|
|
|
| void GDataEntry::ToProto(GDataEntryProto* proto) const {
|
| @@ -636,9 +663,9 @@
|
| proto_file_info->set_creation_time(
|
| file_info_.creation_time.ToInternalValue());
|
|
|
| - proto->set_file_name(file_name_);
|
| proto->set_title(title_);
|
| proto->set_resource_id(resource_id_);
|
| + proto->set_parent_resource_id(parent_resource_id_);
|
| proto->set_edit_url(edit_url_.spec());
|
| proto->set_content_url(content_url_.spec());
|
| }
|
| @@ -699,15 +726,17 @@
|
| proto->set_next_feed_url(next_feed_url_.spec());
|
| proto->set_upload_url(upload_url_.spec());
|
| proto->set_origin(origin_);
|
| - for (GDataFileCollection::const_iterator iter = children_.begin();
|
| - iter != children_.end(); ++iter) {
|
| - GDataFile* file = iter->second->AsGDataFile();
|
| - GDataDirectory* dir = iter->second->AsGDataDirectory();
|
| - if (file)
|
| - file->ToProto(proto->add_child_files());
|
| - if (dir)
|
| - dir->ToProto(proto->add_child_directories());
|
| + for (GDataFileCollection::const_iterator iter = child_files_.begin();
|
| + iter != child_files_.end(); ++iter) {
|
| + GDataFile* file = iter->second;
|
| + file->ToProto(proto->add_child_files());
|
| }
|
| + for (GDataDirectoryCollection::const_iterator iter =
|
| + child_directories_.begin();
|
| + iter != child_directories_.end(); ++iter) {
|
| + GDataDirectory* dir = iter->second;
|
| + dir->ToProto(proto->add_child_directories());
|
| + }
|
| }
|
|
|
| void GDataRootDirectory::FromProto(const GDataRootDirectoryProto& proto) {
|
|
|