• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
CacheCreator(const base::FilePath & path,bool force,int max_bytes,net::CacheType type,net::BackendType backend_type,uint32 flags,base::MessageLoopProxy * thread,net::NetLog * net_log,scoped_ptr<disk_cache::Backend> * backend,const net::CompletionCallback & callback)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 
~CacheCreator()78 CacheCreator::~CacheCreator() {
79 }
80 
Run()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 
DoCallback(int result)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.
OnIOComplete(int result)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 
CreateCacheBackend(net::CacheType type,net::BackendType backend_type,const base::FilePath & path,int max_bytes,bool force,base::MessageLoopProxy * thread,net::NetLog * net_log,scoped_ptr<Backend> * backend,const net::CompletionCallback & callback)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