1c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// found in the LICENSE file. 4c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/disk_cache/cache_util.h" 6c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/file_util.h" 89ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/files/file_enumerator.h" 9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/location.h" 105e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/string_util.h" 115e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/stringprintf.h" 12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/threading/thread_restrictions.h" 13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/threading/worker_pool.h" 14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace { 16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const int kMaxOldFolders = 100; 18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Returns a fully qualified name from path and name, using a given name prefix 20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// and index number. For instance, if the arguments are "/foo", "bar" and 5, it 21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// will return "/foo/old_bar_005". 22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)base::FilePath GetPrefixedName(const base::FilePath& path, 23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const std::string& name, 24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int index) { 25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::string tmp = base::StringPrintf("%s%s_%03d", "old_", 26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) name.c_str(), index); 27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return path.AppendASCII(tmp); 28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// This is a simple callback to cleanup old caches. 31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void CleanupCallback(const base::FilePath& path, const std::string& name) { 32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) for (int i = 0; i < kMaxOldFolders; i++) { 33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::FilePath to_delete = GetPrefixedName(path, name, i); 34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) disk_cache::DeleteCache(to_delete, true); 35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Returns a full path to rename the current cache, in order to delete it. path 39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// is the current folder location, and name is the current folder name. 40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)base::FilePath GetTempCacheName(const base::FilePath& path, 41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const std::string& name) { 42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // We'll attempt to have up to kMaxOldFolders folders for deletion. 43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) for (int i = 0; i < kMaxOldFolders; i++) { 44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::FilePath to_delete = GetPrefixedName(path, name, i); 457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (!base::PathExists(to_delete)) 46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return to_delete; 47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return base::FilePath(); 49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} // namespace 52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace disk_cache { 54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 559ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdochvoid DeleteCache(const base::FilePath& path, bool remove_folder) { 569ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch if (remove_folder) { 579ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch if (!base::DeleteFile(path, /* recursive */ true)) 589ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch LOG(WARNING) << "Unable to delete cache folder."; 599ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch return; 609ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch } 619ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 629ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch base::FileEnumerator iter( 639ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch path, 649ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch /* recursive */ false, 659ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch base::FileEnumerator::FILES | base::FileEnumerator::DIRECTORIES); 669ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch for (base::FilePath file = iter.Next(); !file.value().empty(); 679ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch file = iter.Next()) { 689ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch if (!base::DeleteFile(file, /* recursive */ true)) { 699ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch LOG(WARNING) << "Unable to delete cache."; 709ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch return; 719ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch } 729ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch } 739ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch} 749ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// In order to process a potentially large number of files, we'll rename the 76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// cache directory to old_ + original_name + number, (located on the same parent 77c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// directory), and use a worker thread to delete all the files on all the stale 78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// cache directories. The whole process can still fail if we are not able to 79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// rename the cache directory (for instance due to a sharing violation), and in 80c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// that case a cache for this profile (on the desired path) cannot be created. 81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool DelayedCacheCleanup(const base::FilePath& full_path) { 82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // GetTempCacheName() and MoveCache() use synchronous file 83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // operations. 84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::ThreadRestrictions::ScopedAllowIO allow_io; 85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::FilePath current_path = full_path.StripTrailingSeparators(); 87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::FilePath path = current_path.DirName(); 89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::FilePath name = current_path.BaseName(); 90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#if defined(OS_POSIX) 91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::string name_str = name.value(); 92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#elif defined(OS_WIN) 93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // We created this file so it should only contain ASCII. 94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::string name_str = WideToASCII(name.value()); 95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#endif 96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::FilePath to_delete = GetTempCacheName(path, name_str); 98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (to_delete.empty()) { 99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) LOG(ERROR) << "Unable to get another cache folder"; 100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return false; 101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!disk_cache::MoveCache(full_path, to_delete)) { 104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) LOG(ERROR) << "Unable to move cache folder " << full_path.value() << " to " 105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) << to_delete.value(); 106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return false; 107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::WorkerPool::PostTask( 110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) FROM_HERE, base::Bind(&CleanupCallback, path, name_str), true); 111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return true; 112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} // namespace disk_cache 115