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

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

Powered by Google App Engine
This is Rietveld 408576698