Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(254)

Side by Side Diff: content/browser/service_worker/service_worker_cache_storage.cc

Issue 460683002: Change threading in ServiceWorkerCacheStorage (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698