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 3 // found in the LICENSE file. 4 5 #include "base/files/file_path.h" 6 #include "base/metrics/field_trial.h" 7 #include "base/strings/stringprintf.h" 8 #include "net/base/cache_type.h" 9 #include "net/base/net_errors.h" 10 #include "net/disk_cache/backend_impl.h" 11 #include "net/disk_cache/cache_util.h" 12 #include "net/disk_cache/disk_cache.h" 13 #include "net/disk_cache/mem_backend_impl.h" 14 #include "net/disk_cache/simple/simple_backend_impl.h" 15 16 #ifdef USE_TRACING_CACHE_BACKEND 17 #include "net/disk_cache/tracing_cache_backend.h" 18 #endif 19 20 namespace { 21 22 // Builds an instance of the backend depending on platform, type, experiments 23 // etc. Takes care of the retry state. This object will self-destroy when 24 // finished. 25 class CacheCreator { 26 public: 27 CacheCreator(const base::FilePath& path, bool force, int max_bytes, 28 net::CacheType type, net::BackendType backend_type, uint32 flags, 29 base::MessageLoopProxy* thread, net::NetLog* net_log, 30 scoped_ptr<disk_cache::Backend>* backend, 31 const net::CompletionCallback& callback); 32 33 // Creates the backend. 34 int Run(); 35 36 private: 37 ~CacheCreator(); 38 39 void DoCallback(int result); 40 41 void OnIOComplete(int result); 42 43 const base::FilePath path_; 44 bool force_; 45 bool retry_; 46 int max_bytes_; 47 net::CacheType type_; 48 net::BackendType backend_type_; 49 uint32 flags_; 50 scoped_refptr<base::MessageLoopProxy> thread_; 51 scoped_ptr<disk_cache::Backend>* backend_; 52 net::CompletionCallback callback_; 53 scoped_ptr<disk_cache::Backend> created_cache_; 54 net::NetLog* net_log_; 55 56 DISALLOW_COPY_AND_ASSIGN(CacheCreator); 57 }; 58 59 CacheCreator::CacheCreator( 60 const base::FilePath& path, bool force, int max_bytes, 61 net::CacheType type, net::BackendType backend_type, uint32 flags, 62 base::MessageLoopProxy* thread, net::NetLog* net_log, 63 scoped_ptr<disk_cache::Backend>* backend, 64 const net::CompletionCallback& callback) 65 : path_(path), 66 force_(force), 67 retry_(false), 68 max_bytes_(max_bytes), 69 type_(type), 70 backend_type_(backend_type), 71 flags_(flags), 72 thread_(thread), 73 backend_(backend), 74 callback_(callback), 75 net_log_(net_log) { 76 } 77 78 CacheCreator::~CacheCreator() { 79 } 80 81 int CacheCreator::Run() { 82 // TODO(gavinp,pasko): Turn Simple Cache on for more cache types as 83 // appropriate. 84 if (backend_type_ == net::CACHE_BACKEND_SIMPLE && 85 (type_ == net::DISK_CACHE || type_ == net::APP_CACHE || 86 type_ == net::MEDIA_CACHE)) { 87 disk_cache::SimpleBackendImpl* simple_cache = 88 new disk_cache::SimpleBackendImpl(path_, max_bytes_, type_, 89 thread_.get(), net_log_); 90 created_cache_.reset(simple_cache); 91 return simple_cache->Init( 92 base::Bind(&CacheCreator::OnIOComplete, base::Unretained(this))); 93 } 94 disk_cache::BackendImpl* new_cache = 95 new disk_cache::BackendImpl(path_, thread_.get(), net_log_); 96 created_cache_.reset(new_cache); 97 new_cache->SetMaxSize(max_bytes_); 98 new_cache->SetType(type_); 99 new_cache->SetFlags(flags_); 100 int rv = new_cache->Init( 101 base::Bind(&CacheCreator::OnIOComplete, base::Unretained(this))); 102 DCHECK_EQ(net::ERR_IO_PENDING, rv); 103 return rv; 104 } 105 106 void CacheCreator::DoCallback(int result) { 107 DCHECK_NE(net::ERR_IO_PENDING, result); 108 if (result == net::OK) { 109 #ifndef USE_TRACING_CACHE_BACKEND 110 *backend_ = created_cache_.Pass(); 111 #else 112 *backend_.reset( 113 new disk_cache::TracingCacheBackend(created_cache_.Pass())); 114 #endif 115 } else { 116 LOG(ERROR) << "Unable to create cache"; 117 created_cache_.reset(); 118 } 119 callback_.Run(result); 120 delete this; 121 } 122 123 // If the initialization of the cache fails, and |force| is true, we will 124 // discard the whole cache and create a new one. 125 void CacheCreator::OnIOComplete(int result) { 126 if (result == net::OK || !force_ || retry_) 127 return DoCallback(result); 128 129 // This is a failure and we are supposed to try again, so delete the object, 130 // delete all the files, and try again. 131 retry_ = true; 132 created_cache_.reset(); 133 if (!disk_cache::DelayedCacheCleanup(path_)) 134 return DoCallback(result); 135 136 // The worker thread will start deleting files soon, but the original folder 137 // is not there anymore... let's create a new set of files. 138 int rv = Run(); 139 DCHECK_EQ(net::ERR_IO_PENDING, rv); 140 } 141 142 } // namespace 143 144 namespace disk_cache { 145 146 int CreateCacheBackend(net::CacheType type, 147 net::BackendType backend_type, 148 const base::FilePath& path, 149 int max_bytes, 150 bool force, base::MessageLoopProxy* thread, 151 net::NetLog* net_log, scoped_ptr<Backend>* backend, 152 const net::CompletionCallback& callback) { 153 DCHECK(!callback.is_null()); 154 if (type == net::MEMORY_CACHE) { 155 *backend = disk_cache::MemBackendImpl::CreateBackend(max_bytes, net_log); 156 return *backend ? net::OK : net::ERR_FAILED; 157 } 158 DCHECK(thread); 159 CacheCreator* creator = new CacheCreator(path, force, max_bytes, type, 160 backend_type, kNone, 161 thread, net_log, backend, callback); 162 return creator->Run(); 163 } 164 165 } // namespace disk_cache 166