OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/browser/service_worker/service_worker_cache_storage.h" | 5 #include "content/browser/service_worker/service_worker_cache_storage.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 | 8 |
9 #include "base/file_util.h" | 9 #include "base/file_util.h" |
10 #include "base/files/memory_mapped_file.h" | 10 #include "base/files/memory_mapped_file.h" |
11 #include "base/sha1.h" | 11 #include "base/sha1.h" |
12 #include "base/strings/string_number_conversions.h" | 12 #include "base/strings/string_number_conversions.h" |
13 #include "base/strings/string_util.h" | 13 #include "base/strings/string_util.h" |
14 #include "content/browser/service_worker/service_worker_cache.h" | 14 #include "content/browser/service_worker/service_worker_cache.h" |
15 #include "content/browser/service_worker/service_worker_cache.pb.h" | 15 #include "content/browser/service_worker/service_worker_cache.pb.h" |
16 #include "content/public/browser/browser_thread.h" | 16 #include "content/public/browser/browser_thread.h" |
17 #include "net/base/directory_lister.h" | 17 #include "net/base/directory_lister.h" |
18 #include "net/base/net_errors.h" | |
18 | 19 |
19 namespace content { | 20 namespace content { |
20 | 21 |
21 // Handles the loading and clean up of ServiceWorkerCache objects. | 22 // Handles the loading and clean up of ServiceWorkerCache objects. |
22 class ServiceWorkerCacheStorage::CacheLoader { | 23 class ServiceWorkerCacheStorage::CacheLoader { |
23 public: | 24 public: |
25 typedef base::Callback<void(ServiceWorkerCache*)> CacheCallback; | |
26 typedef base::Callback<void(bool)> BoolCallback; | |
27 typedef base::Callback<void(scoped_ptr<std::vector<std::string> >)> | |
28 StringsCallback; | |
29 | |
30 explicit CacheLoader(base::SequencedTaskRunner* cache_task_runner) | |
31 : cache_task_runner_(cache_task_runner) {} | |
32 | |
24 virtual ~CacheLoader() {}; | 33 virtual ~CacheLoader() {}; |
25 virtual ServiceWorkerCache* LoadCache(const std::string& cache_name) = 0; | 34 |
26 // Creates a new cache, deleting any pre-existing cache of the same name. | 35 // Loads the given cache_name, the cache is NULL if it fails. If the cache |
27 virtual ServiceWorkerCache* CreateCache(const std::string& cache_name) = 0; | 36 // doesn't exist a new one is created. |
28 virtual bool CleanUpDeletedCache(const std::string& key) = 0; | 37 virtual void LoadCache(const std::string& cache_name, |
29 virtual bool WriteIndex(CacheMap* caches) = 0; | 38 const CacheCallback& callback) = 0; |
30 virtual void LoadIndex(std::vector<std::string>* cache_names) = 0; | 39 |
40 // Deletes any pre-existing cache of the same name and then loads it. | |
41 virtual void CreateCache(const std::string& cache_name, | |
42 const CacheCallback& callback) = 0; | |
43 | |
44 // After the backend has been deleted, do any extra house keeping such as | |
45 // removing the cache's directory. | |
46 virtual void CleanUpDeletedCache(const std::string& key, | |
47 const BoolCallback& callback) = 0; | |
48 | |
49 // Writes the cache names to disk if applicable. | |
50 virtual void WriteIndex(CacheMap* caches, const BoolCallback& callback) = 0; | |
51 | |
52 // Loads the cache names from disk if applicable. | |
53 virtual void LoadIndex(scoped_ptr<std::vector<std::string> > cache_names, | |
54 const StringsCallback& callback) = 0; | |
55 | |
56 protected: | |
57 virtual void LoadCacheImpl(const std::string&) {} | |
58 scoped_refptr<base::SequencedTaskRunner> cache_task_runner_; | |
31 }; | 59 }; |
32 | 60 |
33 class ServiceWorkerCacheStorage::MemoryLoader | 61 class ServiceWorkerCacheStorage::MemoryLoader |
34 : public ServiceWorkerCacheStorage::CacheLoader { | 62 : public ServiceWorkerCacheStorage::CacheLoader { |
35 public: | 63 public: |
36 virtual content::ServiceWorkerCache* LoadCache( | 64 explicit MemoryLoader(base::SequencedTaskRunner* cache_task_runner) |
37 const std::string& cache_name) OVERRIDE { | 65 : CacheLoader(cache_task_runner) {} |
66 virtual void LoadCache(const std::string& cache_name, | |
67 const CacheCallback& callback) OVERRIDE { | |
38 NOTREACHED(); | 68 NOTREACHED(); |
39 return NULL; | 69 } |
40 } | 70 |
41 | 71 virtual void CreateCache(const std::string& cache_name, |
42 virtual ServiceWorkerCache* CreateCache( | 72 const CacheCallback& callback) OVERRIDE { |
43 const std::string& cache_name) OVERRIDE { | 73 ServiceWorkerCache* cache = |
44 return ServiceWorkerCache::CreateMemoryCache(cache_name); | 74 ServiceWorkerCache::CreateMemoryCache(cache_name); |
45 } | 75 callback.Run(cache); |
46 | 76 } |
47 virtual bool CleanUpDeletedCache(const std::string& cache_name) OVERRIDE { | 77 |
48 return true; | 78 virtual void CleanUpDeletedCache(const std::string& cache_name, |
49 } | 79 const BoolCallback& callback) OVERRIDE { |
50 | 80 callback.Run(true); |
51 virtual bool WriteIndex(CacheMap* caches) OVERRIDE { return false; } | 81 } |
52 | 82 |
53 virtual void LoadIndex(std::vector<std::string>* cache_names) OVERRIDE { | 83 virtual void WriteIndex(CacheMap* caches, |
54 return; | 84 const BoolCallback& callback) OVERRIDE { |
85 callback.Run(false); | |
86 } | |
87 | |
88 virtual void LoadIndex(scoped_ptr<std::vector<std::string> > cache_names, | |
89 const StringsCallback& callback) OVERRIDE { | |
90 callback.Run(cache_names.Pass()); | |
55 } | 91 } |
56 }; | 92 }; |
57 | 93 |
58 class ServiceWorkerCacheStorage::SimpleCacheLoader | 94 class ServiceWorkerCacheStorage::SimpleCacheLoader |
59 : public ServiceWorkerCacheStorage::CacheLoader { | 95 : public ServiceWorkerCacheStorage::CacheLoader { |
60 public: | 96 public: |
61 explicit SimpleCacheLoader(const base::FilePath& origin_path) | 97 SimpleCacheLoader(const base::FilePath& origin_path, |
62 : origin_path_(origin_path) {} | 98 base::SequencedTaskRunner* cache_task_runner) |
63 | 99 : CacheLoader(cache_task_runner), origin_path_(origin_path) {} |
64 virtual ServiceWorkerCache* LoadCache( | 100 |
65 const std::string& cache_name) OVERRIDE { | 101 virtual void LoadCache(const std::string& cache_name, |
66 base::CreateDirectory(CreatePersistentCachePath(origin_path_, cache_name)); | 102 const CacheCallback& callback) OVERRIDE { |
67 return ServiceWorkerCache::CreatePersistentCache( | 103 DCHECK(thread_checker_.CalledOnValidThread()); |
104 | |
105 // 1. Create the cache's directory if necessary. (LoadCreateDirectory) | |
106 // 2. Create the cache object. (LoadDidCreateDirectory) | |
107 | |
108 cache_task_runner_->PostTask( | |
109 FROM_HERE, | |
110 base::Bind(&SimpleCacheLoader::LoadCreateDirectoryInPool, | |
111 base::Unretained(this), // should be weak_ptr? | |
michaeln
2014/08/11 19:30:17
unretained is no good... deriving CacheLoader from
jkarlin
2014/08/12 14:55:02
Done.
| |
112 CreatePersistentCachePath(origin_path_, cache_name), | |
113 cache_name, | |
114 callback, | |
115 base::MessageLoopProxy::current())); | |
116 } | |
117 | |
118 void LoadCreateDirectoryInPool( | |
119 const base::FilePath& path, | |
120 const std::string& cache_name, | |
121 const CacheCallback& callback, | |
122 scoped_refptr<base::MessageLoopProxy> original_loop) { | |
123 bool rv = base::CreateDirectory(path); | |
124 original_loop->PostTask( | |
125 FROM_HERE, | |
126 base::Bind(&SimpleCacheLoader::LoadDidCreateDirectory, | |
127 base::Unretained(this), | |
128 cache_name, | |
129 callback, | |
130 rv)); | |
131 } | |
132 | |
133 void LoadDidCreateDirectory(const std::string& cache_name, | |
134 const CacheCallback& callback, | |
135 bool dir_rv) { | |
136 DCHECK(thread_checker_.CalledOnValidThread()); | |
137 | |
138 if (!dir_rv) { | |
139 callback.Run(NULL); | |
140 return; | |
141 } | |
142 ServiceWorkerCache* cache = ServiceWorkerCache::CreatePersistentCache( | |
68 CreatePersistentCachePath(origin_path_, cache_name), cache_name); | 143 CreatePersistentCachePath(origin_path_, cache_name), cache_name); |
69 } | 144 callback.Run(cache); |
70 | 145 } |
71 virtual ServiceWorkerCache* CreateCache( | 146 |
72 const std::string& cache_name) OVERRIDE { | 147 virtual void CreateCache(const std::string& cache_name, |
148 const CacheCallback& callback) OVERRIDE { | |
149 DCHECK(thread_checker_.CalledOnValidThread()); | |
150 | |
151 // 1. Delete the cache's directory if it exists. (CreateDeleteFiles) | |
michaeln
2014/08/11 20:30:14
(CreateDeleteFiles) s/b (CreateCacheDeleteFilesInP
jkarlin
2014/08/12 14:55:03
Done.
| |
152 // 2. Load the cache. (LoadCache) | |
153 | |
73 base::FilePath cache_path = | 154 base::FilePath cache_path = |
74 CreatePersistentCachePath(origin_path_, cache_name); | 155 CreatePersistentCachePath(origin_path_, cache_name); |
75 if (base::PathExists(cache_path)) | 156 |
76 base::DeleteFile(cache_path, /* recursive */ true); | 157 cache_task_runner_->PostTask( |
77 return LoadCache(cache_name); | 158 FROM_HERE, |
78 } | 159 base::Bind(&SimpleCacheLoader::CreateCacheDeleteFilesInPool, |
79 | 160 base::Unretained(this), // should be weak_ptr? |
80 virtual bool CleanUpDeletedCache(const std::string& cache_name) OVERRIDE { | 161 cache_path, |
81 return base::DeleteFile(CreatePersistentCachePath(origin_path_, cache_name), | 162 cache_name, |
82 true); | 163 callback, |
83 } | 164 base::MessageLoopProxy::current())); |
84 | 165 } |
85 virtual bool WriteIndex(CacheMap* caches) OVERRIDE { | 166 |
167 void CreateCacheDeleteFilesInPool( | |
168 const base::FilePath& cache_path, | |
169 const std::string& cache_name, | |
170 const CacheCallback& callback, | |
171 scoped_refptr<base::MessageLoopProxy> original_loop) { | |
michaeln
2014/08/11 20:30:14
maybe add DCHECKS for cache_task_runner_.RunTasksO
jkarlin
2014/08/12 14:55:03
Great idea, thanks!
| |
172 base::FilePath path(cache_path); | |
173 if (base::PathExists(path)) | |
174 base::DeleteFile(path, /* recursive */ true); | |
175 original_loop->PostTask(FROM_HERE, | |
176 base::Bind(&SimpleCacheLoader::LoadCache, | |
michaeln
2014/08/11 20:30:14
This operation take multiple hops to the cache_thr
jkarlin
2014/08/12 14:55:03
Done.
| |
177 base::Unretained(this), | |
178 cache_name, | |
179 callback)); | |
180 } | |
181 | |
182 virtual void CleanUpDeletedCache(const std::string& cache_name, | |
183 const BoolCallback& callback) OVERRIDE { | |
184 DCHECK(thread_checker_.CalledOnValidThread()); | |
185 | |
186 // 1. Delete the cache's directory. (CleanUpDeleteCacheDir) | |
187 | |
188 base::FilePath cache_path = | |
189 CreatePersistentCachePath(origin_path_, cache_name); | |
190 cache_task_runner_->PostTask( | |
191 FROM_HERE, | |
192 base::Bind(&SimpleCacheLoader::CleanUpDeleteCacheDirInPool, | |
193 base::Unretained(this), | |
194 cache_path, | |
195 callback, | |
196 base::MessageLoopProxy::current())); | |
197 } | |
198 | |
199 void CleanUpDeleteCacheDirInPool( | |
200 const base::FilePath& cache_path, | |
201 const BoolCallback& callback, | |
202 scoped_refptr<base::MessageLoopProxy> original_loop) { | |
michaeln
2014/08/11 20:30:14
can these be const refs (or a rawptr) to the Messa
jkarlin
2014/08/12 14:55:02
Thanks! Done.
| |
203 bool rv = base::DeleteFile(cache_path, true); | |
204 original_loop->PostTask(FROM_HERE, base::Bind(callback, rv)); | |
205 } | |
206 | |
207 virtual void WriteIndex(CacheMap* caches, | |
208 const BoolCallback& callback) OVERRIDE { | |
209 DCHECK(thread_checker_.CalledOnValidThread()); | |
210 | |
211 // 1. Create the index file as a string. (WriteIndex) | |
212 // 2. Write the file to disk. (WriteIndexWriteToFile) | |
213 | |
86 ServiceWorkerCacheStorageIndex index; | 214 ServiceWorkerCacheStorageIndex index; |
87 | 215 |
88 for (CacheMap::const_iterator iter(caches); !iter.IsAtEnd(); | 216 for (CacheMap::const_iterator iter(caches); !iter.IsAtEnd(); |
89 iter.Advance()) { | 217 iter.Advance()) { |
90 const ServiceWorkerCache* cache = iter.GetCurrentValue(); | 218 const ServiceWorkerCache* cache = iter.GetCurrentValue(); |
91 ServiceWorkerCacheStorageIndex::Cache* index_cache = index.add_cache(); | 219 ServiceWorkerCacheStorageIndex::Cache* index_cache = index.add_cache(); |
92 index_cache->set_name(cache->name()); | 220 index_cache->set_name(cache->name()); |
93 index_cache->set_size(0); // TODO(jkarlin): Make this real. | 221 index_cache->set_size(0); // TODO(jkarlin): Make this real. |
94 } | 222 } |
95 | 223 |
96 std::string serialized; | 224 std::string serialized; |
97 bool success = index.SerializeToString(&serialized); | 225 bool success = index.SerializeToString(&serialized); |
98 DCHECK(success); | 226 DCHECK(success); |
99 | 227 |
100 base::FilePath tmp_path = origin_path_.AppendASCII("index.txt.tmp"); | 228 base::FilePath tmp_path = origin_path_.AppendASCII("index.txt.tmp"); |
101 base::FilePath index_path = origin_path_.AppendASCII("index.txt"); | 229 base::FilePath index_path = origin_path_.AppendASCII("index.txt"); |
102 | 230 |
103 int bytes_written = | 231 cache_task_runner_->PostTask( |
104 base::WriteFile(tmp_path, serialized.c_str(), serialized.size()); | 232 FROM_HERE, |
105 if (bytes_written != implicit_cast<int>(serialized.size())) { | 233 base::Bind(&SimpleCacheLoader::WriteIndexWriteToFileInPool, |
234 base::Unretained(this), // should be weak? | |
235 tmp_path, | |
236 index_path, | |
237 serialized, | |
238 caches, | |
239 callback, | |
240 base::MessageLoopProxy::current())); | |
241 } | |
242 | |
243 void WriteIndexWriteToFileInPool( | |
244 const base::FilePath& tmp_path, | |
245 const base::FilePath& index_path, | |
246 const std::string& data, | |
247 CacheMap* caches, | |
248 const BoolCallback& callback, | |
249 scoped_refptr<base::MessageLoopProxy> original_loop) { | |
250 int bytes_written = base::WriteFile(tmp_path, data.c_str(), data.size()); | |
251 if (bytes_written != implicit_cast<int>(data.size())) { | |
106 base::DeleteFile(tmp_path, /* recursive */ false); | 252 base::DeleteFile(tmp_path, /* recursive */ false); |
107 return false; | 253 original_loop->PostTask(FROM_HERE, base::Bind(callback, false)); |
108 } | 254 } |
109 | 255 |
110 // Atomically rename the temporary index file to become the real one. | 256 // Atomically rename the temporary index file to become the real one. |
111 return base::ReplaceFile(tmp_path, index_path, NULL); | 257 bool rv = base::ReplaceFile(tmp_path, index_path, NULL); |
258 original_loop->PostTask(FROM_HERE, base::Bind(callback, rv)); | |
112 } | 259 } |
113 | 260 |
114 virtual void LoadIndex(std::vector<std::string>* names) OVERRIDE { | 261 virtual void LoadIndex(scoped_ptr<std::vector<std::string> > names, |
262 const StringsCallback& callback) OVERRIDE { | |
263 DCHECK(thread_checker_.CalledOnValidThread()); | |
264 | |
265 // 1. Read the file from disk. (LoadIndexReadFile) | |
266 // 2. Parse file and return the names of the caches (LoadIndexDidReadFile) | |
267 | |
115 base::FilePath index_path = origin_path_.AppendASCII("index.txt"); | 268 base::FilePath index_path = origin_path_.AppendASCII("index.txt"); |
116 | 269 |
117 std::string serialized; | 270 cache_task_runner_->PostTask( |
118 if (!base::ReadFileToString(index_path, &serialized)) | 271 FROM_HERE, |
119 return; | 272 base::Bind(&SimpleCacheLoader::LoadIndexReadFileInPool, |
273 base::Unretained(this), | |
274 index_path, | |
275 base::Passed(names.Pass()), | |
276 callback, | |
277 base::MessageLoopProxy::current())); | |
278 } | |
279 | |
280 void LoadIndexReadFileInPool( | |
281 const base::FilePath& index_path, | |
282 scoped_ptr<std::vector<std::string> > names, | |
283 const StringsCallback& callback, | |
284 scoped_refptr<base::MessageLoopProxy> original_loop) { | |
285 std::string body; | |
286 base::ReadFileToString(index_path, &body); | |
287 | |
288 original_loop->PostTask(FROM_HERE, | |
289 base::Bind(&SimpleCacheLoader::LoadIndexDidReadFile, | |
290 base::Unretained(this), | |
291 base::Passed(names.Pass()), | |
292 callback, | |
293 body)); | |
294 } | |
295 | |
296 void LoadIndexDidReadFile(scoped_ptr<std::vector<std::string> > names, | |
297 const StringsCallback& callback, | |
298 const std::string& serialized) { | |
299 DCHECK(thread_checker_.CalledOnValidThread()); | |
120 | 300 |
121 ServiceWorkerCacheStorageIndex index; | 301 ServiceWorkerCacheStorageIndex index; |
122 index.ParseFromString(serialized); | 302 index.ParseFromString(serialized); |
123 | 303 |
124 for (int i = 0, max = index.cache_size(); i < max; ++i) { | 304 for (int i = 0, max = index.cache_size(); i < max; ++i) { |
125 const ServiceWorkerCacheStorageIndex::Cache& cache = index.cache(i); | 305 const ServiceWorkerCacheStorageIndex::Cache& cache = index.cache(i); |
126 names->push_back(cache.name()); | 306 names->push_back(cache.name()); |
127 } | 307 } |
128 | 308 |
129 // TODO(jkarlin): Delete caches that are in the directory and not returned | 309 // TODO(jkarlin): Delete caches that are in the directory and not returned |
130 // in LoadIndex. | 310 // in LoadIndex. |
131 return; | 311 callback.Run(names.Pass()); |
132 } | 312 } |
133 | 313 |
134 private: | 314 private: |
135 std::string HexedHash(const std::string& value) { | 315 std::string HexedHash(const std::string& value) { |
136 std::string value_hash = base::SHA1HashString(value); | 316 std::string value_hash = base::SHA1HashString(value); |
137 std::string valued_hexed_hash = base::StringToLowerASCII( | 317 std::string valued_hexed_hash = base::StringToLowerASCII( |
138 base::HexEncode(value_hash.c_str(), value_hash.length())); | 318 base::HexEncode(value_hash.c_str(), value_hash.length())); |
139 return valued_hexed_hash; | 319 return valued_hexed_hash; |
140 } | 320 } |
141 | 321 |
142 base::FilePath CreatePersistentCachePath(const base::FilePath& origin_path, | 322 base::FilePath CreatePersistentCachePath(const base::FilePath& origin_path, |
143 const std::string& cache_name) { | 323 const std::string& cache_name) { |
144 return origin_path.AppendASCII(HexedHash(cache_name)); | 324 return origin_path.AppendASCII(HexedHash(cache_name)); |
145 } | 325 } |
146 | 326 |
327 base::ThreadChecker thread_checker_; | |
147 const base::FilePath origin_path_; | 328 const base::FilePath origin_path_; |
148 }; | 329 }; |
149 | 330 |
150 ServiceWorkerCacheStorage::ServiceWorkerCacheStorage( | 331 ServiceWorkerCacheStorage::ServiceWorkerCacheStorage( |
151 const base::FilePath& path, | 332 const base::FilePath& path, |
152 bool memory_only, | 333 bool memory_only, |
153 const scoped_refptr<base::MessageLoopProxy>& callback_loop) | 334 base::SequencedTaskRunner* cache_task_runner) |
154 : initialized_(false), origin_path_(path), callback_loop_(callback_loop) { | 335 : initialized_(false), |
336 origin_path_(path), | |
337 cache_task_runner_(cache_task_runner) { | |
155 if (memory_only) | 338 if (memory_only) |
156 cache_loader_.reset(new MemoryLoader()); | 339 cache_loader_.reset(new MemoryLoader(cache_task_runner_)); |
157 else | 340 else |
158 cache_loader_.reset(new SimpleCacheLoader(origin_path_)); | 341 cache_loader_.reset( |
342 new SimpleCacheLoader(origin_path_, cache_task_runner_)); | |
159 } | 343 } |
160 | 344 |
161 ServiceWorkerCacheStorage::~ServiceWorkerCacheStorage() { | 345 ServiceWorkerCacheStorage::~ServiceWorkerCacheStorage() { |
162 } | 346 } |
163 | 347 |
164 void ServiceWorkerCacheStorage::CreateCache( | 348 void ServiceWorkerCacheStorage::CreateCache( |
165 const std::string& cache_name, | 349 const std::string& cache_name, |
166 const CacheAndErrorCallback& callback) { | 350 const CacheAndErrorCallback& callback) { |
167 LazyInit(); | 351 if (!initialized_) { |
352 LazyInit(base::Bind(&ServiceWorkerCacheStorage::CreateCache, | |
353 base::Unretained(this), | |
354 cache_name, | |
355 callback)); | |
356 return; | |
357 } | |
168 | 358 |
169 if (cache_name.empty()) { | 359 if (cache_name.empty()) { |
170 callback_loop_->PostTask( | 360 callback.Run(0, CACHE_STORAGE_ERROR_EMPTY_KEY); |
171 FROM_HERE, base::Bind(callback, 0, CACHE_STORAGE_ERROR_EMPTY_KEY)); | |
172 return; | 361 return; |
173 } | 362 } |
174 | 363 |
175 if (GetLoadedCache(cache_name)) { | 364 if (GetLoadedCache(cache_name)) { |
176 callback_loop_->PostTask( | 365 callback.Run(0, CACHE_STORAGE_ERROR_EXISTS); |
177 FROM_HERE, base::Bind(callback, 0, CACHE_STORAGE_ERROR_EXISTS)); | |
178 return; | 366 return; |
179 } | 367 } |
180 | 368 |
181 ServiceWorkerCache* cache = cache_loader_->CreateCache(cache_name); | 369 cache_loader_->CreateCache( |
182 | 370 cache_name, |
183 if (!cache) { | 371 base::Bind(&ServiceWorkerCacheStorage::CreateCacheDidCreateCache, |
184 callback_loop_->PostTask( | |
185 FROM_HERE, base::Bind(callback, 0, CACHE_STORAGE_ERROR_STORAGE)); | |
186 return; | |
187 } | |
188 | |
189 InitCache(cache); | |
190 | |
191 cache_loader_->WriteIndex(&cache_map_); | |
192 | |
193 cache->CreateBackend( | |
194 base::Bind(&ServiceWorkerCacheStorage::InitializeCacheCallback, | |
195 base::Unretained(this), | 372 base::Unretained(this), |
michaeln
2014/08/11 19:30:17
use of unretained here and in other callbacks can
jkarlin
2014/08/12 14:55:03
Done.
| |
196 cache, | 373 cache_name, |
197 callback)); | 374 callback)); |
198 } | 375 } |
199 | 376 |
200 void ServiceWorkerCacheStorage::GetCache( | 377 void ServiceWorkerCacheStorage::GetCache( |
201 const std::string& cache_name, | 378 const std::string& cache_name, |
202 const CacheAndErrorCallback& callback) { | 379 const CacheAndErrorCallback& callback) { |
203 LazyInit(); | 380 DCHECK(thread_checker_.CalledOnValidThread()); |
381 | |
382 if (!initialized_) { | |
383 LazyInit(base::Bind(&ServiceWorkerCacheStorage::GetCache, | |
384 base::Unretained(this), | |
385 cache_name, | |
386 callback)); | |
387 return; | |
388 } | |
204 | 389 |
205 if (cache_name.empty()) { | 390 if (cache_name.empty()) { |
206 callback_loop_->PostTask( | 391 callback.Run(0, CACHE_STORAGE_ERROR_EMPTY_KEY); |
207 FROM_HERE, base::Bind(callback, 0, CACHE_STORAGE_ERROR_EMPTY_KEY)); | |
208 return; | 392 return; |
209 } | 393 } |
210 | 394 |
211 ServiceWorkerCache* cache = GetLoadedCache(cache_name); | 395 ServiceWorkerCache* cache = GetLoadedCache(cache_name); |
212 if (!cache) { | 396 if (!cache) { |
213 callback_loop_->PostTask( | 397 callback.Run(0, CACHE_STORAGE_ERROR_NOT_FOUND); |
214 FROM_HERE, base::Bind(callback, 0, CACHE_STORAGE_ERROR_NOT_FOUND)); | |
215 return; | 398 return; |
216 } | 399 } |
217 | 400 |
218 cache->CreateBackend( | 401 cache->CreateBackend(base::Bind(&ServiceWorkerCacheStorage::DidCreateBackend, |
219 base::Bind(&ServiceWorkerCacheStorage::InitializeCacheCallback, | 402 base::Unretained(this), |
220 base::Unretained(this), | 403 cache, |
221 cache, | 404 callback)); |
222 callback)); | |
223 } | 405 } |
224 | 406 |
225 void ServiceWorkerCacheStorage::HasCache(const std::string& cache_name, | 407 void ServiceWorkerCacheStorage::HasCache(const std::string& cache_name, |
226 const BoolAndErrorCallback& callback) { | 408 const BoolAndErrorCallback& callback) { |
227 LazyInit(); | 409 DCHECK(thread_checker_.CalledOnValidThread()); |
410 | |
411 if (!initialized_) { | |
412 LazyInit(base::Bind(&ServiceWorkerCacheStorage::HasCache, | |
413 base::Unretained(this), | |
414 cache_name, | |
415 callback)); | |
416 return; | |
417 } | |
228 | 418 |
229 if (cache_name.empty()) { | 419 if (cache_name.empty()) { |
230 callback_loop_->PostTask( | 420 callback.Run(false, CACHE_STORAGE_ERROR_EMPTY_KEY); |
231 FROM_HERE, base::Bind(callback, false, CACHE_STORAGE_ERROR_EMPTY_KEY)); | |
232 return; | 421 return; |
233 } | 422 } |
234 | 423 |
235 bool has_cache = GetLoadedCache(cache_name) != NULL; | 424 bool has_cache = GetLoadedCache(cache_name) != NULL; |
236 | 425 |
237 callback_loop_->PostTask( | 426 callback.Run(has_cache, CACHE_STORAGE_ERROR_NO_ERROR); |
238 FROM_HERE, | |
239 base::Bind( | |
240 callback, has_cache, CACHE_STORAGE_ERROR_NO_ERROR)); | |
241 } | 427 } |
242 | 428 |
243 void ServiceWorkerCacheStorage::DeleteCache( | 429 void ServiceWorkerCacheStorage::DeleteCache( |
244 const std::string& cache_name, | 430 const std::string& cache_name, |
245 const BoolAndErrorCallback& callback) { | 431 const BoolAndErrorCallback& callback) { |
246 LazyInit(); | 432 DCHECK(thread_checker_.CalledOnValidThread()); |
433 | |
434 if (!initialized_) { | |
435 LazyInit(base::Bind(&ServiceWorkerCacheStorage::DeleteCache, | |
436 base::Unretained(this), | |
437 cache_name, | |
438 callback)); | |
439 return; | |
440 } | |
247 | 441 |
248 if (cache_name.empty()) { | 442 if (cache_name.empty()) { |
249 callback_loop_->PostTask( | 443 callback.Run(false, CACHE_STORAGE_ERROR_EMPTY_KEY); |
250 FROM_HERE, base::Bind(callback, false, CACHE_STORAGE_ERROR_EMPTY_KEY)); | |
251 return; | 444 return; |
252 } | 445 } |
253 | 446 |
254 ServiceWorkerCache* cache = GetLoadedCache(cache_name); | 447 ServiceWorkerCache* cache = GetLoadedCache(cache_name); |
255 if (!cache) { | 448 if (!cache) { |
256 callback_loop_->PostTask( | 449 callback.Run(false, CACHE_STORAGE_ERROR_NOT_FOUND); |
257 FROM_HERE, base::Bind(callback, false, CACHE_STORAGE_ERROR_NOT_FOUND)); | |
258 return; | 450 return; |
259 } | 451 } |
260 | 452 |
261 name_map_.erase(cache_name); | 453 name_map_.erase(cache_name); |
262 cache_map_.Remove(cache->id()); // deletes cache | 454 cache_map_.Remove(cache->id()); // deletes cache |
263 | 455 |
264 cache_loader_->WriteIndex(&cache_map_); // Update the index. | 456 // Update the Index |
265 | 457 cache_loader_->WriteIndex( |
266 cache_loader_->CleanUpDeletedCache(cache_name); | 458 &cache_map_, |
267 | 459 base::Bind(&ServiceWorkerCacheStorage::DeleteCacheDidWriteIndex, |
268 callback_loop_->PostTask( | 460 base::Unretained(this), |
269 FROM_HERE, base::Bind(callback, true, CACHE_STORAGE_ERROR_NO_ERROR)); | 461 cache_name, |
462 callback)); | |
270 } | 463 } |
271 | 464 |
272 void ServiceWorkerCacheStorage::EnumerateCaches( | 465 void ServiceWorkerCacheStorage::EnumerateCaches( |
273 const StringsAndErrorCallback& callback) { | 466 const StringsAndErrorCallback& callback) { |
274 LazyInit(); | 467 DCHECK(thread_checker_.CalledOnValidThread()); |
468 | |
469 if (!initialized_) { | |
470 LazyInit(base::Bind(&ServiceWorkerCacheStorage::EnumerateCaches, | |
471 base::Unretained(this), | |
472 callback)); | |
473 return; | |
474 } | |
275 | 475 |
276 std::vector<std::string> names; | 476 std::vector<std::string> names; |
277 for (NameMap::const_iterator it = name_map_.begin(); it != name_map_.end(); | 477 for (NameMap::const_iterator it = name_map_.begin(); it != name_map_.end(); |
278 ++it) { | 478 ++it) { |
279 names.push_back(it->first); | 479 names.push_back(it->first); |
280 } | 480 } |
281 | 481 |
282 callback_loop_->PostTask( | 482 callback.Run(names, CACHE_STORAGE_ERROR_NO_ERROR); |
283 FROM_HERE, base::Bind(callback, names, CACHE_STORAGE_ERROR_NO_ERROR)); | |
284 } | 483 } |
285 | 484 |
286 void ServiceWorkerCacheStorage::InitializeCacheCallback( | 485 void ServiceWorkerCacheStorage::DidCreateBackend( |
287 const ServiceWorkerCache* cache, | 486 const ServiceWorkerCache* cache, |
288 const CacheAndErrorCallback& callback, | 487 const CacheAndErrorCallback& callback, |
289 bool success) { | 488 bool success) { |
489 DCHECK(thread_checker_.CalledOnValidThread()); | |
490 | |
290 if (!success) { | 491 if (!success) { |
291 // TODO(jkarlin): This should delete the directory and try again in case | 492 // TODO(jkarlin): This should delete the directory and try again in case |
292 // the cache is simply corrupt. | 493 // the cache is simply corrupt. |
293 callback_loop_->PostTask( | 494 callback.Run(0, CACHE_STORAGE_ERROR_STORAGE); |
294 FROM_HERE, base::Bind(callback, 0, CACHE_STORAGE_ERROR_STORAGE)); | |
295 return; | 495 return; |
296 } | 496 } |
297 callback_loop_->PostTask( | 497 callback.Run(cache->id(), CACHE_STORAGE_ERROR_NO_ERROR); |
298 FROM_HERE, | |
299 base::Bind(callback, cache->id(), CACHE_STORAGE_ERROR_NO_ERROR)); | |
300 } | 498 } |
301 | 499 |
302 // Init is run lazily so that it is called on the proper MessageLoop. | 500 // Init is run lazily so that it is called on the proper MessageLoop. |
303 void ServiceWorkerCacheStorage::LazyInit() { | 501 void ServiceWorkerCacheStorage::LazyInit(const base::Closure& callback) { |
304 if (initialized_) | 502 DCHECK(thread_checker_.CalledOnValidThread()); |
503 DCHECK(!initialized_); | |
504 | |
505 init_callbacks_.push_back(callback); | |
506 | |
507 // If this isn't the first call to LazyInit then return as the initialization | |
508 // has already started. | |
509 if (init_callbacks_.size() > 1u) | |
305 return; | 510 return; |
306 | 511 |
307 std::vector<std::string> indexed_cache_names; | 512 // 1. Get the list of cache names (async call) |
308 cache_loader_->LoadIndex(&indexed_cache_names); | 513 // 2. For each cache name, load the cache (async call) |
514 // 3. Once each load is complete, update the map variables. | |
515 // 4. Call the list of waiting callbacks. | |
309 | 516 |
310 for (std::vector<std::string>::const_iterator it = | 517 scoped_ptr<std::vector<std::string> > indexed_cache_names( |
311 indexed_cache_names.begin(); | 518 new std::vector<std::string>()); |
312 it != indexed_cache_names.end(); | 519 |
313 ++it) { | 520 cache_loader_->LoadIndex( |
314 ServiceWorkerCache* cache = cache_loader_->LoadCache(*it); | 521 indexed_cache_names.Pass(), |
315 InitCache(cache); | 522 base::Bind(&ServiceWorkerCacheStorage::LazyInitDidLoadIndex, |
316 } | 523 base::Unretained(this), |
317 initialized_ = true; | 524 callback)); |
318 } | 525 } |
319 | 526 |
320 void ServiceWorkerCacheStorage::InitCache(ServiceWorkerCache* cache) { | 527 void ServiceWorkerCacheStorage::LazyInitDidLoadIndex( |
528 const base::Closure& callback, | |
529 scoped_ptr<std::vector<std::string> > indexed_cache_names) { | |
530 DCHECK(thread_checker_.CalledOnValidThread()); | |
531 | |
532 if (indexed_cache_names->empty()) { | |
533 LazyInitDone(); | |
534 return; | |
535 } | |
536 | |
537 std::vector<std::string>::const_iterator iter = indexed_cache_names->begin(); | |
538 std::vector<std::string>::const_iterator iter_next = iter + 1; | |
539 | |
540 cache_loader_->LoadCache( | |
541 *iter, | |
542 base::Bind(&ServiceWorkerCacheStorage::LazyInitIterateAndLoadCacheName, | |
543 base::Unretained(this), | |
544 callback, | |
545 base::Passed(indexed_cache_names.Pass()), | |
546 iter_next)); | |
547 } | |
548 | |
549 void ServiceWorkerCacheStorage::LazyInitIterateAndLoadCacheName( | |
550 const base::Closure& callback, | |
551 scoped_ptr<std::vector<std::string> > indexed_cache_names, | |
552 std::vector<std::string>::const_iterator iter, | |
553 ServiceWorkerCache* cache) { | |
554 DCHECK(thread_checker_.CalledOnValidThread()); | |
555 | |
556 if (cache) | |
557 AddCacheToMaps(cache); | |
558 | |
559 if (iter == indexed_cache_names->end()) { | |
560 LazyInitDone(); | |
561 return; | |
562 } | |
563 | |
564 std::vector<std::string>::const_iterator iter_next = iter + 1; | |
565 cache_loader_->LoadCache( | |
566 *iter, | |
567 base::Bind(&ServiceWorkerCacheStorage::LazyInitIterateAndLoadCacheName, | |
568 base::Unretained(this), | |
569 callback, | |
570 base::Passed(indexed_cache_names.Pass()), | |
571 iter_next)); | |
572 } | |
573 | |
574 void ServiceWorkerCacheStorage::LazyInitDone() { | |
575 initialized_ = true; | |
576 for (std::vector<base::Closure>::iterator it = init_callbacks_.begin(); | |
577 it != init_callbacks_.end(); | |
578 ++it) { | |
579 it->Run(); | |
580 } | |
581 init_callbacks_.clear(); | |
582 } | |
583 | |
584 void ServiceWorkerCacheStorage::AddCacheToMaps(ServiceWorkerCache* cache) { | |
585 DCHECK(thread_checker_.CalledOnValidThread()); | |
586 | |
321 CacheID id = cache_map_.Add(cache); | 587 CacheID id = cache_map_.Add(cache); |
322 name_map_.insert(std::make_pair(cache->name(), id)); | 588 name_map_.insert(std::make_pair(cache->name(), id)); |
323 cache->set_id(id); | 589 cache->set_id(id); |
324 } | 590 } |
325 | 591 |
592 void ServiceWorkerCacheStorage::CreateCacheDidCreateCache( | |
593 const std::string& cache_name, | |
594 const CacheAndErrorCallback& callback, | |
595 ServiceWorkerCache* cache) { | |
596 DCHECK(thread_checker_.CalledOnValidThread()); | |
597 | |
598 if (!cache) { | |
599 callback.Run(0, CACHE_STORAGE_ERROR_STORAGE); | |
600 return; | |
601 } | |
602 | |
603 AddCacheToMaps(cache); | |
604 | |
605 cache_loader_->WriteIndex( | |
606 &cache_map_, | |
607 base::Bind(&ServiceWorkerCacheStorage::CreateCacheDidWriteIndex, | |
608 base::Unretained(this), | |
609 callback, | |
610 base::Unretained(cache))); | |
611 } | |
612 | |
613 void ServiceWorkerCacheStorage::CreateCacheDidWriteIndex( | |
614 const CacheAndErrorCallback& callback, | |
615 ServiceWorkerCache* cache, | |
616 bool success) { | |
617 DCHECK(thread_checker_.CalledOnValidThread()); | |
618 cache->CreateBackend(base::Bind(&ServiceWorkerCacheStorage::DidCreateBackend, | |
619 base::Unretained(this), | |
620 cache, | |
621 callback)); | |
622 } | |
623 | |
624 void ServiceWorkerCacheStorage::DeleteCacheDidWriteIndex( | |
625 const std::string& cache_name, | |
626 const BoolAndErrorCallback& callback, | |
627 bool success) { | |
628 DCHECK(thread_checker_.CalledOnValidThread()); | |
629 | |
630 cache_loader_->CleanUpDeletedCache( | |
631 cache_name, | |
632 base::Bind(&ServiceWorkerCacheStorage::DeleteCacheDidCleanUp, | |
633 base::Unretained(this), | |
634 callback)); | |
635 } | |
636 | |
637 void ServiceWorkerCacheStorage::DeleteCacheDidCleanUp( | |
638 const BoolAndErrorCallback& callback, | |
639 bool success) { | |
640 DCHECK(thread_checker_.CalledOnValidThread()); | |
641 | |
642 callback.Run(true, CACHE_STORAGE_ERROR_NO_ERROR); | |
643 } | |
644 | |
326 ServiceWorkerCache* ServiceWorkerCacheStorage::GetLoadedCache( | 645 ServiceWorkerCache* ServiceWorkerCacheStorage::GetLoadedCache( |
327 const std::string& cache_name) const { | 646 const std::string& cache_name) const { |
647 DCHECK(thread_checker_.CalledOnValidThread()); | |
328 DCHECK(initialized_); | 648 DCHECK(initialized_); |
329 | 649 |
330 NameMap::const_iterator it = name_map_.find(cache_name); | 650 NameMap::const_iterator it = name_map_.find(cache_name); |
331 if (it == name_map_.end()) | 651 if (it == name_map_.end()) |
332 return NULL; | 652 return NULL; |
333 | 653 |
334 ServiceWorkerCache* cache = cache_map_.Lookup(it->second); | 654 ServiceWorkerCache* cache = cache_map_.Lookup(it->second); |
335 DCHECK(cache); | 655 DCHECK(cache); |
336 return cache; | 656 return cache; |
337 } | 657 } |
338 | 658 |
339 } // namespace content | 659 } // namespace content |
OLD | NEW |