15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/chromeos/drive/file_cache.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/callback_helpers.h" 10868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/files/file_enumerator.h" 111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 130f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)#include "base/metrics/histogram.h" 145e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/string_util.h" 155e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/stringprintf.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/sys_info.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/chromeos/drive/drive.pb.h" 18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/chromeos/drive/file_system_util.h" 19eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "chrome/browser/chromeos/drive/resource_metadata_storage.h" 208bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "chrome/browser/drive/drive_api_util.h" 21a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#include "chromeos/chromeos_constants.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_thread.h" 235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "google_apis/drive/task_util.h" 24c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "net/base/filename_util.h" 250f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)#include "net/base/mime_sniffer.h" 260f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)#include "net/base/mime_util.h" 275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "third_party/cros_system_api/constants/cryptohome.h" 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserThread; 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace drive { 32b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)namespace internal { 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 35424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// Returns ID extracted from the path. 36424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)std::string GetIdFromPath(const base::FilePath& path) { 377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return util::UnescapeCacheFileName(path.BaseName().AsUTF8Unsafe()); 387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} 397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 42eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochFileCache::FileCache(ResourceMetadataStorage* storage, 437d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) const base::FilePath& cache_file_directory, 44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::SequencedTaskRunner* blocking_task_runner, 45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) FreeDiskSpaceGetterInterface* free_disk_space_getter) 46eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch : cache_file_directory_(cache_file_directory), 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) blocking_task_runner_(blocking_task_runner), 48eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch storage_(storage), 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) free_disk_space_getter_(free_disk_space_getter), 50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) weak_ptr_factory_(this) { 517d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) DCHECK(blocking_task_runner_.get()); 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)FileCache::~FileCache() { 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Must be on the sequenced worker pool, as |metadata_| must be deleted on 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // the sequenced worker pool. 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AssertOnSequencedWorkerPool(); 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 61424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)base::FilePath FileCache::GetCacheFilePath(const std::string& id) const { 627d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return cache_file_directory_.Append( 63424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) base::FilePath::FromUTF8Unsafe(util::EscapeCacheFileName(id))); 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void FileCache::AssertOnSequencedWorkerPool() { 67a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread()); 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool FileCache::IsUnderFileCacheDirectory(const base::FilePath& path) const { 717d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return cache_file_directory_.IsParent(path); 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)bool FileCache::FreeDiskSpaceIfNeededFor(int64 num_bytes) { 7590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) AssertOnSequencedWorkerPool(); 7690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 7790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Do nothing and return if we have enough space. 787d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (HasEnoughSpaceFor(num_bytes, cache_file_directory_)) 7990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return true; 8090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 8190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Otherwise, try to free up the disk space. 8290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DVLOG(1) << "Freeing up disk space for " << num_bytes; 83868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 847d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // Remove all entries unless specially marked. 85cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) scoped_ptr<ResourceMetadataStorage::Iterator> it = storage_->GetIterator(); 86868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) for (; !it->IsAtEnd(); it->Advance()) { 87cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (it->GetValue().file_specific_info().has_cache_state() && 88cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) !it->GetValue().file_specific_info().cache_state().is_pinned() && 89cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) !it->GetValue().file_specific_info().cache_state().is_dirty() && 90cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) !mounted_files_.count(it->GetID())) { 91cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ResourceEntry entry(it->GetValue()); 92cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) entry.mutable_file_specific_info()->clear_cache_state(); 93cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) storage_->PutEntry(entry); 94cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 95868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 96cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (it->HasError()) 97cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return false; 98868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 997d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // Remove all files which have no corresponding cache entries. 1007d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) base::FileEnumerator enumerator(cache_file_directory_, 1017d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) false, // not recursive 1027d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) base::FileEnumerator::FILES); 103cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ResourceEntry entry; 1047d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) for (base::FilePath current = enumerator.Next(); !current.empty(); 1057d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) current = enumerator.Next()) { 106424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) std::string id = GetIdFromPath(current); 107cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) FileError error = storage_->GetEntry(id, &entry); 108cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (error == FILE_ERROR_NOT_FOUND || 109cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) (error == FILE_ERROR_OK && 110cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) !entry.file_specific_info().cache_state().is_present())) 1117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch base::DeleteFile(current, false /* recursive */); 112cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) else if (error != FILE_ERROR_OK) 113cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return false; 1147d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } 11590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 11690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Check the disk space again. 1177d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return HasEnoughSpaceFor(num_bytes, cache_file_directory_); 11890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 11990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 120424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)FileError FileCache::GetFile(const std::string& id, 12190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::FilePath* cache_file_path) { 12290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) AssertOnSequencedWorkerPool(); 12390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DCHECK(cache_file_path); 12490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 125cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ResourceEntry entry; 126cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) FileError error = storage_->GetEntry(id, &entry); 127cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (error != FILE_ERROR_OK) 128cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return error; 129cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!entry.file_specific_info().cache_state().is_present()) 13090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return FILE_ERROR_NOT_FOUND; 13190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 132424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) *cache_file_path = GetCacheFilePath(id); 13390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return FILE_ERROR_OK; 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 136424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)FileError FileCache::Store(const std::string& id, 13790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const std::string& md5, 13890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const base::FilePath& source_path, 13990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) FileOperationType file_operation_type) { 14090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) AssertOnSequencedWorkerPool(); 141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 142cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ResourceEntry entry; 143cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) FileError error = storage_->GetEntry(id, &entry); 144cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (error != FILE_ERROR_OK) 145cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return error; 146cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 147a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) int64 file_size = 0; 148a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (file_operation_type == FILE_OPERATION_COPY) { 149a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (!base::GetFileSize(source_path, &file_size)) { 150a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) LOG(WARNING) << "Couldn't get file size for: " << source_path.value(); 151a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return FILE_ERROR_FAILED; 152a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 153a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 154a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (!FreeDiskSpaceIfNeededFor(file_size)) 155a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return FILE_ERROR_NO_LOCAL_SPACE; 156c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // If file is mounted, return error. 1585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (mounted_files_.count(id)) 159a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return FILE_ERROR_IN_USE; 160a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 161a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::FilePath dest_path = GetCacheFilePath(id); 162a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) bool success = false; 163a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) switch (file_operation_type) { 164a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) case FILE_OPERATION_MOVE: 165a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) success = base::Move(source_path, dest_path); 166a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) break; 167a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) case FILE_OPERATION_COPY: 168a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) success = base::CopyFile(source_path, dest_path); 169a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) break; 170a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) default: 171a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) NOTREACHED(); 172a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 173a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 174a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (!success) { 175a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) LOG(ERROR) << "Failed to store: " 176a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) << "source_path = " << source_path.value() << ", " 177a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) << "dest_path = " << dest_path.value() << ", " 178a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) << "file_operation_type = " << file_operation_type; 179a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return FILE_ERROR_FAILED; 180a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 181a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 182a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Now that file operations have completed, update metadata. 183cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) FileCacheEntry* cache_state = 184cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) entry.mutable_file_specific_info()->mutable_cache_state(); 185cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) cache_state->set_md5(md5); 186cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) cache_state->set_is_present(true); 1875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (md5.empty()) 188cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) cache_state->set_is_dirty(true); 189cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return storage_->PutEntry(entry); 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 192424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)FileError FileCache::Pin(const std::string& id) { 193868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) AssertOnSequencedWorkerPool(); 194868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 195cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ResourceEntry entry; 196cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) FileError error = storage_->GetEntry(id, &entry); 197cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (error != FILE_ERROR_OK) 198cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return error; 199cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) entry.mutable_file_specific_info()->mutable_cache_state()->set_is_pinned( 200cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) true); 201cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return storage_->PutEntry(entry); 202868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 203868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 204424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)FileError FileCache::Unpin(const std::string& id) { 20590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) AssertOnSequencedWorkerPool(); 20690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 20790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Unpinning a file means its entry must exist in cache. 208cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ResourceEntry entry; 209cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) FileError error = storage_->GetEntry(id, &entry); 210cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (error != FILE_ERROR_OK) 211cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return error; 21290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 21390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Now that file operations have completed, update metadata. 214cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (entry.file_specific_info().cache_state().is_present()) { 215cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) entry.mutable_file_specific_info()->mutable_cache_state()->set_is_pinned( 216cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) false); 21790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } else { 21890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Remove the existing entry if we are unpinning a non-present file. 219cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) entry.mutable_file_specific_info()->clear_cache_state(); 22090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 221cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) error = storage_->PutEntry(entry); 222cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (error != FILE_ERROR_OK) 223cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return error; 2247d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 2257d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // Now it's a chance to free up space if needed. 2267d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) FreeDiskSpaceIfNeededFor(0); 2277d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 22890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return FILE_ERROR_OK; 22990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 23090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 231424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)FileError FileCache::MarkAsMounted(const std::string& id, 232424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) base::FilePath* cache_file_path) { 233424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) AssertOnSequencedWorkerPool(); 234424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) DCHECK(cache_file_path); 235424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 236424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // Get cache entry associated with the id and md5 237cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ResourceEntry entry; 238cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) FileError error = storage_->GetEntry(id, &entry); 239cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (error != FILE_ERROR_OK) 240cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return error; 241cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!entry.file_specific_info().cache_state().is_present()) 242424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return FILE_ERROR_NOT_FOUND; 243424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 244424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (mounted_files_.count(id)) 245424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return FILE_ERROR_INVALID_OPERATION; 246424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 247424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // Ensure the file is readable to cros_disks. See crbug.com/236994. 248424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) base::FilePath path = GetCacheFilePath(id); 249f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (!base::SetPosixFilePermissions( 250424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) path, 251f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) base::FILE_PERMISSION_READ_BY_USER | 252f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) base::FILE_PERMISSION_WRITE_BY_USER | 253f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) base::FILE_PERMISSION_READ_BY_GROUP | 254f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) base::FILE_PERMISSION_READ_BY_OTHERS)) 255424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return FILE_ERROR_FAILED; 256424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 257424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) mounted_files_.insert(id); 258424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 259424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) *cache_file_path = path; 260424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return FILE_ERROR_OK; 261424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)} 262424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 2635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)FileError FileCache::OpenForWrite( 2645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string& id, 2655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<base::ScopedClosureRunner>* file_closer) { 266868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) AssertOnSequencedWorkerPool(); 267868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 268868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // Marking a file dirty means its entry and actual file blob must exist in 269868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // cache. 270cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ResourceEntry entry; 271cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) FileError error = storage_->GetEntry(id, &entry); 272cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (error != FILE_ERROR_OK) 273cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return error; 274cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!entry.file_specific_info().cache_state().is_present()) { 275424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) LOG(WARNING) << "Can't mark dirty a file that wasn't cached: " << id; 276868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return FILE_ERROR_NOT_FOUND; 277868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 278868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 279cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) entry.mutable_file_specific_info()->mutable_cache_state()->set_is_dirty(true); 280cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) entry.mutable_file_specific_info()->mutable_cache_state()->clear_md5(); 281cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) error = storage_->PutEntry(entry); 282cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (error != FILE_ERROR_OK) 283cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return error; 2845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) write_opened_files_[id]++; 2865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) file_closer->reset(new base::ScopedClosureRunner( 2875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base::Bind(&google_apis::RunTaskWithTaskRunner, 2885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) blocking_task_runner_, 2895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(&FileCache::CloseForWrite, 2905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) weak_ptr_factory_.GetWeakPtr(), 2915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) id)))); 2925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return FILE_ERROR_OK; 2935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool FileCache::IsOpenedForWrite(const std::string& id) { 2965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) AssertOnSequencedWorkerPool(); 2975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return write_opened_files_.count(id); 2985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)FileError FileCache::UpdateMd5(const std::string& id) { 3015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) AssertOnSequencedWorkerPool(); 3025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (IsOpenedForWrite(id)) 3045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return FILE_ERROR_IN_USE; 3055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 306cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ResourceEntry entry; 307cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) FileError error = storage_->GetEntry(id, &entry); 308cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (error != FILE_ERROR_OK) 309cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return error; 310cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!entry.file_specific_info().cache_state().is_present()) 3115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return FILE_ERROR_NOT_FOUND; 3125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string& md5 = util::GetMd5Digest(GetCacheFilePath(id)); 3145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (md5.empty()) 3155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return FILE_ERROR_NOT_FOUND; 3165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 317cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) entry.mutable_file_specific_info()->mutable_cache_state()->set_md5(md5); 318cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return storage_->PutEntry(entry); 319868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 320868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 3215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)FileError FileCache::ClearDirty(const std::string& id) { 32290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) AssertOnSequencedWorkerPool(); 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (IsOpenedForWrite(id)) 3255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return FILE_ERROR_IN_USE; 3265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 32790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Clearing a dirty file means its entry and actual file blob must exist in 32890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // cache. 329cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ResourceEntry entry; 330cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) FileError error = storage_->GetEntry(id, &entry); 331cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (error != FILE_ERROR_OK) 332cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return error; 333cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!entry.file_specific_info().cache_state().is_present()) { 33490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) LOG(WARNING) << "Can't clear dirty state of a file that wasn't cached: " 335424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) << id; 33690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return FILE_ERROR_NOT_FOUND; 33790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 33890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 3395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // If a file is not dirty (it should have been marked dirty via OpenForWrite), 3405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // clearing its dirty state is an invalid operation. 341cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!entry.file_specific_info().cache_state().is_dirty()) { 342424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) LOG(WARNING) << "Can't clear dirty state of a non-dirty file: " << id; 34390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return FILE_ERROR_INVALID_OPERATION; 34490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 34590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 346cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) entry.mutable_file_specific_info()->mutable_cache_state()->set_is_dirty( 347cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) false); 348cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return storage_->PutEntry(entry); 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 351424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)FileError FileCache::Remove(const std::string& id) { 35290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) AssertOnSequencedWorkerPool(); 35390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 354cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ResourceEntry entry; 35590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 3567d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // If entry doesn't exist, nothing to do. 357cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) FileError error = storage_->GetEntry(id, &entry); 358cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (error == FILE_ERROR_NOT_FOUND) 359cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return FILE_ERROR_OK; 360cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (error != FILE_ERROR_OK) 361cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return error; 362cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!entry.file_specific_info().has_cache_state()) 36390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return FILE_ERROR_OK; 36490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 3657dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // Cannot delete a mounted file. 366424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (mounted_files_.count(id)) 3677d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return FILE_ERROR_IN_USE; 36890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 3697dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // Delete the file. 370424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) base::FilePath path = GetCacheFilePath(id); 3717dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (!base::DeleteFile(path, false /* recursive */)) 3727dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return FILE_ERROR_FAILED; 37390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 37490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Now that all file operations have completed, remove from metadata. 375cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) entry.mutable_file_specific_info()->clear_cache_state(); 376cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return storage_->PutEntry(entry); 37790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 37890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 379d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)bool FileCache::ClearAll() { 380d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) AssertOnSequencedWorkerPool(); 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 382d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Remove files. 383d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) base::FileEnumerator enumerator(cache_file_directory_, 384d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) false, // not recursive 385d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) base::FileEnumerator::FILES); 386d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) for (base::FilePath file = enumerator.Next(); !file.empty(); 387d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) file = enumerator.Next()) 388d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) base::DeleteFile(file, false /* recursive */); 389d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 390d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) return true; 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3937d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)bool FileCache::Initialize() { 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AssertOnSequencedWorkerPool(); 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Older versions do not clear MD5 when marking entries dirty. 3975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Clear MD5 of all dirty entries to deal with old data. 398cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) scoped_ptr<ResourceMetadataStorage::Iterator> it = storage_->GetIterator(); 3995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (; !it->IsAtEnd(); it->Advance()) { 400cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (it->GetValue().file_specific_info().cache_state().is_dirty()) { 401cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ResourceEntry new_entry(it->GetValue()); 402cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) new_entry.mutable_file_specific_info()->mutable_cache_state()-> 403cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) clear_md5(); 404cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (storage_->PutEntry(new_entry) != FILE_ERROR_OK) 4055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 4065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 4075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 408cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (it->HasError()) 409cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return false; 4105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 4118bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (!RenameCacheFilesToNewFormat()) 4128bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) return false; 413868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return true; 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void FileCache::Destroy() { 4177d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 4187d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 4197d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // Destroy myself on the blocking pool. 4207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // Note that base::DeletePointer<> cannot be used as the destructor of this 4217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // class is private. 4227d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) blocking_task_runner_->PostTask( 4237d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) FROM_HERE, 4247d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) base::Bind(&FileCache::DestroyOnBlockingPool, base::Unretained(this))); 4257d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)} 4267d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 427c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void FileCache::DestroyOnBlockingPool() { 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AssertOnSequencedWorkerPool(); 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete this; 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4320f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)bool FileCache::RecoverFilesFromCacheDirectory( 4330f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) const base::FilePath& dest_directory, 434f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const ResourceMetadataStorage::RecoveredCacheInfoMap& 435f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) recovered_cache_info) { 4360f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) int file_number = 1; 4370f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 4380f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) base::FileEnumerator enumerator(cache_file_directory_, 4390f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) false, // not recursive 4400f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) base::FileEnumerator::FILES); 4410f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) for (base::FilePath current = enumerator.Next(); !current.empty(); 4420f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) current = enumerator.Next()) { 4430f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) const std::string& id = GetIdFromPath(current); 444cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ResourceEntry entry; 445cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) FileError error = storage_->GetEntry(id, &entry); 446cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (error != FILE_ERROR_OK && error != FILE_ERROR_NOT_FOUND) 447cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return false; 448cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (error == FILE_ERROR_OK && 449cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) entry.file_specific_info().cache_state().is_present()) { 4500f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // This file is managed by FileCache, no need to recover it. 4510f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) continue; 4520f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) } 4530f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 4540f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // If a cache entry which is non-dirty and has matching MD5 is found in 4550f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // |recovered_cache_entries|, it means the current file is already uploaded 4560f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // to the server. Just delete it instead of recovering it. 457f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ResourceMetadataStorage::RecoveredCacheInfoMap::const_iterator it = 458f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) recovered_cache_info.find(id); 459f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (it != recovered_cache_info.end()) { 460f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Due to the DB corruption, cache info might be recovered from old 461f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // revision. Perform MD5 check even when is_dirty is false just in case. 462f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (!it->second.is_dirty && 463f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) it->second.md5 == util::GetMd5Digest(current)) { 4640f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) base::DeleteFile(current, false /* recursive */); 4650f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) continue; 4660f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) } 4670f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) } 4680f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 4690f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // Read file contents to sniff mime type. 4700f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) std::vector<char> content(net::kMaxBytesToSniff); 4710f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) const int read_result = 472a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::ReadFile(current, &content[0], content.size()); 4730f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) if (read_result < 0) { 4740f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) LOG(WARNING) << "Cannot read: " << current.value(); 4750f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) return false; 4760f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) } 4770f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) if (read_result == 0) // Skip empty files. 4780f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) continue; 4790f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 480f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Use recovered file name if available, otherwise decide file name with 481f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // sniffed mime type. 4820f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) base::FilePath dest_base_name(FILE_PATH_LITERAL("file")); 4830f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) std::string mime_type; 484f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (it != recovered_cache_info.end() && !it->second.title.empty()) { 485f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // We can use a file name recovered from the trashed DB. 486f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) dest_base_name = base::FilePath::FromUTF8Unsafe(it->second.title); 487f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } else if (net::SniffMimeType(&content[0], read_result, 488f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) net::FilePathToFileURL(current), 489f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) std::string(), &mime_type) || 490f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) net::SniffMimeTypeFromLocalData(&content[0], read_result, 491f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) &mime_type)) { 4920f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // Change base name for common mime types. 4930f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) if (net::MatchesMimeType("image/*", mime_type)) { 4940f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) dest_base_name = base::FilePath(FILE_PATH_LITERAL("image")); 4950f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) } else if (net::MatchesMimeType("video/*", mime_type)) { 4960f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) dest_base_name = base::FilePath(FILE_PATH_LITERAL("video")); 4970f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) } else if (net::MatchesMimeType("audio/*", mime_type)) { 4980f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) dest_base_name = base::FilePath(FILE_PATH_LITERAL("audio")); 4990f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) } 5000f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 5010f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // Estimate extension from mime type. 5020f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) std::vector<base::FilePath::StringType> extensions; 5030f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) base::FilePath::StringType extension; 5040f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) if (net::GetPreferredExtensionForMimeType(mime_type, &extension)) 5050f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) extensions.push_back(extension); 5060f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) else 5070f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) net::GetExtensionsForMimeType(mime_type, &extensions); 5080f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 5090f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // Add extension if possible. 5100f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) if (!extensions.empty()) 5110f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) dest_base_name = dest_base_name.AddExtension(extensions[0]); 5120f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) } 5130f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 5140f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // Add file number to the file name and move. 5150f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) const base::FilePath& dest_path = dest_directory.Append(dest_base_name) 5160f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) .InsertBeforeExtensionASCII(base::StringPrintf("%08d", file_number++)); 517a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (!base::CreateDirectory(dest_directory) || 5180f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) !base::Move(current, dest_path)) { 5190f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) LOG(WARNING) << "Failed to move: " << current.value() 5200f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) << " to " << dest_path.value(); 5210f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) return false; 5220f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) } 5230f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) } 5240f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) UMA_HISTOGRAM_COUNTS("Drive.NumberOfCacheFilesRecoveredAfterDBCorruption", 5250f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) file_number - 1); 5260f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) return true; 5270f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)} 5280f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 529b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)FileError FileCache::MarkAsUnmounted(const base::FilePath& file_path) { 5302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) AssertOnSequencedWorkerPool(); 531c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(IsUnderFileCacheDirectory(file_path)); 5322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 533424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) std::string id = GetIdFromPath(file_path); 5342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 535cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Get the entry associated with the id. 536cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ResourceEntry entry; 537cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) FileError error = storage_->GetEntry(id, &entry); 538cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (error != FILE_ERROR_OK) 539cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return error; 5402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 541424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) std::set<std::string>::iterator it = mounted_files_.find(id); 5427d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (it == mounted_files_.end()) 543c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return FILE_ERROR_INVALID_OPERATION; 5442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) mounted_files_.erase(it); 546c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return FILE_ERROR_OK; 5472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 5482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 549c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool FileCache::HasEnoughSpaceFor(int64 num_bytes, 550c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const base::FilePath& path) { 5512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int64 free_space = 0; 5522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (free_disk_space_getter_) 5532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) free_space = free_disk_space_getter_->AmountOfFreeDiskSpace(); 5542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) else 5552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) free_space = base::SysInfo::AmountOfFreeDiskSpace(path); 5562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Subtract this as if this portion does not exist. 5585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) free_space -= cryptohome::kMinFreeSpaceInBytes; 5592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return (free_space >= num_bytes); 5602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 5612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5628bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)bool FileCache::RenameCacheFilesToNewFormat() { 5638bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) base::FileEnumerator enumerator(cache_file_directory_, 5648bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) false, // not recursive 5658bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) base::FileEnumerator::FILES); 5668bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) for (base::FilePath current = enumerator.Next(); !current.empty(); 5678bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) current = enumerator.Next()) { 5688bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) base::FilePath new_path = current.RemoveExtension(); 5698bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (!new_path.Extension().empty()) { 5708bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // Delete files with multiple extensions. 5718bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (!base::DeleteFile(current, false /* recursive */)) 5728bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) return false; 5738bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) continue; 5748bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) } 5758bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) const std::string& id = GetIdFromPath(new_path); 5768bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) new_path = GetCacheFilePath(util::CanonicalizeResourceId(id)); 5778bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (new_path != current && !base::Move(current, new_path)) 5788bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) return false; 5797dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 5808bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) return true; 5817dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} 5827dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 5835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void FileCache::CloseForWrite(const std::string& id) { 5845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) AssertOnSequencedWorkerPool(); 5855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::map<std::string, int>::iterator it = write_opened_files_.find(id); 5875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (it == write_opened_files_.end()) 5885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 5895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK_LT(0, it->second); 5915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) --it->second; 5925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (it->second == 0) 5935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) write_opened_files_.erase(it); 59446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 59546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // Update last modified date. 59646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ResourceEntry entry; 59746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) FileError error = storage_->GetEntry(id, &entry); 59846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (error != FILE_ERROR_OK) { 59946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) LOG(ERROR) << "Failed to get entry: " << id << ", " 60046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) << FileErrorToString(error); 60146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return; 60246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 60346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) entry.mutable_file_info()->set_last_modified( 60446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) base::Time::Now().ToInternalValue()); 60546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) error = storage_->PutEntry(entry); 60646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (error != FILE_ERROR_OK) { 60746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) LOG(ERROR) << "Failed to put entry: " << id << ", " 60846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) << FileErrorToString(error); 60946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 6105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 6115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 612b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)} // namespace internal 6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace drive 614