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_file_system.h" | 5 #include "chrome/browser/chromeos/gdata/gdata_file_system.h" |
6 | 6 |
7 #include <errno.h> | 7 #include <errno.h> |
8 #include <sys/stat.h> | 8 #include <sys/stat.h> |
9 | 9 |
10 #include <set> | 10 #include <set> |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
50 | 50 |
51 namespace gdata { | 51 namespace gdata { |
52 namespace { | 52 namespace { |
53 | 53 |
54 const char kMimeTypeJson[] = "application/json"; | 54 const char kMimeTypeJson[] = "application/json"; |
55 const char kMimeTypeOctetStream[] = "application/octet-stream"; | 55 const char kMimeTypeOctetStream[] = "application/octet-stream"; |
56 | 56 |
57 const FilePath::CharType kGDataRootDirectory[] = FILE_PATH_LITERAL("gdata"); | 57 const FilePath::CharType kGDataRootDirectory[] = FILE_PATH_LITERAL("gdata"); |
58 const char kWildCard[] = "*"; | 58 const char kWildCard[] = "*"; |
59 const char kLocallyModifiedFileExtension[] = "local"; | 59 const char kLocallyModifiedFileExtension[] = "local"; |
| 60 const char kMountedArchiveFileExtension[] = "mounted"; |
60 | 61 |
61 const FilePath::CharType kGDataCacheVersionDir[] = FILE_PATH_LITERAL("v1"); | 62 const FilePath::CharType kGDataCacheVersionDir[] = FILE_PATH_LITERAL("v1"); |
62 const FilePath::CharType kGDataCacheMetaDir[] = FILE_PATH_LITERAL("meta"); | 63 const FilePath::CharType kGDataCacheMetaDir[] = FILE_PATH_LITERAL("meta"); |
63 const FilePath::CharType kGDataCachePinnedDir[] = FILE_PATH_LITERAL("pinned"); | 64 const FilePath::CharType kGDataCachePinnedDir[] = FILE_PATH_LITERAL("pinned"); |
64 const FilePath::CharType kGDataCacheOutgoingDir[] = | 65 const FilePath::CharType kGDataCacheOutgoingDir[] = |
65 FILE_PATH_LITERAL("outgoing"); | 66 FILE_PATH_LITERAL("outgoing"); |
66 const FilePath::CharType kGDataCachePersistentDir[] = | 67 const FilePath::CharType kGDataCachePersistentDir[] = |
67 FILE_PATH_LITERAL("persistent"); | 68 FILE_PATH_LITERAL("persistent"); |
68 const FilePath::CharType kGDataCacheTmpDir[] = FILE_PATH_LITERAL("tmp"); | 69 const FilePath::CharType kGDataCacheTmpDir[] = FILE_PATH_LITERAL("tmp"); |
69 const FilePath::CharType kGDataCacheTmpDownloadsDir[] = | 70 const FilePath::CharType kGDataCacheTmpDownloadsDir[] = |
(...skipping 431 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
501 const std::string& md5, | 502 const std::string& md5, |
502 const FilePath& gdata_file_path, | 503 const FilePath& gdata_file_path, |
503 FilePath* cache_file_path) { | 504 FilePath* cache_file_path) { |
504 DCHECK(error); | 505 DCHECK(error); |
505 DCHECK(cache_file_path); | 506 DCHECK(cache_file_path); |
506 | 507 |
507 if (!callback.is_null()) | 508 if (!callback.is_null()) |
508 callback.Run(*error, resource_id, md5, gdata_file_path, *cache_file_path); | 509 callback.Run(*error, resource_id, md5, gdata_file_path, *cache_file_path); |
509 } | 510 } |
510 | 511 |
| 512 // Ditto for SetMountedStateCallback |
| 513 void RunSetMountedStateCallbackHelper( |
| 514 const SetMountedStateCallback& callback, |
| 515 base::PlatformFileError* error, |
| 516 FilePath* cache_file_path) { |
| 517 DCHECK(error); |
| 518 DCHECK(cache_file_path); |
| 519 |
| 520 if (!callback.is_null()) |
| 521 callback.Run(*error, *cache_file_path); |
| 522 } |
| 523 |
511 void RunGetCacheStateCallbackHelper( | 524 void RunGetCacheStateCallbackHelper( |
512 const GetCacheStateCallback& callback, | 525 const GetCacheStateCallback& callback, |
513 base::PlatformFileError* error, | 526 base::PlatformFileError* error, |
514 int* cache_state) { | 527 int* cache_state) { |
515 DCHECK(error); | 528 DCHECK(error); |
516 DCHECK(cache_state); | 529 DCHECK(cache_state); |
517 | 530 |
518 if (!callback.is_null()) | 531 if (!callback.is_null()) |
519 callback.Run(*error, *cache_state); | 532 callback.Run(*error, *cache_state); |
520 } | 533 } |
(...skipping 1483 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2004 if (regular_file) { | 2017 if (regular_file) { |
2005 properties->file_md5 = regular_file->file_md5(); | 2018 properties->file_md5 = regular_file->file_md5(); |
2006 properties->mime_type = regular_file->content_mime_type(); | 2019 properties->mime_type = regular_file->content_mime_type(); |
2007 properties->content_url = regular_file->content_url(); | 2020 properties->content_url = regular_file->content_url(); |
2008 properties->alternate_url = regular_file->alternate_url(); | 2021 properties->alternate_url = regular_file->alternate_url(); |
2009 properties->is_hosted_document = regular_file->is_hosted_document(); | 2022 properties->is_hosted_document = regular_file->is_hosted_document(); |
2010 } | 2023 } |
2011 return true; | 2024 return true; |
2012 } | 2025 } |
2013 | 2026 |
| 2027 bool GDataFileSystem::IsUnderGDataCacheDirectory(const FilePath& path) const { |
| 2028 return gdata_cache_path_ == path || gdata_cache_path_.IsParent(path); |
| 2029 } |
| 2030 |
2014 FilePath GDataFileSystem::GetGDataCacheTmpDirectory() const { | 2031 FilePath GDataFileSystem::GetGDataCacheTmpDirectory() const { |
2015 return cache_paths_[GDataRootDirectory::CACHE_TYPE_TMP]; | 2032 return cache_paths_[GDataRootDirectory::CACHE_TYPE_TMP]; |
2016 } | 2033 } |
2017 | 2034 |
2018 FilePath GDataFileSystem::GetGDataTempDownloadFolderPath() const { | 2035 FilePath GDataFileSystem::GetGDataTempDownloadFolderPath() const { |
2019 return cache_paths_[GDataRootDirectory::CACHE_TYPE_TMP_DOWNLOADS]; | 2036 return cache_paths_[GDataRootDirectory::CACHE_TYPE_TMP_DOWNLOADS]; |
2020 } | 2037 } |
2021 | 2038 |
2022 FilePath GDataFileSystem::GetGDataTempDocumentFolderPath() const { | 2039 FilePath GDataFileSystem::GetGDataTempDocumentFolderPath() const { |
2023 return cache_paths_[GDataRootDirectory::CACHE_TYPE_TMP_DOCUMENTS]; | 2040 return cache_paths_[GDataRootDirectory::CACHE_TYPE_TMP_DOCUMENTS]; |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2118 GetWeakPtrForCurrentThread(), | 2135 GetWeakPtrForCurrentThread(), |
2119 callback); | 2136 callback); |
2120 } | 2137 } |
2121 | 2138 |
2122 if (to_pin) | 2139 if (to_pin) |
2123 Pin(resource_id, md5, cache_callback); | 2140 Pin(resource_id, md5, cache_callback); |
2124 else | 2141 else |
2125 Unpin(resource_id, md5, cache_callback); | 2142 Unpin(resource_id, md5, cache_callback); |
2126 } | 2143 } |
2127 | 2144 |
| 2145 void GDataFileSystem::SetMountedState(const FilePath& file_path, bool to_mount, |
| 2146 const SetMountedStateCallback& callback) { |
| 2147 InitializeCacheIfNecessary(); |
| 2148 |
| 2149 base::PlatformFileError* error = |
| 2150 new base::PlatformFileError(base::PLATFORM_FILE_OK); |
| 2151 FilePath* cache_file_path = new FilePath; |
| 2152 PostBlockingPoolSequencedTaskAndReply( |
| 2153 kGDataFileSystemToken, |
| 2154 FROM_HERE, |
| 2155 base::Bind(&GDataFileSystem::SetMountedStateOnIOThreadPool, |
| 2156 base::Unretained(this), |
| 2157 file_path, |
| 2158 to_mount, |
| 2159 error, |
| 2160 cache_file_path), |
| 2161 base::Bind(&RunSetMountedStateCallbackHelper, |
| 2162 callback, |
| 2163 base::Owned(error), |
| 2164 base::Owned(cache_file_path))); |
| 2165 } |
| 2166 |
| 2167 void GDataFileSystem::SetMountedStateOnIOThreadPool( |
| 2168 const FilePath& file_path, |
| 2169 bool to_mount, |
| 2170 base::PlatformFileError *error, |
| 2171 FilePath* cache_file_path) { |
| 2172 DCHECK(error); |
| 2173 DCHECK(cache_file_path); |
| 2174 |
| 2175 // Lock to access cache map. |
| 2176 base::AutoLock lock(lock_); |
| 2177 |
| 2178 // Parse file path to obtain resource_id, md5 and extra_extension. |
| 2179 std::string resource_id; |
| 2180 std::string md5; |
| 2181 std::string extra_extension; |
| 2182 util::ParseCacheFilePath(file_path, &resource_id, &md5, &extra_extension); |
| 2183 // The extra_extension shall be ".mounted" iff we're unmounting. |
| 2184 DCHECK(!to_mount == (extra_extension == kMountedArchiveFileExtension)); |
| 2185 |
| 2186 // Get cache entry associated with the resource_id and md5 |
| 2187 GDataRootDirectory::CacheEntry* entry = root_->GetCacheEntry(resource_id, |
| 2188 md5); |
| 2189 if (!entry) { |
| 2190 *error = base::PLATFORM_FILE_ERROR_NOT_FOUND; |
| 2191 return; |
| 2192 } |
| 2193 if (to_mount == entry->IsMounted()) { |
| 2194 *error = base::PLATFORM_FILE_ERROR_INVALID_OPERATION; |
| 2195 return; |
| 2196 } |
| 2197 |
| 2198 // Get the subdir type and path for the unmounted state. |
| 2199 GDataRootDirectory::CacheSubDirectoryType unmounted_subdir = |
| 2200 entry->IsPinned() ? GDataRootDirectory::CACHE_TYPE_PERSISTENT : |
| 2201 GDataRootDirectory::CACHE_TYPE_TMP; |
| 2202 FilePath unmounted_path = GetCacheFilePath(resource_id, md5, unmounted_subdir, |
| 2203 CACHED_FILE_FROM_SERVER); |
| 2204 |
| 2205 // Get the subdir type and path for the mounted state. |
| 2206 GDataRootDirectory::CacheSubDirectoryType mounted_subdir = |
| 2207 GDataRootDirectory::CACHE_TYPE_PERSISTENT; |
| 2208 FilePath mounted_path = GetCacheFilePath(resource_id, md5, mounted_subdir, |
| 2209 CACHED_FILE_MOUNTED); |
| 2210 |
| 2211 // Determine the source and destination paths for moving the cache blob. |
| 2212 FilePath source_path; |
| 2213 GDataRootDirectory::CacheSubDirectoryType dest_subdir; |
| 2214 int cache_state = entry->cache_state; |
| 2215 if (to_mount) { |
| 2216 source_path = unmounted_path; |
| 2217 *cache_file_path = mounted_path; |
| 2218 dest_subdir = mounted_subdir; |
| 2219 cache_state = GDataFile::SetCacheMounted(cache_state); |
| 2220 } else { |
| 2221 source_path = mounted_path; |
| 2222 *cache_file_path = unmounted_path; |
| 2223 dest_subdir = unmounted_subdir; |
| 2224 cache_state = GDataFile::ClearCacheMounted(cache_state); |
| 2225 } |
| 2226 |
| 2227 // Move cache blob from source path to destination path. |
| 2228 *error = ModifyCacheState(source_path, *cache_file_path, |
| 2229 GDataFileSystem::FILE_OPERATION_MOVE, |
| 2230 FilePath(), false); |
| 2231 if (*error == base::PLATFORM_FILE_OK) { |
| 2232 // Now that cache operation is complete, update cache map |
| 2233 root_->UpdateCacheMap(resource_id, md5, dest_subdir, cache_state); |
| 2234 } |
| 2235 } |
| 2236 |
2128 void GDataFileSystem::OnSetPinStateCompleted( | 2237 void GDataFileSystem::OnSetPinStateCompleted( |
2129 const FileOperationCallback& callback, | 2238 const FileOperationCallback& callback, |
2130 base::PlatformFileError error, | 2239 base::PlatformFileError error, |
2131 const std::string& resource_id, | 2240 const std::string& resource_id, |
2132 const std::string& md5) { | 2241 const std::string& md5) { |
2133 callback.Run(error); | 2242 callback.Run(error); |
2134 } | 2243 } |
2135 | 2244 |
2136 void GDataFileSystem::OnGetAvailableSpace( | 2245 void GDataFileSystem::OnGetAvailableSpace( |
2137 const GetAvailableSpaceCallback& callback, | 2246 const GetAvailableSpaceCallback& callback, |
(...skipping 1070 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3208 FilePath GDataFileSystem::GetCacheFilePath( | 3317 FilePath GDataFileSystem::GetCacheFilePath( |
3209 const std::string& resource_id, | 3318 const std::string& resource_id, |
3210 const std::string& md5, | 3319 const std::string& md5, |
3211 GDataRootDirectory::CacheSubDirectoryType sub_dir_type, | 3320 GDataRootDirectory::CacheSubDirectoryType sub_dir_type, |
3212 CachedFileOrigin file_origin) const { | 3321 CachedFileOrigin file_origin) const { |
3213 DCHECK(sub_dir_type != GDataRootDirectory::CACHE_TYPE_META); | 3322 DCHECK(sub_dir_type != GDataRootDirectory::CACHE_TYPE_META); |
3214 | 3323 |
3215 // Runs on any thread. | 3324 // Runs on any thread. |
3216 // Filename is formatted as resource_id.md5, i.e. resource_id is the base | 3325 // Filename is formatted as resource_id.md5, i.e. resource_id is the base |
3217 // name and md5 is the extension. | 3326 // name and md5 is the extension. |
3218 std::string base_name = GDataEntry::EscapeUtf8FileName(resource_id); | 3327 std::string base_name = util::EscapeCacheFileName(resource_id); |
3219 if (file_origin == CACHED_FILE_LOCALLY_MODIFIED) { | 3328 if (file_origin == CACHED_FILE_LOCALLY_MODIFIED) { |
3220 DCHECK(sub_dir_type == GDataRootDirectory::CACHE_TYPE_PERSISTENT); | 3329 DCHECK(sub_dir_type == GDataRootDirectory::CACHE_TYPE_PERSISTENT); |
3221 base_name += FilePath::kExtensionSeparator; | 3330 base_name += FilePath::kExtensionSeparator; |
3222 base_name += kLocallyModifiedFileExtension; | 3331 base_name += kLocallyModifiedFileExtension; |
3223 } else if (!md5.empty()) { | 3332 } else if (!md5.empty()) { |
3224 base_name += FilePath::kExtensionSeparator; | 3333 base_name += FilePath::kExtensionSeparator; |
3225 base_name += GDataEntry::EscapeUtf8FileName(md5); | 3334 base_name += util::EscapeCacheFileName(md5); |
| 3335 } |
| 3336 // For mounted archives the filename is formatted as resource_id.md5.mounted, |
| 3337 // i.e. resource_id.md5 is the base name and ".mounted" is the extension |
| 3338 if (file_origin == CACHED_FILE_MOUNTED) { |
| 3339 DCHECK(sub_dir_type == GDataRootDirectory::CACHE_TYPE_PERSISTENT); |
| 3340 base_name += FilePath::kExtensionSeparator; |
| 3341 base_name += kMountedArchiveFileExtension; |
3226 } | 3342 } |
3227 return cache_paths_[sub_dir_type].Append(base_name); | 3343 return cache_paths_[sub_dir_type].Append(base_name); |
3228 } | 3344 } |
3229 | 3345 |
3230 void GDataFileSystem::GetFileFromCacheByResourceIdAndMd5( | 3346 void GDataFileSystem::GetFileFromCacheByResourceIdAndMd5( |
3231 const std::string& resource_id, | 3347 const std::string& resource_id, |
3232 const std::string& md5, | 3348 const std::string& md5, |
3233 const GetFileFromCacheCallback& callback) { | 3349 const GetFileFromCacheCallback& callback) { |
3234 GetFileFromCacheByResourceIdAndMd5Internal( | 3350 GetFileFromCacheByResourceIdAndMd5Internal( |
3235 resource_id, md5, FilePath(), callback); | 3351 resource_id, md5, FilePath(), callback); |
(...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3458 FilePath* cache_file_path) { | 3574 FilePath* cache_file_path) { |
3459 DCHECK(error); | 3575 DCHECK(error); |
3460 DCHECK(cache_file_path); | 3576 DCHECK(cache_file_path); |
3461 | 3577 |
3462 // Lock to access cache map. | 3578 // Lock to access cache map. |
3463 base::AutoLock lock(lock_); | 3579 base::AutoLock lock(lock_); |
3464 | 3580 |
3465 GDataRootDirectory::CacheEntry* entry = root_->GetCacheEntry(resource_id, | 3581 GDataRootDirectory::CacheEntry* entry = root_->GetCacheEntry(resource_id, |
3466 md5); | 3582 md5); |
3467 if (entry && entry->IsPresent()) { | 3583 if (entry && entry->IsPresent()) { |
| 3584 CachedFileOrigin file_origin; |
| 3585 if (entry->IsMounted()) { |
| 3586 file_origin = CACHED_FILE_MOUNTED; |
| 3587 } else if (entry->IsDirty()) { |
| 3588 file_origin = CACHED_FILE_LOCALLY_MODIFIED; |
| 3589 } else { |
| 3590 file_origin = CACHED_FILE_FROM_SERVER; |
| 3591 } |
3468 *cache_file_path = GetCacheFilePath( | 3592 *cache_file_path = GetCacheFilePath( |
3469 resource_id, | 3593 resource_id, |
3470 md5, | 3594 md5, |
3471 entry->sub_dir_type, | 3595 entry->sub_dir_type, |
3472 entry->IsDirty() ? CACHED_FILE_LOCALLY_MODIFIED : | 3596 file_origin); |
3473 CACHED_FILE_FROM_SERVER); | |
3474 *error = base::PLATFORM_FILE_OK; | 3597 *error = base::PLATFORM_FILE_OK; |
3475 } else { | 3598 } else { |
3476 *error = base::PLATFORM_FILE_ERROR_NOT_FOUND; | 3599 *error = base::PLATFORM_FILE_ERROR_NOT_FOUND; |
3477 } | 3600 } |
3478 } | 3601 } |
3479 | 3602 |
3480 void GDataFileSystem::GetCacheStateOnIOThreadPool( | 3603 void GDataFileSystem::GetCacheStateOnIOThreadPool( |
3481 const std::string& resource_id, | 3604 const std::string& resource_id, |
3482 const std::string& md5, | 3605 const std::string& md5, |
3483 base::PlatformFileError* error, | 3606 base::PlatformFileError* error, |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3520 int cache_state = GDataFile::CACHE_STATE_PRESENT; | 3643 int cache_state = GDataFile::CACHE_STATE_PRESENT; |
3521 GDataRootDirectory::CacheSubDirectoryType sub_dir_type = | 3644 GDataRootDirectory::CacheSubDirectoryType sub_dir_type = |
3522 GDataRootDirectory::CACHE_TYPE_TMP; | 3645 GDataRootDirectory::CACHE_TYPE_TMP; |
3523 | 3646 |
3524 GDataRootDirectory::CacheEntry* entry = root_->GetCacheEntry( | 3647 GDataRootDirectory::CacheEntry* entry = root_->GetCacheEntry( |
3525 resource_id, md5); | 3648 resource_id, md5); |
3526 | 3649 |
3527 // If file was previously pinned, store it in persistent dir and create | 3650 // If file was previously pinned, store it in persistent dir and create |
3528 // symlink in pinned dir. | 3651 // symlink in pinned dir. |
3529 if (entry) { // File exists in cache. | 3652 if (entry) { // File exists in cache. |
3530 // If file is dirty, return error. | 3653 // If file is dirty or mounted, return error. |
3531 if (entry->IsDirty()) { | 3654 if (entry->IsDirty() || entry->IsMounted()) { |
3532 LOG(WARNING) << "Can't store a file to replace a dirty file: res_id=" | 3655 LOG(WARNING) << "Can't store a file to replace a " |
3533 << resource_id | 3656 << (entry->IsDirty() ? "dirty" : "mounted") |
| 3657 << " file: res_id=" << resource_id |
3534 << ", md5=" << md5; | 3658 << ", md5=" << md5; |
3535 *error = base::PLATFORM_FILE_ERROR_IN_USE; | 3659 *error = base::PLATFORM_FILE_ERROR_IN_USE; |
3536 return; | 3660 return; |
3537 } | 3661 } |
3538 | 3662 |
3539 cache_state |= entry->cache_state; | 3663 cache_state |= entry->cache_state; |
3540 | 3664 |
3541 // If file is pinned, determines destination path. | 3665 // If file is pinned, determines destination path. |
3542 if (entry->IsPinned()) { | 3666 if (entry->IsPinned()) { |
3543 sub_dir_type = GDataRootDirectory::CACHE_TYPE_PERSISTENT; | 3667 sub_dir_type = GDataRootDirectory::CACHE_TYPE_PERSISTENT; |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3622 | 3746 |
3623 // Set sub_dir_type to PINNED to indicate that the file doesn't exist. | 3747 // Set sub_dir_type to PINNED to indicate that the file doesn't exist. |
3624 // When the file is finally downloaded and StoreToCache called, it will be | 3748 // When the file is finally downloaded and StoreToCache called, it will be |
3625 // moved to persistent directory. | 3749 // moved to persistent directory. |
3626 sub_dir_type = GDataRootDirectory::CACHE_TYPE_PINNED; | 3750 sub_dir_type = GDataRootDirectory::CACHE_TYPE_PINNED; |
3627 } else { // File exists in cache, determines destination path. | 3751 } else { // File exists in cache, determines destination path. |
3628 cache_state |= entry->cache_state; | 3752 cache_state |= entry->cache_state; |
3629 | 3753 |
3630 // Determine source and destination paths. | 3754 // Determine source and destination paths. |
3631 | 3755 |
3632 // If file is dirty, don't move it, so determine |dest_path| and set | 3756 // If file is dirty or mounted, don't move it, so determine |dest_path| and |
3633 // |source_path| the same, because ModifyCacheState only moves files if | 3757 // set |source_path| the same, because ModifyCacheState only moves files if |
3634 // source and destination are different. | 3758 // source and destination are different. |
3635 if (entry->IsDirty()) { | 3759 if (entry->IsDirty() || entry->IsMounted()) { |
3636 DCHECK_EQ(GDataRootDirectory::CACHE_TYPE_PERSISTENT, entry->sub_dir_type); | 3760 DCHECK_EQ(GDataRootDirectory::CACHE_TYPE_PERSISTENT, entry->sub_dir_type); |
3637 dest_path = GetCacheFilePath(resource_id, | 3761 dest_path = GetCacheFilePath(resource_id, |
3638 md5, | 3762 md5, |
3639 entry->sub_dir_type, | 3763 entry->sub_dir_type, |
3640 CACHED_FILE_LOCALLY_MODIFIED); | 3764 CACHED_FILE_LOCALLY_MODIFIED); |
3641 source_path = dest_path; | 3765 source_path = dest_path; |
3642 } else { | 3766 } else { |
3643 // Gets the current path of the file in cache. | 3767 // Gets the current path of the file in cache. |
3644 source_path = GetCacheFilePath(resource_id, | 3768 source_path = GetCacheFilePath(resource_id, |
3645 md5, | 3769 md5, |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3705 return; | 3829 return; |
3706 } | 3830 } |
3707 | 3831 |
3708 // Entry exists in cache, determines source and destination paths. | 3832 // Entry exists in cache, determines source and destination paths. |
3709 | 3833 |
3710 FilePath source_path; | 3834 FilePath source_path; |
3711 FilePath dest_path; | 3835 FilePath dest_path; |
3712 GDataRootDirectory::CacheSubDirectoryType sub_dir_type = | 3836 GDataRootDirectory::CacheSubDirectoryType sub_dir_type = |
3713 GDataRootDirectory::CACHE_TYPE_TMP; | 3837 GDataRootDirectory::CACHE_TYPE_TMP; |
3714 | 3838 |
3715 // If file is dirty, don't move it, so determine |dest_path| and set | 3839 // If file is dirty or mounted, don't move it, so determine |dest_path| and |
3716 // |source_path| the same, because ModifyCacheState moves files if source | 3840 // set |source_path| the same, because ModifyCacheState moves files if source |
3717 // and destination are different. | 3841 // and destination are different. |
3718 if (entry->IsDirty()) { | 3842 if (entry->IsDirty() || entry->IsMounted()) { |
3719 sub_dir_type = GDataRootDirectory::CACHE_TYPE_PERSISTENT; | 3843 sub_dir_type = GDataRootDirectory::CACHE_TYPE_PERSISTENT; |
3720 DCHECK_EQ(sub_dir_type, entry->sub_dir_type); | 3844 DCHECK_EQ(sub_dir_type, entry->sub_dir_type); |
3721 dest_path = GetCacheFilePath(resource_id, | 3845 dest_path = GetCacheFilePath(resource_id, |
3722 md5, | 3846 md5, |
3723 entry->sub_dir_type, | 3847 entry->sub_dir_type, |
3724 CACHED_FILE_LOCALLY_MODIFIED); | 3848 CACHED_FILE_LOCALLY_MODIFIED); |
3725 source_path = dest_path; | 3849 source_path = dest_path; |
3726 } else { | 3850 } else { |
3727 // Gets the current path of the file in cache. | 3851 // Gets the current path of the file in cache. |
3728 source_path = GetCacheFilePath(resource_id, | 3852 source_path = GetCacheFilePath(resource_id, |
(...skipping 311 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4040 // Lock to access cache map. | 4164 // Lock to access cache map. |
4041 base::AutoLock lock(lock_); | 4165 base::AutoLock lock(lock_); |
4042 | 4166 |
4043 // MD5 is not passed into RemoveFromCache and hence | 4167 // MD5 is not passed into RemoveFromCache and hence |
4044 // RemoveFromCacheOnIOThreadPool, because we would delete all cache files | 4168 // RemoveFromCacheOnIOThreadPool, because we would delete all cache files |
4045 // corresponding to <resource_id> regardless of the md5. | 4169 // corresponding to <resource_id> regardless of the md5. |
4046 // So, search for entry in cache without taking md5 into account. | 4170 // So, search for entry in cache without taking md5 into account. |
4047 GDataRootDirectory::CacheEntry* entry = root_->GetCacheEntry( | 4171 GDataRootDirectory::CacheEntry* entry = root_->GetCacheEntry( |
4048 resource_id, std::string()); | 4172 resource_id, std::string()); |
4049 | 4173 |
4050 // If entry doesn't exist or is dirty in cache, nothing to do. | 4174 // If entry doesn't exist or is dirty or mounted in cache, nothing to do. |
4051 if (!entry || entry->IsDirty()) { | 4175 if (!entry || entry->IsDirty() || entry->IsMounted()) { |
4052 DVLOG(1) << "Entry " << (entry ? "is dirty" : "doesn't exist") | 4176 DVLOG(1) << "Entry is " |
| 4177 << (entry ? (entry->IsDirty() ? "dirty" : "mounted") : |
| 4178 "non-existent") |
4053 << " in cache, not removing"; | 4179 << " in cache, not removing"; |
4054 *error = base::PLATFORM_FILE_OK; | 4180 *error = base::PLATFORM_FILE_OK; |
4055 return; | 4181 return; |
4056 } | 4182 } |
4057 | 4183 |
4058 // Determine paths to delete all cache versions of |resource_id| in | 4184 // Determine paths to delete all cache versions of |resource_id| in |
4059 // persistent, tmp and pinned directories. | 4185 // persistent, tmp and pinned directories. |
4060 std::vector<FilePath> paths_to_delete; | 4186 std::vector<FilePath> paths_to_delete; |
4061 | 4187 |
4062 // For files in persistent and tmp dirs, delete files that match | 4188 // For files in persistent and tmp dirs, delete files that match |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4164 file_util::FileEnumerator enumerator( | 4290 file_util::FileEnumerator enumerator( |
4165 cache_paths_[sub_dir_type], | 4291 cache_paths_[sub_dir_type], |
4166 false, // not recursive | 4292 false, // not recursive |
4167 static_cast<file_util::FileEnumerator::FileType>( | 4293 static_cast<file_util::FileEnumerator::FileType>( |
4168 file_util::FileEnumerator::FILES | | 4294 file_util::FileEnumerator::FILES | |
4169 file_util::FileEnumerator::SHOW_SYM_LINKS), | 4295 file_util::FileEnumerator::SHOW_SYM_LINKS), |
4170 kWildCard); | 4296 kWildCard); |
4171 for (FilePath current = enumerator.Next(); !current.empty(); | 4297 for (FilePath current = enumerator.Next(); !current.empty(); |
4172 current = enumerator.Next()) { | 4298 current = enumerator.Next()) { |
4173 // Extract resource_id and md5 from filename. | 4299 // Extract resource_id and md5 from filename. |
4174 FilePath base_name = current.BaseName(); | |
4175 std::string resource_id; | 4300 std::string resource_id; |
4176 std::string md5; | 4301 std::string md5; |
4177 | 4302 std::string extra_extension; |
4178 // Pinned and outgoing symlinks have no extension. | 4303 util::ParseCacheFilePath(current, &resource_id, &md5, &extra_extension); |
4179 if (sub_dir_type == GDataRootDirectory::CACHE_TYPE_PINNED || | |
4180 sub_dir_type == GDataRootDirectory::CACHE_TYPE_OUTGOING) { | |
4181 resource_id = GDataEntry::UnescapeUtf8FileName(base_name.value()); | |
4182 } else { | |
4183 FilePath::StringType extension = base_name.Extension(); | |
4184 if (!extension.empty()) { | |
4185 // FilePath::Extension returns ".", so strip it. | |
4186 md5 = GDataEntry::UnescapeUtf8FileName(extension.substr(1)); | |
4187 } | |
4188 resource_id = GDataEntry::UnescapeUtf8FileName( | |
4189 base_name.RemoveExtension().value()); | |
4190 } | |
4191 | 4304 |
4192 // Determine cache state. | 4305 // Determine cache state. |
4193 int cache_state = GDataFile::CACHE_STATE_NONE; | 4306 int cache_state = GDataFile::CACHE_STATE_NONE; |
4194 // If we're scanning pinned directory and if entry already exists, just | 4307 // If we're scanning pinned directory and if entry already exists, just |
4195 // update its pinned state. | 4308 // update its pinned state. |
4196 if (sub_dir_type == GDataRootDirectory::CACHE_TYPE_PINNED) { | 4309 if (sub_dir_type == GDataRootDirectory::CACHE_TYPE_PINNED) { |
4197 GDataRootDirectory::CacheMap::iterator iter = | 4310 GDataRootDirectory::CacheMap::iterator iter = |
4198 cache_map->find(resource_id); | 4311 cache_map->find(resource_id); |
4199 if (iter != cache_map->end()) { // Entry exists, update pinned state. | 4312 if (iter != cache_map->end()) { // Entry exists, update pinned state. |
4200 GDataRootDirectory::CacheEntry* entry = iter->second; | 4313 GDataRootDirectory::CacheEntry* entry = iter->second; |
(...skipping 11 matching lines...) Expand all Loading... |
4212 // ignore this outgoing symlink and move on. | 4325 // ignore this outgoing symlink and move on. |
4213 GDataRootDirectory::CacheMap::iterator iter = | 4326 GDataRootDirectory::CacheMap::iterator iter = |
4214 cache_map->find(resource_id); | 4327 cache_map->find(resource_id); |
4215 if (iter != cache_map->end()) { // Entry exists, update dirty state. | 4328 if (iter != cache_map->end()) { // Entry exists, update dirty state. |
4216 GDataRootDirectory::CacheEntry* entry = iter->second; | 4329 GDataRootDirectory::CacheEntry* entry = iter->second; |
4217 entry->cache_state = GDataFile::SetCacheDirty(entry->cache_state); | 4330 entry->cache_state = GDataFile::SetCacheDirty(entry->cache_state); |
4218 } else { | 4331 } else { |
4219 NOTREACHED() << "Dirty cache file MUST have actual file blob"; | 4332 NOTREACHED() << "Dirty cache file MUST have actual file blob"; |
4220 } | 4333 } |
4221 continue; | 4334 continue; |
| 4335 } else if (extra_extension == kMountedArchiveFileExtension) { |
| 4336 // Mounted archives in cache should be unmounted upon logout/shutdown. |
| 4337 // But if we encounter a mounted file at start, delete it and create an |
| 4338 // entry with not PRESENT state. |
| 4339 DCHECK(sub_dir_type == GDataRootDirectory::CACHE_TYPE_PERSISTENT); |
| 4340 file_util::Delete(current, false); |
4222 } else { | 4341 } else { |
4223 // Scanning other directories means that cache file is actually present. | 4342 // Scanning other directories means that cache file is actually present. |
4224 cache_state = GDataFile::SetCachePresent(cache_state); | 4343 cache_state = GDataFile::SetCachePresent(cache_state); |
4225 } | 4344 } |
4226 | 4345 |
4227 // Create and insert new entry into cache map. | 4346 // Create and insert new entry into cache map. |
4228 GDataRootDirectory::CacheEntry* entry = new GDataRootDirectory::CacheEntry( | 4347 GDataRootDirectory::CacheEntry* entry = new GDataRootDirectory::CacheEntry( |
4229 md5, sub_dir_type, cache_state); | 4348 md5, sub_dir_type, cache_state); |
4230 cache_map->insert(std::make_pair(resource_id, entry)); | 4349 cache_map->insert(std::make_pair(resource_id, entry)); |
4231 } | 4350 } |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4321 pref_registrar_->Init(profile_->GetPrefs()); | 4440 pref_registrar_->Init(profile_->GetPrefs()); |
4322 pref_registrar_->Add(prefs::kDisableGDataHostedFiles, this); | 4441 pref_registrar_->Add(prefs::kDisableGDataHostedFiles, this); |
4323 } | 4442 } |
4324 | 4443 |
4325 void SetFreeDiskSpaceGetterForTesting(FreeDiskSpaceGetterInterface* getter) { | 4444 void SetFreeDiskSpaceGetterForTesting(FreeDiskSpaceGetterInterface* getter) { |
4326 delete global_free_disk_getter_for_testing; // Safe to delete NULL; | 4445 delete global_free_disk_getter_for_testing; // Safe to delete NULL; |
4327 global_free_disk_getter_for_testing = getter; | 4446 global_free_disk_getter_for_testing = getter; |
4328 } | 4447 } |
4329 | 4448 |
4330 } // namespace gdata | 4449 } // namespace gdata |
OLD | NEW |