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/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 "net/base/escape.h" | 16 #include "net/base/escape.h" |
| 17 | 17 |
| 18 namespace gdata { | |
| 18 namespace { | 19 namespace { |
| 19 | 20 |
| 20 // Content refresh time. | 21 // Content refresh time. |
| 21 #ifndef NDEBUG | 22 #ifndef NDEBUG |
| 22 const int kRefreshTimeInSec = 10; | 23 const int kRefreshTimeInSec = 10; |
| 23 #else | 24 #else |
| 24 const int kRefreshTimeInSec = 5*60; | 25 const int kRefreshTimeInSec = 5*60; |
| 25 #endif | 26 #endif |
| 26 | 27 |
| 27 const char kSlash[] = "/"; | 28 const char kSlash[] = "/"; |
| 28 const char kEscapedSlash[] = "\xE2\x88\x95"; | 29 const char kEscapedSlash[] = "\xE2\x88\x95"; |
| 30 const FilePath::CharType kGDataRootDirectory[] = FILE_PATH_LITERAL("gdata"); | |
| 29 | 31 |
| 30 std::string CacheSubDirectoryTypeToString( | 32 std::string CacheSubDirectoryTypeToString( |
| 31 gdata::GDataRootDirectory::CacheSubDirectoryType subdir) { | 33 GDataRootDirectory::CacheSubDirectoryType subdir) { |
| 32 switch (subdir) { | 34 switch (subdir) { |
| 33 case gdata::GDataRootDirectory::CACHE_TYPE_META: return "meta"; | 35 case GDataRootDirectory::CACHE_TYPE_META: return "meta"; |
| 34 case gdata::GDataRootDirectory::CACHE_TYPE_PINNED: return "pinned"; | 36 case GDataRootDirectory::CACHE_TYPE_PINNED: return "pinned"; |
| 35 case gdata::GDataRootDirectory::CACHE_TYPE_OUTGOING: return "outgoing"; | 37 case GDataRootDirectory::CACHE_TYPE_OUTGOING: return "outgoing"; |
| 36 case gdata::GDataRootDirectory::CACHE_TYPE_PERSISTENT: return "persistent"; | 38 case GDataRootDirectory::CACHE_TYPE_PERSISTENT: return "persistent"; |
| 37 case gdata::GDataRootDirectory::CACHE_TYPE_TMP: return "tmp"; | 39 case GDataRootDirectory::CACHE_TYPE_TMP: return "tmp"; |
| 38 case gdata::GDataRootDirectory::CACHE_TYPE_TMP_DOWNLOADS: | 40 case GDataRootDirectory::CACHE_TYPE_TMP_DOWNLOADS: |
| 39 return "tmp_downloads"; | 41 return "tmp_downloads"; |
| 40 case gdata::GDataRootDirectory::CACHE_TYPE_TMP_DOCUMENTS: | 42 case GDataRootDirectory::CACHE_TYPE_TMP_DOCUMENTS: |
| 41 return "tmp_documents"; | 43 return "tmp_documents"; |
| 42 case gdata::GDataRootDirectory::NUM_CACHE_TYPES: | 44 case GDataRootDirectory::NUM_CACHE_TYPES: |
| 43 NOTREACHED(); | 45 NOTREACHED(); |
| 44 } | 46 } |
| 45 NOTREACHED(); | 47 NOTREACHED(); |
| 46 return "unknown subdir"; | 48 return "unknown subdir"; |
| 47 } | 49 } |
| 48 | 50 |
| 49 // Extracts resource_id out of edit url. | 51 // Extracts resource_id out of edit url. |
| 50 std::string ExtractResourceId(const GURL& url) { | 52 std::string ExtractResourceId(const GURL& url) { |
| 51 return net::UnescapeURLComponent(url.ExtractFileName(), | 53 return net::UnescapeURLComponent(url.ExtractFileName(), |
| 52 net::UnescapeRule::URL_SPECIAL_CHARS); | 54 net::UnescapeRule::URL_SPECIAL_CHARS); |
| 53 } | 55 } |
| 54 | 56 |
| 55 } // namespace | 57 } // namespace |
| 56 | 58 |
| 57 namespace gdata { | |
| 58 | |
| 59 // GDataEntry class. | 59 // GDataEntry class. |
| 60 | 60 |
| 61 GDataEntry::GDataEntry(GDataDirectory* parent, GDataRootDirectory* root) | 61 GDataEntry::GDataEntry(GDataDirectory* parent, GDataRootDirectory* root) |
| 62 : parent_(parent), | 62 : root_(root), |
| 63 root_(root), | |
| 64 deleted_(false) { | 63 deleted_(false) { |
| 64 SetParent(parent); | |
| 65 } | 65 } |
| 66 | 66 |
| 67 GDataEntry::~GDataEntry() { | 67 GDataEntry::~GDataEntry() { |
| 68 } | 68 } |
| 69 | 69 |
| 70 GDataFile* GDataEntry::AsGDataFile() { | 70 GDataFile* GDataEntry::AsGDataFile() { |
| 71 return NULL; | 71 return NULL; |
| 72 } | 72 } |
| 73 | 73 |
| 74 GDataDirectory* GDataEntry::AsGDataDirectory() { | 74 GDataDirectory* GDataEntry::AsGDataDirectory() { |
| 75 return NULL; | 75 return NULL; |
| 76 } | 76 } |
| 77 | 77 |
| 78 GDataRootDirectory* GDataEntry::AsGDataRootDirectory() { | 78 GDataRootDirectory* GDataEntry::AsGDataRootDirectory() { |
| 79 return NULL; | 79 return NULL; |
| 80 } | 80 } |
| 81 | 81 |
| 82 const GDataFile* GDataEntry::AsGDataFileConst() const { | 82 const GDataFile* GDataEntry::AsGDataFileConst() const { |
| 83 // cast away const and call the non-const version. This is safe. | 83 // cast away const and call the non-const version. This is safe. |
| 84 return const_cast<GDataEntry*>(this)->AsGDataFile(); | 84 return const_cast<GDataEntry*>(this)->AsGDataFile(); |
| 85 } | 85 } |
| 86 | 86 |
| 87 const GDataDirectory* GDataEntry::AsGDataDirectoryConst() const { | 87 const GDataDirectory* GDataEntry::AsGDataDirectoryConst() const { |
| 88 // cast away const and call the non-const version. This is safe. | 88 // cast away const and call the non-const version. This is safe. |
| 89 return const_cast<GDataEntry*>(this)->AsGDataDirectory(); | 89 return const_cast<GDataEntry*>(this)->AsGDataDirectory(); |
| 90 } | 90 } |
| 91 | 91 |
| 92 FilePath GDataEntry::GetFilePath() const { | 92 FilePath GDataEntry::GetFilePath() const { |
| 93 FilePath path; | 93 FilePath path; |
| 94 std::vector<FilePath::StringType> parts; | 94 if (parent()) |
| 95 for (const GDataEntry* entry = this; entry != NULL; entry = entry->parent_) | 95 path = parent()->GetFilePath(); |
| 96 parts.push_back(entry->file_name()); | 96 path = path.Append(file_name()); |
| 97 return path; | |
| 98 } | |
| 97 | 99 |
| 98 // Paste paths parts back together in reverse order from upward tree | 100 void GDataEntry::SetParent(GDataDirectory* parent) { |
| 99 // traversal. | 101 parent_ = parent; |
| 100 for (std::vector<FilePath::StringType>::reverse_iterator iter = | 102 parent_resource_id_ = parent ? parent->resource_id() : ""; |
|
satorux1
2012/04/27 21:35:41
IIRC, parent_resource_id_ was used for delta updat
achuithb
2012/04/27 22:15:03
I think it is. It should always point to the corre
| |
| 101 parts.rbegin(); | |
| 102 iter != parts.rend(); ++iter) { | |
| 103 path = path.Append(*iter); | |
| 104 } | |
| 105 return path; | |
| 106 } | 103 } |
| 107 | 104 |
| 108 void GDataEntry::SetFileNameFromTitle() { | 105 void GDataEntry::SetFileNameFromTitle() { |
| 109 file_name_ = EscapeUtf8FileName(title_); | 106 file_name_ = EscapeUtf8FileName(title_); |
| 110 } | 107 } |
| 111 | 108 |
| 112 // static. | 109 // static. |
| 113 GDataEntry* GDataEntry::FromDocumentEntry(GDataDirectory* parent, | 110 GDataEntry* GDataEntry::FromDocumentEntry(GDataDirectory* parent, |
| 114 DocumentEntry* doc, | 111 DocumentEntry* doc, |
| 115 GDataRootDirectory* root) { | 112 GDataRootDirectory* root) { |
| 116 DCHECK(doc); | 113 DCHECK(doc); |
| 117 if (doc->is_folder()) | 114 if (doc->is_folder()) |
| 118 return GDataDirectory::FromDocumentEntry(parent, doc, root); | 115 return GDataDirectory::FromDocumentEntry(parent, doc, root); |
| 119 else if (doc->is_hosted_document() || doc->is_file()) | 116 else if (doc->is_hosted_document() || doc->is_file()) |
| 120 return GDataFile::FromDocumentEntry(parent, doc, root); | 117 return GDataFile::FromDocumentEntry(parent, doc, root); |
| 121 | 118 |
| 122 return NULL; | 119 return NULL; |
| 123 } | 120 } |
| 124 | 121 |
| 125 // static. | 122 // static. |
| 126 std::string GDataEntry::EscapeUtf8FileName(const std::string& input) { | 123 std::string GDataEntry::EscapeUtf8FileName(const std::string& input) { |
| 127 std::string output; | 124 std::string output; |
| 128 if (ReplaceChars(input, kSlash, std::string(kEscapedSlash), &output)) | 125 if (ReplaceChars(input, kSlash, std::string(kEscapedSlash), &output)) |
| 129 return output; | 126 return output; |
| 130 | 127 |
| 131 return input; | 128 return input; |
| 132 } | 129 } |
| 133 | 130 |
| 134 // static. | 131 // static. |
| 135 std::string GDataEntry::UnescapeUtf8FileName(const std::string& input) { | 132 std::string GDataEntry::UnescapeUtf8FileName(const std::string& input) { |
| 136 std::string output = input; | 133 std::string output = input; |
| 137 ReplaceSubstringsAfterOffset(&output, 0, std::string(kEscapedSlash), kSlash); | 134 ReplaceSubstringsAfterOffset(&output, 0, std::string(kEscapedSlash), kSlash); |
| 138 return output; | 135 return output; |
| 139 } | 136 } |
| 140 | 137 |
| 141 // GDataFile class implementation. | 138 // GDataFile class implementation. |
| 142 | 139 |
| 143 GDataFile::GDataFile(GDataDirectory* parent, GDataRootDirectory* root) | 140 GDataFile::GDataFile(GDataDirectory* parent, GDataRootDirectory* root) |
| 144 : GDataEntry(parent, root), | 141 : GDataEntry(parent, root), |
| 145 kind_(gdata::DocumentEntry::UNKNOWN), | 142 kind_(DocumentEntry::UNKNOWN), |
| 146 is_hosted_document_(false) { | 143 is_hosted_document_(false) { |
| 147 file_info_.is_directory = false; | 144 file_info_.is_directory = false; |
| 148 } | 145 } |
| 149 | 146 |
| 150 GDataFile::~GDataFile() { | 147 GDataFile::~GDataFile() { |
| 151 } | 148 } |
| 152 | 149 |
| 153 GDataFile* GDataFile::AsGDataFile() { | 150 GDataFile* GDataFile::AsGDataFile() { |
| 154 return this; | 151 return this; |
| 155 } | 152 } |
| 156 | 153 |
| 157 void GDataFile::SetFileNameFromTitle() { | 154 void GDataFile::SetFileNameFromTitle() { |
| 158 if (is_hosted_document_) { | 155 if (is_hosted_document_) { |
| 159 file_name_ = EscapeUtf8FileName(title_ + document_extension_); | 156 file_name_ = EscapeUtf8FileName(title_ + document_extension_); |
| 160 } else { | 157 } else { |
| 161 GDataEntry::SetFileNameFromTitle(); | 158 GDataEntry::SetFileNameFromTitle(); |
| 162 } | 159 } |
| 163 } | 160 } |
| 164 | 161 |
| 165 // static. | 162 // static. |
| 166 GDataEntry* GDataFile::FromDocumentEntry(GDataDirectory* parent, | 163 GDataEntry* GDataFile::FromDocumentEntry(GDataDirectory* parent, |
| 167 DocumentEntry* doc, | 164 DocumentEntry* doc, |
| 168 GDataRootDirectory* root) { | 165 GDataRootDirectory* root) { |
| 169 DCHECK(doc->is_hosted_document() || doc->is_file()); | 166 DCHECK(doc->is_hosted_document() || doc->is_file()); |
| 170 GDataFile* file = new GDataFile(parent, root); | 167 GDataFile* file = new GDataFile(parent, root); |
| 171 | 168 |
| 172 // For regular files, the 'filename' and 'title' attribute in the metadata | 169 // For regular files, the 'filename' and 'title' attribute in the metadata |
| 173 // may be different (e.g. due to rename). To be consistent with the web | 170 // may be different (e.g. due to rename). To be consistent with the web |
| 174 // interface and other client to use the 'title' attribute, instead of | 171 // interface and other client to use the 'title' attribute, instead of |
| 175 // 'filename', as the file name in the local snapshot. | 172 // 'filename', as the file name in the local snapshot. |
| 176 file->title_ = UTF16ToUTF8(doc->title()); | 173 file->title_ = UTF16ToUTF8(doc->title()); |
| 177 | 174 |
| 178 // Check if this entry is a true file, or... | 175 // Check if this entry is a true file, or... |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 234 GDataDirectory::~GDataDirectory() { | 231 GDataDirectory::~GDataDirectory() { |
| 235 RemoveChildren(); | 232 RemoveChildren(); |
| 236 } | 233 } |
| 237 | 234 |
| 238 GDataDirectory* GDataDirectory::AsGDataDirectory() { | 235 GDataDirectory* GDataDirectory::AsGDataDirectory() { |
| 239 return this; | 236 return this; |
| 240 } | 237 } |
| 241 | 238 |
| 242 // static | 239 // static |
| 243 GDataEntry* GDataDirectory::FromDocumentEntry(GDataDirectory* parent, | 240 GDataEntry* GDataDirectory::FromDocumentEntry(GDataDirectory* parent, |
| 244 DocumentEntry* doc, | 241 DocumentEntry* doc, |
| 245 GDataRootDirectory* root) { | 242 GDataRootDirectory* root) { |
| 246 DCHECK(doc->is_folder()); | 243 DCHECK(doc->is_folder()); |
| 247 GDataDirectory* dir = new GDataDirectory(parent, root); | 244 GDataDirectory* dir = new GDataDirectory(parent, root); |
| 248 dir->title_ = UTF16ToUTF8(doc->title()); | 245 dir->title_ = UTF16ToUTF8(doc->title()); |
| 249 // SetFileNameFromTitle() must be called after |title_| is set. | 246 // SetFileNameFromTitle() must be called after |title_| is set. |
| 250 dir->SetFileNameFromTitle(); | 247 dir->SetFileNameFromTitle(); |
| 251 dir->file_info_.last_modified = doc->updated_time(); | 248 dir->file_info_.last_modified = doc->updated_time(); |
| 252 dir->file_info_.last_accessed = doc->updated_time(); | 249 dir->file_info_.last_accessed = doc->updated_time(); |
| 253 dir->file_info_.creation_time = doc->published_time(); | 250 dir->file_info_.creation_time = doc->published_time(); |
| 254 // Extract feed link. | 251 // Extract feed link. |
| 255 dir->start_feed_url_ = doc->content_url(); | 252 dir->start_feed_url_ = doc->content_url(); |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 266 if (parent_link) | 263 if (parent_link) |
| 267 dir->parent_resource_id_ = ExtractResourceId(parent_link->href()); | 264 dir->parent_resource_id_ = ExtractResourceId(parent_link->href()); |
| 268 | 265 |
| 269 const Link* upload_link = doc->GetLinkByType(Link::RESUMABLE_CREATE_MEDIA); | 266 const Link* upload_link = doc->GetLinkByType(Link::RESUMABLE_CREATE_MEDIA); |
| 270 if (upload_link) | 267 if (upload_link) |
| 271 dir->upload_url_ = upload_link->href(); | 268 dir->upload_url_ = upload_link->href(); |
| 272 | 269 |
| 273 return dir; | 270 return dir; |
| 274 } | 271 } |
| 275 | 272 |
| 276 void GDataDirectory::RemoveChildren() { | |
| 277 // Remove children from resource map first. | |
| 278 root_->RemoveEntriesFromResourceMap(children_); | |
| 279 | |
| 280 // Then delete and remove the children from tree. | |
| 281 STLDeleteValues(&children_); | |
| 282 children_.clear(); | |
| 283 } | |
| 284 | |
| 285 bool GDataDirectory::NeedsRefresh() const { | 273 bool GDataDirectory::NeedsRefresh() const { |
| 286 // Already refreshing by someone else. | 274 // Already refreshing by someone else. |
| 287 if (origin_ == REFRESHING) | 275 if (origin_ == REFRESHING) |
| 288 return false; | 276 return false; |
| 289 | 277 |
| 290 // Refresh is needed for content read from disk cache or stale content. | 278 // Refresh is needed for content read from disk cache or stale content. |
| 291 if (origin_ == FROM_CACHE) | 279 if (origin_ == FROM_CACHE) |
| 292 return true; | 280 return true; |
| 293 | 281 |
| 294 if ((base::Time::Now() - refresh_time_).InSeconds() < kRefreshTimeInSec) | 282 if ((base::Time::Now() - refresh_time_).InSeconds() < kRefreshTimeInSec) |
| 295 return false; | 283 return false; |
| 296 | 284 |
| 297 return true; | 285 return true; |
| 298 } | 286 } |
| 299 | 287 |
| 300 void GDataDirectory::AddEntry(GDataEntry* entry) { | 288 void GDataDirectory::AddEntry(GDataEntry* entry) { |
| 289 // The entry name may have been changed due to prior name de-duplication. | |
| 290 // We need to first restore the file name based on the title before going | |
| 291 // through name de-duplication again when it is added to another directory. | |
| 292 entry->SetFileNameFromTitle(); | |
| 293 | |
| 301 // Do file name de-duplication - find files with the same name and | 294 // Do file name de-duplication - find files with the same name and |
| 302 // append a name modifier to the name. | 295 // append a name modifier to the name. |
| 303 int max_modifier = 1; | 296 int max_modifier = 1; |
| 304 FilePath full_file_name(entry->file_name()); | 297 FilePath full_file_name(entry->file_name()); |
| 305 std::string extension = full_file_name.Extension(); | 298 const std::string extension = full_file_name.Extension(); |
| 306 std::string file_name = full_file_name.RemoveExtension().value(); | 299 const std::string file_name = full_file_name.RemoveExtension().value(); |
| 307 while (children_.find(full_file_name.value()) != children_.end()) { | 300 while (FindChild(full_file_name.value())) { |
| 308 if (!extension.empty()) { | 301 if (!extension.empty()) { |
| 309 full_file_name = FilePath(base::StringPrintf("%s (%d)%s", | 302 full_file_name = FilePath(base::StringPrintf("%s (%d)%s", |
| 310 file_name.c_str(), | 303 file_name.c_str(), |
| 311 ++max_modifier, | 304 ++max_modifier, |
| 312 extension.c_str())); | 305 extension.c_str())); |
| 313 } else { | 306 } else { |
| 314 full_file_name = FilePath(base::StringPrintf("%s (%d)", | 307 full_file_name = FilePath(base::StringPrintf("%s (%d)", |
| 315 file_name.c_str(), | 308 file_name.c_str(), |
| 316 ++max_modifier)); | 309 ++max_modifier)); |
| 317 } | 310 } |
| 318 } | 311 } |
| 319 if (full_file_name.value() != entry->file_name()) | 312 entry->set_file_name(full_file_name.value()); |
| 320 entry->set_file_name(full_file_name.value()); | 313 |
| 321 children_.insert(std::make_pair(entry->file_name(), entry)); | 314 DVLOG(1) << "AddEntry: dir = " << GetFilePath().value() |
| 322 DVLOG(1) << "Adding: " | 315 << ", file = " + entry->file_name() |
| 323 << this->GetFilePath().value() | 316 << ", parent resource = " << entry->parent_resource_id() |
| 324 << "/" + entry->file_name() | 317 << ", resource = " + entry->resource_id(); |
| 325 << ", resource " << entry->parent_resource_id() | 318 |
| 326 << "/" + entry->resource_id(); | |
| 327 | 319 |
| 328 // Add entry to resource map. | 320 // Add entry to resource map. |
| 329 root_->AddEntryToResourceMap(entry); | 321 root_->AddEntryToResourceMap(entry); |
| 330 | 322 // Setup child and parent links. |
| 331 entry->set_parent(this); | 323 AddChild(entry); |
| 324 entry->SetParent(this); | |
| 332 } | 325 } |
| 333 | 326 |
| 334 bool GDataDirectory::TakeEntry(GDataEntry* entry) { | 327 bool GDataDirectory::TakeEntry(GDataEntry* entry) { |
| 335 DCHECK(entry); | 328 DCHECK(entry); |
| 336 DCHECK(entry->parent()); | 329 DCHECK(entry->parent()); |
| 337 | 330 |
| 338 entry->parent()->RemoveEntryFromChildrenList(entry); | 331 entry->parent()->RemoveChild(entry); |
| 339 | |
| 340 // The entry name may have been changed due to prior name de-duplication. | |
| 341 // We need to first restore the file name based on the title before going | |
| 342 // through name de-duplication again when it is added to another directory. | |
| 343 entry->SetFileNameFromTitle(); | |
| 344 AddEntry(entry); | 332 AddEntry(entry); |
| 345 | 333 |
| 346 return true; | 334 return true; |
| 347 } | 335 } |
| 348 | 336 |
| 349 bool GDataDirectory::TakeOverEntries(GDataDirectory* dir) { | 337 bool GDataDirectory::TakeOverEntries(GDataDirectory* dir) { |
| 350 for (GDataFileCollection::iterator iter = dir->children_.begin(); | 338 for (GDataFileCollection::iterator iter = dir->child_files_.begin(); |
| 351 iter != dir->children_.end(); ++iter) { | 339 iter != dir->child_files_.end(); ++iter) { |
| 352 GDataEntry* entry = iter->second; | 340 AddEntry(iter->second); |
| 353 entry->SetFileNameFromTitle(); | |
| 354 AddEntry(entry); | |
| 355 } | 341 } |
| 356 dir->children_.clear(); | 342 dir->child_files_.clear(); |
| 343 | |
| 344 for (GDataDirectoryCollection::iterator iter = | |
| 345 dir->child_directories_.begin(); | |
| 346 iter != dir->child_directories_.end(); ++iter) { | |
| 347 AddEntry(iter->second); | |
| 348 } | |
| 349 dir->child_directories_.clear(); | |
| 357 return true; | 350 return true; |
| 358 } | 351 } |
| 359 | 352 |
| 360 bool GDataDirectory::RemoveEntry(GDataEntry* entry) { | 353 bool GDataDirectory::RemoveEntry(GDataEntry* entry) { |
| 361 DCHECK(entry); | 354 DCHECK(entry); |
| 362 | 355 |
| 363 if (!RemoveEntryFromChildrenList(entry)) | 356 if (!RemoveChild(entry)) |
| 364 return false; | 357 return false; |
| 365 | 358 |
| 366 delete entry; | 359 delete entry; |
| 367 return true; | 360 return true; |
| 368 } | 361 } |
| 369 | 362 |
| 370 bool GDataDirectory::RemoveEntryFromChildrenList(GDataEntry* entry) { | 363 GDataEntry* GDataDirectory::FindChild( |
| 364 const FilePath::StringType& file_name) const { | |
| 365 GDataFileCollection::const_iterator it = child_files_.find(file_name); | |
| 366 if (it != child_files_.end()) | |
| 367 return it->second; | |
| 368 | |
| 369 GDataDirectoryCollection::const_iterator itd = | |
| 370 child_directories_.find(file_name); | |
| 371 if (itd != child_directories_.end()) | |
| 372 return itd->second; | |
| 373 | |
| 374 return NULL; | |
| 375 } | |
| 376 | |
| 377 void GDataDirectory::AddChild(GDataEntry* entry) { | |
| 371 DCHECK(entry); | 378 DCHECK(entry); |
| 372 | 379 |
| 373 GDataFileCollection::iterator iter = children_.find(entry->file_name()); | 380 GDataFile* file = entry->AsGDataFile(); |
| 374 if (iter == children_.end()) | 381 if (file) |
| 382 child_files_.insert(std::make_pair(entry->file_name(), file)); | |
| 383 | |
| 384 GDataDirectory* directory = entry->AsGDataDirectory(); | |
| 385 if (directory) | |
| 386 child_directories_.insert(std::make_pair(entry->file_name(), directory)); | |
| 387 } | |
| 388 | |
| 389 bool GDataDirectory::RemoveChild(GDataEntry* entry) { | |
| 390 DCHECK(entry); | |
| 391 | |
| 392 const std::string file_name(entry->file_name()); | |
| 393 GDataEntry* found_entry = FindChild(file_name); | |
| 394 if (!found_entry) | |
| 375 return false; | 395 return false; |
| 376 | 396 |
| 377 DCHECK(iter->second); | 397 DCHECK_EQ(entry, found_entry); |
| 378 DCHECK_EQ(entry, iter->second); | |
| 379 | 398 |
| 380 // Remove entry from resource map first. | 399 // Remove entry from resource map first. |
| 381 root_->RemoveEntryFromResourceMap(entry); | 400 root_->RemoveEntryFromResourceMap(entry); |
| 382 | 401 |
| 383 // Then delete it from tree. | 402 // Then delete it from tree. |
| 384 children_.erase(iter); | 403 child_files_.erase(file_name); |
| 404 child_directories_.erase(file_name); | |
| 385 | 405 |
| 386 return true; | 406 return true; |
| 387 } | 407 } |
| 388 | 408 |
| 409 void GDataDirectory::RemoveChildren() { | |
| 410 // Remove child files first. | |
| 411 for (GDataFileCollection::const_iterator iter = child_files_.begin(); | |
| 412 iter != child_files_.end(); ++iter) { | |
| 413 root_->RemoveEntryFromResourceMap(iter->second); | |
| 414 } | |
| 415 STLDeleteValues(&child_files_); | |
| 416 child_files_.clear(); | |
| 417 | |
| 418 for (GDataDirectoryCollection::iterator iter = child_directories_.begin(); | |
| 419 iter != child_directories_.end(); ++iter) { | |
| 420 GDataDirectory* dir = iter->second; | |
| 421 // Remove directories recursively. | |
| 422 dir->RemoveChildren(); | |
| 423 root_->RemoveEntryFromResourceMap(dir); | |
| 424 } | |
| 425 STLDeleteValues(&child_directories_); | |
| 426 child_directories_.clear(); | |
| 427 } | |
| 428 | |
| 389 // GDataRootDirectory::CacheEntry struct implementation. | 429 // GDataRootDirectory::CacheEntry struct implementation. |
| 390 | 430 |
| 391 std::string GDataRootDirectory::CacheEntry::ToString() const { | 431 std::string GDataRootDirectory::CacheEntry::ToString() const { |
| 392 std::vector<std::string> cache_states; | 432 std::vector<std::string> cache_states; |
| 393 if (GDataFile::IsCachePresent(cache_state)) | 433 if (GDataFile::IsCachePresent(cache_state)) |
| 394 cache_states.push_back("present"); | 434 cache_states.push_back("present"); |
| 395 if (GDataFile::IsCachePinned(cache_state)) | 435 if (GDataFile::IsCachePinned(cache_state)) |
| 396 cache_states.push_back("pinned"); | 436 cache_states.push_back("pinned"); |
| 397 if (GDataFile::IsCacheDirty(cache_state)) | 437 if (GDataFile::IsCacheDirty(cache_state)) |
| 398 cache_states.push_back("dirty"); | 438 cache_states.push_back("dirty"); |
| 399 | 439 |
| 400 return base::StringPrintf("md5=%s, subdir=%s, cache_state=%s", | 440 return base::StringPrintf("md5=%s, subdir=%s, cache_state=%s", |
| 401 md5.c_str(), | 441 md5.c_str(), |
| 402 CacheSubDirectoryTypeToString(sub_dir_type).c_str(), | 442 CacheSubDirectoryTypeToString(sub_dir_type).c_str(), |
| 403 JoinString(cache_states, ',').c_str()); | 443 JoinString(cache_states, ',').c_str()); |
| 404 } | 444 } |
| 405 | 445 |
| 406 // GDataRootDirectory class implementation. | 446 // GDataRootDirectory class implementation. |
| 407 | 447 |
| 408 GDataRootDirectory::GDataRootDirectory() | 448 GDataRootDirectory::GDataRootDirectory() |
| 409 : ALLOW_THIS_IN_INITIALIZER_LIST(GDataDirectory(NULL, this)), | 449 : ALLOW_THIS_IN_INITIALIZER_LIST(GDataDirectory(NULL, this)), |
| 410 largest_changestamp_(0), serialized_size_(0) { | 450 largest_changestamp_(0), serialized_size_(0) { |
| 451 title_ = kGDataRootDirectory; | |
| 452 SetFileNameFromTitle(); | |
| 411 } | 453 } |
| 412 | 454 |
| 413 GDataRootDirectory::~GDataRootDirectory() { | 455 GDataRootDirectory::~GDataRootDirectory() { |
| 414 STLDeleteValues(&cache_map_); | 456 STLDeleteValues(&cache_map_); |
| 415 cache_map_.clear(); | 457 cache_map_.clear(); |
| 416 | 458 |
| 417 resource_map_.clear(); | 459 resource_map_.clear(); |
| 418 } | 460 } |
| 419 | 461 |
| 420 GDataRootDirectory* GDataRootDirectory::AsGDataRootDirectory() { | 462 GDataRootDirectory* GDataRootDirectory::AsGDataRootDirectory() { |
| 421 return this; | 463 return this; |
| 422 } | 464 } |
| 423 | 465 |
| 424 void GDataRootDirectory::AddEntryToResourceMap(GDataEntry* entry) { | 466 void GDataRootDirectory::AddEntryToResourceMap(GDataEntry* entry) { |
| 425 // GDataFileSystem has already locked. | 467 // GDataFileSystem has already locked. |
| 468 DVLOG(1) << "AddEntryToResourceMap " << entry->resource_id(); | |
| 426 resource_map_.insert(std::make_pair(entry->resource_id(), entry)); | 469 resource_map_.insert(std::make_pair(entry->resource_id(), entry)); |
| 427 } | 470 } |
| 428 | 471 |
| 429 void GDataRootDirectory::RemoveEntryFromResourceMap(GDataEntry* entry) { | 472 void GDataRootDirectory::RemoveEntryFromResourceMap(GDataEntry* entry) { |
| 430 // GDataFileSystem has already locked. | 473 // GDataFileSystem has already locked. |
| 431 resource_map_.erase(entry->resource_id()); | 474 resource_map_.erase(entry->resource_id()); |
| 432 } | 475 } |
| 433 | 476 |
| 434 void GDataRootDirectory::RemoveEntriesFromResourceMap( | |
| 435 const GDataFileCollection& children) { | |
| 436 // GDataFileSystem has already locked. | |
| 437 for (GDataFileCollection::const_iterator iter = children.begin(); | |
| 438 iter != children.end(); ++iter) { | |
| 439 // Recursively call RemoveEntrysFromResourceMap for each directory. | |
| 440 if (iter->second->AsGDataDirectory()) { | |
| 441 RemoveEntriesFromResourceMap( | |
| 442 iter->second->AsGDataDirectory()->children()); | |
| 443 continue; | |
| 444 } | |
| 445 | |
| 446 resource_map_.erase(iter->second->resource_id()); | |
| 447 } | |
| 448 } | |
| 449 | |
| 450 void GDataRootDirectory::FindEntryByPath( | 477 void GDataRootDirectory::FindEntryByPath( |
| 451 const FilePath& file_path, | 478 const FilePath& file_path, |
| 452 FindEntryDelegate* delegate) { | 479 FindEntryDelegate* delegate) { |
| 453 // GDataFileSystem has already locked. | 480 // GDataFileSystem has already locked. |
| 454 DCHECK(delegate); | 481 DCHECK(delegate); |
| 455 | 482 |
| 456 std::vector<FilePath::StringType> components; | 483 std::vector<FilePath::StringType> components; |
| 457 file_path.GetComponents(&components); | 484 file_path.GetComponents(&components); |
| 458 | 485 |
| 459 GDataDirectory* current_dir = this; | 486 GDataDirectory* current_dir = this; |
| 460 FilePath directory_path; | 487 FilePath directory_path; |
| 461 for (size_t i = 0; i < components.size() && current_dir; i++) { | 488 for (size_t i = 0; i < components.size() && current_dir; i++) { |
| 462 directory_path = directory_path.Append(current_dir->file_name()); | 489 directory_path = directory_path.Append(current_dir->file_name()); |
| 463 | 490 |
| 464 // Last element must match, if not last then it must be a directory. | 491 // Last element must match, if not last then it must be a directory. |
| 465 if (i == components.size() - 1) { | 492 if (i == components.size() - 1) { |
| 466 if (current_dir->file_name() == components[i]) | 493 if (current_dir->file_name() == components[i]) |
| 467 delegate->OnDone(base::PLATFORM_FILE_OK, directory_path, current_dir); | 494 delegate->OnDone(base::PLATFORM_FILE_OK, directory_path, current_dir); |
| 468 else | 495 else |
| 469 delegate->OnDone(base::PLATFORM_FILE_ERROR_NOT_FOUND, FilePath(), NULL); | 496 delegate->OnDone(base::PLATFORM_FILE_ERROR_NOT_FOUND, FilePath(), NULL); |
| 470 | 497 |
| 471 return; | 498 return; |
| 472 } | 499 } |
| 473 | 500 |
| 474 // Not the last part of the path, search for the next segment. | 501 // Not the last part of the path, search for the next segment. |
| 475 GDataFileCollection::const_iterator file_iter = | 502 GDataEntry* entry = current_dir->FindChild(components[i + 1]); |
| 476 current_dir->children().find(components[i + 1]); | 503 if (!entry) { |
| 477 if (file_iter == current_dir->children().end()) { | |
| 478 delegate->OnDone(base::PLATFORM_FILE_ERROR_NOT_FOUND, FilePath(), NULL); | 504 delegate->OnDone(base::PLATFORM_FILE_ERROR_NOT_FOUND, FilePath(), NULL); |
| 479 return; | 505 return; |
| 480 } | 506 } |
| 481 | 507 |
| 482 // Found file, must be the last segment. | 508 // Found file, must be the last segment. |
| 483 if (file_iter->second->file_info().is_directory) { | 509 if (entry->file_info().is_directory) { |
| 484 // Found directory, continue traversal. | 510 // Found directory, continue traversal. |
| 485 current_dir = file_iter->second->AsGDataDirectory(); | 511 current_dir = entry->AsGDataDirectory(); |
| 486 } else { | 512 } else { |
| 487 if ((i + 1) == (components.size() - 1)) { | 513 if ((i + 1) == (components.size() - 1)) { |
| 488 delegate->OnDone(base::PLATFORM_FILE_OK, | 514 delegate->OnDone(base::PLATFORM_FILE_OK, |
| 489 directory_path, | 515 directory_path, |
| 490 file_iter->second); | 516 entry); |
| 491 } else { | 517 } else { |
| 492 delegate->OnDone(base::PLATFORM_FILE_ERROR_NOT_FOUND, FilePath(), NULL); | 518 delegate->OnDone(base::PLATFORM_FILE_ERROR_NOT_FOUND, FilePath(), NULL); |
| 493 } | 519 } |
| 494 | 520 |
| 495 return; | 521 return; |
| 496 } | 522 } |
| 497 } | 523 } |
| 498 delegate->OnDone(base::PLATFORM_FILE_ERROR_NOT_FOUND, FilePath(), NULL); | 524 delegate->OnDone(base::PLATFORM_FILE_ERROR_NOT_FOUND, FilePath(), NULL); |
| 499 } | 525 } |
| 500 | 526 |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 610 file_info_.size = proto.file_info().size(); | 636 file_info_.size = proto.file_info().size(); |
| 611 file_info_.is_directory = proto.file_info().is_directory(); | 637 file_info_.is_directory = proto.file_info().is_directory(); |
| 612 file_info_.is_symbolic_link = proto.file_info().is_symbolic_link(); | 638 file_info_.is_symbolic_link = proto.file_info().is_symbolic_link(); |
| 613 file_info_.last_modified = base::Time::FromInternalValue( | 639 file_info_.last_modified = base::Time::FromInternalValue( |
| 614 proto.file_info().last_modified()); | 640 proto.file_info().last_modified()); |
| 615 file_info_.last_accessed = base::Time::FromInternalValue( | 641 file_info_.last_accessed = base::Time::FromInternalValue( |
| 616 proto.file_info().last_accessed()); | 642 proto.file_info().last_accessed()); |
| 617 file_info_.creation_time = base::Time::FromInternalValue( | 643 file_info_.creation_time = base::Time::FromInternalValue( |
| 618 proto.file_info().creation_time()); | 644 proto.file_info().creation_time()); |
| 619 | 645 |
| 620 file_name_ = proto.file_name(); | |
| 621 title_ = proto.title(); | 646 title_ = proto.title(); |
| 622 resource_id_ = proto.resource_id(); | 647 resource_id_ = proto.resource_id(); |
| 648 parent_resource_id_ = proto.parent_resource_id(); | |
| 623 edit_url_ = GURL(proto.edit_url()); | 649 edit_url_ = GURL(proto.edit_url()); |
| 624 content_url_ = GURL(proto.content_url()); | 650 content_url_ = GURL(proto.content_url()); |
| 651 SetFileNameFromTitle(); | |
| 625 } | 652 } |
| 626 | 653 |
| 627 void GDataEntry::ToProto(GDataEntryProto* proto) const { | 654 void GDataEntry::ToProto(GDataEntryProto* proto) const { |
| 628 PlatformFileInfoProto* proto_file_info = proto->mutable_file_info(); | 655 PlatformFileInfoProto* proto_file_info = proto->mutable_file_info(); |
| 629 proto_file_info->set_size(file_info_.size); | 656 proto_file_info->set_size(file_info_.size); |
| 630 proto_file_info->set_is_directory(file_info_.is_directory); | 657 proto_file_info->set_is_directory(file_info_.is_directory); |
| 631 proto_file_info->set_is_symbolic_link(file_info_.is_symbolic_link); | 658 proto_file_info->set_is_symbolic_link(file_info_.is_symbolic_link); |
| 632 proto_file_info->set_last_modified( | 659 proto_file_info->set_last_modified( |
| 633 file_info_.last_modified.ToInternalValue()); | 660 file_info_.last_modified.ToInternalValue()); |
| 634 proto_file_info->set_last_accessed( | 661 proto_file_info->set_last_accessed( |
| 635 file_info_.last_accessed.ToInternalValue()); | 662 file_info_.last_accessed.ToInternalValue()); |
| 636 proto_file_info->set_creation_time( | 663 proto_file_info->set_creation_time( |
| 637 file_info_.creation_time.ToInternalValue()); | 664 file_info_.creation_time.ToInternalValue()); |
| 638 | 665 |
| 639 proto->set_file_name(file_name_); | |
| 640 proto->set_title(title_); | 666 proto->set_title(title_); |
| 641 proto->set_resource_id(resource_id_); | 667 proto->set_resource_id(resource_id_); |
| 668 proto->set_parent_resource_id(parent_resource_id_); | |
| 642 proto->set_edit_url(edit_url_.spec()); | 669 proto->set_edit_url(edit_url_.spec()); |
| 643 proto->set_content_url(content_url_.spec()); | 670 proto->set_content_url(content_url_.spec()); |
| 644 } | 671 } |
| 645 | 672 |
| 646 void GDataFile::FromProto(const GDataFileProto& proto) { | 673 void GDataFile::FromProto(const GDataFileProto& proto) { |
| 647 DCHECK(!proto.gdata_entry().file_info().is_directory()); | 674 DCHECK(!proto.gdata_entry().file_info().is_directory()); |
| 648 GDataEntry::FromProto(proto.gdata_entry()); | 675 GDataEntry::FromProto(proto.gdata_entry()); |
| 649 kind_ = DocumentEntry::EntryKind(proto.kind()); | 676 kind_ = DocumentEntry::EntryKind(proto.kind()); |
| 650 thumbnail_url_ = GURL(proto.thumbnail_url()); | 677 thumbnail_url_ = GURL(proto.thumbnail_url()); |
| 651 alternate_url_ = GURL(proto.alternate_url()); | 678 alternate_url_ = GURL(proto.alternate_url()); |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 692 } | 719 } |
| 693 | 720 |
| 694 void GDataDirectory::ToProto(GDataDirectoryProto* proto) const { | 721 void GDataDirectory::ToProto(GDataDirectoryProto* proto) const { |
| 695 GDataEntry::ToProto(proto->mutable_gdata_entry()); | 722 GDataEntry::ToProto(proto->mutable_gdata_entry()); |
| 696 DCHECK(proto->gdata_entry().file_info().is_directory()); | 723 DCHECK(proto->gdata_entry().file_info().is_directory()); |
| 697 proto->set_refresh_time(refresh_time_.ToInternalValue()); | 724 proto->set_refresh_time(refresh_time_.ToInternalValue()); |
| 698 proto->set_start_feed_url(start_feed_url_.spec()); | 725 proto->set_start_feed_url(start_feed_url_.spec()); |
| 699 proto->set_next_feed_url(next_feed_url_.spec()); | 726 proto->set_next_feed_url(next_feed_url_.spec()); |
| 700 proto->set_upload_url(upload_url_.spec()); | 727 proto->set_upload_url(upload_url_.spec()); |
| 701 proto->set_origin(origin_); | 728 proto->set_origin(origin_); |
| 702 for (GDataFileCollection::const_iterator iter = children_.begin(); | 729 for (GDataFileCollection::const_iterator iter = child_files_.begin(); |
| 703 iter != children_.end(); ++iter) { | 730 iter != child_files_.end(); ++iter) { |
| 704 GDataFile* file = iter->second->AsGDataFile(); | 731 GDataFile* file = iter->second; |
| 705 GDataDirectory* dir = iter->second->AsGDataDirectory(); | 732 file->ToProto(proto->add_child_files()); |
| 706 if (file) | 733 } |
| 707 file->ToProto(proto->add_child_files()); | 734 for (GDataDirectoryCollection::const_iterator iter = |
| 708 if (dir) | 735 child_directories_.begin(); |
| 709 dir->ToProto(proto->add_child_directories()); | 736 iter != child_directories_.end(); ++iter) { |
| 737 GDataDirectory* dir = iter->second; | |
| 738 dir->ToProto(proto->add_child_directories()); | |
| 710 } | 739 } |
| 711 } | 740 } |
| 712 | 741 |
| 713 void GDataRootDirectory::FromProto(const GDataRootDirectoryProto& proto) { | 742 void GDataRootDirectory::FromProto(const GDataRootDirectoryProto& proto) { |
| 714 root_ = this; | 743 root_ = this; |
| 715 GDataDirectory::FromProto(proto.gdata_directory()); | 744 GDataDirectory::FromProto(proto.gdata_directory()); |
| 716 largest_changestamp_ = proto.largest_changestamp(); | 745 largest_changestamp_ = proto.largest_changestamp(); |
| 717 } | 746 } |
| 718 | 747 |
| 719 void GDataRootDirectory::ToProto(GDataRootDirectoryProto* proto) const { | 748 void GDataRootDirectory::ToProto(GDataRootDirectoryProto* proto) const { |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 778 bool ok = proto->ParseFromString(serialized_proto); | 807 bool ok = proto->ParseFromString(serialized_proto); |
| 779 if (ok) { | 808 if (ok) { |
| 780 FromProto(*proto.get()); | 809 FromProto(*proto.get()); |
| 781 set_origin(FROM_CACHE); | 810 set_origin(FROM_CACHE); |
| 782 set_refresh_time(base::Time::Now()); | 811 set_refresh_time(base::Time::Now()); |
| 783 } | 812 } |
| 784 return ok; | 813 return ok; |
| 785 } | 814 } |
| 786 | 815 |
| 787 } // namespace gdata | 816 } // namespace gdata |
| OLD | NEW |