OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/browser/service_worker/service_worker_cache_storage.h" | 5 #include "content/browser/service_worker/service_worker_cache_storage.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 | 8 |
9 #include "base/file_util.h" | 9 #include "base/file_util.h" |
10 #include "base/files/memory_mapped_file.h" | 10 #include "base/files/memory_mapped_file.h" |
11 #include "base/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 |
OLD | NEW |