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 17namespace { 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. 22class 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 61CacheCreator::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 85CacheCreator::~CacheCreator() { 86} 87 88int 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 122void 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. 141void 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 160namespace disk_cache { 161 162int 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