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/blockfile/backend_impl.h" 11 #include "net/disk_cache/cache_util.h" 12 #include "net/disk_cache/disk_cache.h" 13 #include "net/disk_cache/memory/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 #if defined(OS_ANDROID) 83 static const bool kSimpleBackendIsDefault = true; 84 #else 85 static const bool kSimpleBackendIsDefault = false; 86 #endif 87 if (backend_type_ == net::CACHE_BACKEND_SIMPLE || 88 (backend_type_ == net::CACHE_BACKEND_DEFAULT && 89 kSimpleBackendIsDefault)) { 90 disk_cache::SimpleBackendImpl* simple_cache = 91 new disk_cache::SimpleBackendImpl(path_, max_bytes_, type_, 92 thread_.get(), net_log_); 93 created_cache_.reset(simple_cache); 94 return simple_cache->Init( 95 base::Bind(&CacheCreator::OnIOComplete, base::Unretained(this))); 96 } 97 98 // Avoid references to blockfile functions on Android to reduce binary size. 99 #if defined(OS_ANDROID) 100 return net::ERR_FAILED; 101 #else 102 disk_cache::BackendImpl* new_cache = 103 new disk_cache::BackendImpl(path_, thread_.get(), net_log_); 104 created_cache_.reset(new_cache); 105 new_cache->SetMaxSize(max_bytes_); 106 new_cache->SetType(type_); 107 new_cache->SetFlags(flags_); 108 int rv = new_cache->Init( 109 base::Bind(&CacheCreator::OnIOComplete, base::Unretained(this))); 110 DCHECK_EQ(net::ERR_IO_PENDING, rv); 111 return rv; 112 #endif 113 } 114 115 void CacheCreator::DoCallback(int result) { 116 DCHECK_NE(net::ERR_IO_PENDING, result); 117 if (result == net::OK) { 118 #ifndef USE_TRACING_CACHE_BACKEND 119 *backend_ = created_cache_.Pass(); 120 #else 121 *backend_.reset( 122 new disk_cache::TracingCacheBackend(created_cache_.Pass())); 123 #endif 124 } else { 125 LOG(ERROR) << "Unable to create cache"; 126 created_cache_.reset(); 127 } 128 callback_.Run(result); 129 delete this; 130 } 131 132 // If the initialization of the cache fails, and |force| is true, we will 133 // discard the whole cache and create a new one. 134 void CacheCreator::OnIOComplete(int result) { 135 if (result == net::OK || !force_ || retry_) 136 return DoCallback(result); 137 138 // This is a failure and we are supposed to try again, so delete the object, 139 // delete all the files, and try again. 140 retry_ = true; 141 created_cache_.reset(); 142 if (!disk_cache::DelayedCacheCleanup(path_)) 143 return DoCallback(result); 144 145 // The worker thread will start deleting files soon, but the original folder 146 // is not there anymore... let's create a new set of files. 147 int rv = Run(); 148 DCHECK_EQ(net::ERR_IO_PENDING, rv); 149 } 150 151 } // namespace 152 153 namespace disk_cache { 154 155 int CreateCacheBackend(net::CacheType type, 156 net::BackendType backend_type, 157 const base::FilePath& path, 158 int max_bytes, 159 bool force, base::MessageLoopProxy* thread, 160 net::NetLog* net_log, scoped_ptr<Backend>* backend, 161 const net::CompletionCallback& callback) { 162 DCHECK(!callback.is_null()); 163 if (type == net::MEMORY_CACHE) { 164 *backend = disk_cache::MemBackendImpl::CreateBackend(max_bytes, net_log); 165 return *backend ? net::OK : net::ERR_FAILED; 166 } 167 DCHECK(thread); 168 CacheCreator* creator = new CacheCreator(path, force, max_bytes, type, 169 backend_type, kNone, 170 thread, net_log, backend, callback); 171 return creator->Run(); 172 } 173 174 } // namespace disk_cache 175