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