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

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

Issue 424863002: Fill in some of ServiceWorkerFetchStores. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@cache_storage
Patch Set: Updated license 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_fetch_stores.h" 5 #include "content/browser/service_worker/service_worker_fetch_stores.h"
6 6
7 #include <string> 7 #include <string>
8 8
9 #include "base/file_util.h"
10 #include "base/files/memory_mapped_file.h"
11 #include "base/sha1.h"
12 #include "base/strings/string_number_conversions.h"
13 #include "base/strings/string_util.h"
14 #include "content/browser/service_worker/service_worker_cache.pb.h"
15 #include "content/browser/service_worker/service_worker_fetch_store.h"
9 #include "content/public/browser/browser_thread.h" 16 #include "content/public/browser/browser_thread.h"
17 #include "net/base/directory_lister.h"
10 18
11 namespace content { 19 namespace content {
12 20
21 // Handles the loading of ServiceWorkerFetchStore and any extra clean up other
22 // than deleting the ServiceWorkerFetchStore object.
23 class ServiceWorkerFetchStores::StoresLoader {
24 public:
25 virtual ~StoresLoader() {};
26 virtual ServiceWorkerFetchStore* LoadStore(const std::string& key) = 0;
27 // Creates a new store, deleting any pre-existing store of the same name.
28 virtual ServiceWorkerFetchStore* CreateStore(const std::string& key) = 0;
29 virtual bool CleanUpDeletedStore(const std::string& key) = 0;
30 virtual bool WriteIndex(StoreMap* stores) = 0;
31 virtual void LoadIndex(std::vector<std::string>* names) = 0;
32 };
33
34 class ServiceWorkerFetchStores::MemoryLoader
35 : public ServiceWorkerFetchStores::StoresLoader {
36 public:
37 virtual content::ServiceWorkerFetchStore* LoadStore(
38 const std::string& key) OVERRIDE {
39 NOTREACHED();
40 return NULL;
41 }
42
43 virtual ServiceWorkerFetchStore* CreateStore(
44 const std::string& key) OVERRIDE {
45 return ServiceWorkerFetchStore::CreateMemoryStore(key);
46 }
47
48 virtual bool CleanUpDeletedStore(const std::string& key) OVERRIDE {
49 return true;
50 }
51
52 virtual bool WriteIndex(StoreMap* stores) OVERRIDE { return false; }
53
54 virtual void LoadIndex(std::vector<std::string>* names) OVERRIDE { return; }
55 };
56
57 class ServiceWorkerFetchStores::SimpleCacheLoader
58 : public ServiceWorkerFetchStores::StoresLoader {
59 public:
60 explicit SimpleCacheLoader(const base::FilePath& origin_path)
61 : origin_path_(origin_path) {}
62
63 virtual ServiceWorkerFetchStore* LoadStore(const std::string& key) OVERRIDE {
64 base::CreateDirectory(CreatePersistentStorePath(origin_path_, key));
65 return ServiceWorkerFetchStore::CreatePersistentStore(
66 CreatePersistentStorePath(origin_path_, key), key);
67 }
68
69 virtual ServiceWorkerFetchStore* CreateStore(
70 const std::string& key) OVERRIDE {
71 base::FilePath store_path = CreatePersistentStorePath(origin_path_, key);
72 if (base::PathExists(store_path))
73 base::DeleteFile(store_path, /* recursive */ true);
74 return LoadStore(key);
75 }
76
77 virtual bool CleanUpDeletedStore(const std::string& key) OVERRIDE {
78 return base::DeleteFile(CreatePersistentStorePath(origin_path_, key), true);
79 }
80
81 virtual bool WriteIndex(StoreMap* stores) OVERRIDE {
82 ServiceWorkerCacheStorageIndex index;
83
84 for (StoreMap::const_iterator iter(stores); !iter.IsAtEnd();
85 iter.Advance()) {
86 const ServiceWorkerFetchStore* store = iter.GetCurrentValue();
87 ServiceWorkerCacheStorageIndex::Cache* cache = index.add_cache();
88 cache->set_name(store->name());
89 cache->set_size(0); // TODO(jkarlin): Make this real.
90 }
91
92 std::string serialized;
93 bool success = index.SerializeToString(&serialized);
94 DCHECK(success);
95
96 base::FilePath tmp_path = origin_path_.AppendASCII("index.txt.tmp");
97 base::FilePath index_path = origin_path_.AppendASCII("index.txt");
98
99 int bytes_written =
100 base::WriteFile(tmp_path, serialized.c_str(), serialized.size());
101 if (bytes_written != implicit_cast<int>(serialized.size())) {
102 base::DeleteFile(tmp_path, /* recursive */ false);
103 return false;
104 }
105
106 // Atomically rename the temporary index file to become the real one.
107 return base::ReplaceFile(tmp_path, index_path, NULL);
108 }
109
110 virtual void LoadIndex(std::vector<std::string>* names) OVERRIDE {
111 base::FilePath index_path = origin_path_.AppendASCII("index.txt");
112
113 std::string serialized;
114 if (!base::ReadFileToString(index_path, &serialized))
115 return;
116
117 ServiceWorkerCacheStorageIndex index;
118 index.ParseFromString(serialized);
119
120 for (int i = 0, max = index.cache_size(); i < max; ++i) {
121 const ServiceWorkerCacheStorageIndex::Cache& cache = index.cache(i);
122 names->push_back(cache.name());
123 }
124
125 // TODO(jkarlin): Delete stores that are in the directory and not returned
126 // in LoadIndex.
127 return;
128 }
129
130 private:
131 std::string HexedHash(const std::string& value) {
132 std::string value_hash = base::SHA1HashString(value);
133 std::string valued_hexed_hash = base::StringToLowerASCII(
134 base::HexEncode(value_hash.c_str(), value_hash.length()));
135 return valued_hexed_hash;
136 }
137
138 base::FilePath CreatePersistentStorePath(const base::FilePath& origin_path,
139 const std::string& store_name) {
140 return origin_path.AppendASCII(HexedHash(store_name));
141 }
142
143 const base::FilePath origin_path_;
144 };
145
13 ServiceWorkerFetchStores::ServiceWorkerFetchStores( 146 ServiceWorkerFetchStores::ServiceWorkerFetchStores(
14 const base::FilePath& path, 147 const base::FilePath& path,
15 BackendType backend_type, 148 bool memory_only,
16 const scoped_refptr<base::MessageLoopProxy>& callback_loop) 149 const scoped_refptr<base::MessageLoopProxy>& callback_loop)
17 : origin_path_(path), 150 : initialized_(false), origin_path_(path), callback_loop_(callback_loop) {
18 backend_type_(backend_type), 151 if (memory_only)
19 callback_loop_(callback_loop) { 152 stores_loader_.reset(new MemoryLoader());
153 else
154 stores_loader_.reset(new SimpleCacheLoader(origin_path_));
20 } 155 }
21 156
22 ServiceWorkerFetchStores::~ServiceWorkerFetchStores() { 157 ServiceWorkerFetchStores::~ServiceWorkerFetchStores() {
23 } 158 }
24 159
25 void ServiceWorkerFetchStores::CreateStore( 160 void ServiceWorkerFetchStores::CreateStore(
26 const std::string& key, 161 const std::string& store_name,
27 const StoreAndErrorCallback& callback) { 162 const StoreAndErrorCallback& callback) {
28 // TODO(jkarlin): Implement this. 163 LazyInit();
29 164
30 callback_loop_->PostTask(FROM_HERE, 165 if (store_name.empty()) {
31 base::Bind(callback, 0, FETCH_STORES_ERROR_EXISTS)); 166 callback_loop_->PostTask(
32 return; 167 FROM_HERE, base::Bind(callback, 0, FETCH_STORES_ERROR_EMPTY_KEY));
33 } 168 return;
34 169 }
35 void ServiceWorkerFetchStores::Get(const std::string& key, 170
36 const StoreAndErrorCallback& callback) { 171 if (GetLoadedStore(store_name)) {
37 // TODO(jkarlin): Implement this. 172 callback_loop_->PostTask(
38 173 FROM_HERE, base::Bind(callback, 0, FETCH_STORES_ERROR_EXISTS));
39 callback_loop_->PostTask(FROM_HERE, 174 return;
40 base::Bind(callback, 0, FETCH_STORES_ERROR_EXISTS)); 175 }
41 return; 176
42 } 177 ServiceWorkerFetchStore* store = stores_loader_->CreateStore(store_name);
43 178
44 void ServiceWorkerFetchStores::Has(const std::string& key, 179 if (!store) {
45 const BoolAndErrorCallback& callback) const { 180 callback_loop_->PostTask(
46 // TODO(jkarlin): Implement this. 181 FROM_HERE, base::Bind(callback, 0, FETCH_STORES_ERROR_STORAGE));
182 return;
183 }
184
185 InitStore(store);
186
187 stores_loader_->WriteIndex(&store_map_);
188
189 store->CreateBackend(
190 base::Bind(&ServiceWorkerFetchStores::InitializeStoreCallback,
191 base::Unretained(this),
192 store,
193 callback));
194 }
195
196 void ServiceWorkerFetchStores::GetStore(const std::string& store_name,
197 const StoreAndErrorCallback& callback) {
198 LazyInit();
199
200 if (store_name.empty()) {
201 callback_loop_->PostTask(
202 FROM_HERE, base::Bind(callback, 0, FETCH_STORES_ERROR_EMPTY_KEY));
203 return;
204 }
205
206 ServiceWorkerFetchStore* store = GetLoadedStore(store_name);
207 if (!store) {
208 callback_loop_->PostTask(
209 FROM_HERE, base::Bind(callback, 0, FETCH_STORES_ERROR_NOT_FOUND));
210 return;
211 }
212
213 store->CreateBackend(
214 base::Bind(&ServiceWorkerFetchStores::InitializeStoreCallback,
215 base::Unretained(this),
216 store,
217 callback));
218 }
219
220 void ServiceWorkerFetchStores::HasStore(const std::string& store_name,
221 const BoolAndErrorCallback& callback) {
222 LazyInit();
223
224 if (store_name.empty()) {
225 callback_loop_->PostTask(
226 FROM_HERE, base::Bind(callback, false, FETCH_STORES_ERROR_EMPTY_KEY));
227 return;
228 }
229
230 bool has_store = GetLoadedStore(store_name) != NULL;
47 231
48 callback_loop_->PostTask( 232 callback_loop_->PostTask(
49 FROM_HERE, base::Bind(callback, false, FETCH_STORES_ERROR_EXISTS)); 233 FROM_HERE,
50 return; 234 base::Bind(
51 } 235 callback, has_store, FETCH_STORES_ERROR_NO_ERROR));
52 236 }
53 void ServiceWorkerFetchStores::Delete(const std::string& key, 237
54 const StoreAndErrorCallback& callback) { 238 void ServiceWorkerFetchStores::DeleteStore(
55 // TODO(jkarlin): Implement this. 239 const std::string& store_name,
56 240 const BoolAndErrorCallback& callback) {
57 callback_loop_->PostTask(FROM_HERE, 241 LazyInit();
58 base::Bind(callback, 0, FETCH_STORES_ERROR_EXISTS)); 242
59 return; 243 if (store_name.empty()) {
60 } 244 callback_loop_->PostTask(
61 245 FROM_HERE, base::Bind(callback, false, FETCH_STORES_ERROR_EMPTY_KEY));
62 void ServiceWorkerFetchStores::Keys( 246 return;
63 const StringsAndErrorCallback& callback) const { 247 }
64 // TODO(jkarlin): Implement this. 248
65 std::vector<std::string> out; 249 ServiceWorkerFetchStore* store = GetLoadedStore(store_name);
250 if (!store) {
251 callback_loop_->PostTask(
252 FROM_HERE, base::Bind(callback, false, FETCH_STORES_ERROR_NOT_FOUND));
253 return;
254 }
255
256 name_map_.erase(store_name);
257 store_map_.Remove(store->id()); // deletes store
258
259 stores_loader_->WriteIndex(&store_map_); // Update the index.
260
261 stores_loader_->CleanUpDeletedStore(store_name);
262
66 callback_loop_->PostTask( 263 callback_loop_->PostTask(
67 FROM_HERE, base::Bind(callback, out, FETCH_STORES_ERROR_EXISTS)); 264 FROM_HERE, base::Bind(callback, true, FETCH_STORES_ERROR_NO_ERROR));
68 return; 265 }
266
267 void ServiceWorkerFetchStores::EnumerateStores(
268 const StringsAndErrorCallback& callback) {
269 LazyInit();
270
271 std::vector<std::string> names;
272 for (NameMap::const_iterator it = name_map_.begin(); it != name_map_.end();
273 ++it) {
274 names.push_back(it->first);
275 }
276
277 callback_loop_->PostTask(
278 FROM_HERE, base::Bind(callback, names, FETCH_STORES_ERROR_NO_ERROR));
279 }
280
281 void ServiceWorkerFetchStores::InitializeStoreCallback(
282 const ServiceWorkerFetchStore* store,
283 const StoreAndErrorCallback& callback,
284 bool success) {
285 if (!success) {
286 // TODO(jkarlin): This should delete the directory and try again in case
287 // the cache is simply corrupt.
288 callback_loop_->PostTask(
289 FROM_HERE, base::Bind(callback, 0, FETCH_STORES_ERROR_STORAGE));
290 return;
291 }
292 callback_loop_->PostTask(
293 FROM_HERE,
294 base::Bind(callback, store->id(), FETCH_STORES_ERROR_NO_ERROR));
295 }
296
297 // Init is run lazily so that it is called on the proper MessageLoop.
298 void ServiceWorkerFetchStores::LazyInit() {
299 if (initialized_)
300 return;
301
302 std::vector<std::string> indexed_store_names;
303 stores_loader_->LoadIndex(&indexed_store_names);
304
305 for (std::vector<std::string>::const_iterator it =
306 indexed_store_names.begin();
307 it != indexed_store_names.end();
308 ++it) {
309 ServiceWorkerFetchStore* store = stores_loader_->LoadStore(*it);
310 InitStore(store);
311 }
312 initialized_ = true;
313 }
314
315 void ServiceWorkerFetchStores::InitStore(ServiceWorkerFetchStore* store) {
316 StoreID id = store_map_.Add(store);
317 name_map_.insert(std::make_pair(store->name(), id));
318 store->set_id(id);
319 }
320
321 ServiceWorkerFetchStore* ServiceWorkerFetchStores::GetLoadedStore(
322 const std::string& key) const {
323 DCHECK(initialized_);
324
325 NameMap::const_iterator it = name_map_.find(key);
326 if (it == name_map_.end())
327 return NULL;
328
329 ServiceWorkerFetchStore* store = store_map_.Lookup(it->second);
330 DCHECK(store);
331 return store;
69 } 332 }
70 333
71 } // namespace content 334 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698