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 |