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

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

Powered by Google App Engine
This is Rietveld 408576698