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

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

Issue 444333006: Rename ServiceWorkerFetchStore/FetchStores/FetchStoresManager (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@fetch_stores3
Patch Set: Rebase 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
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "content/browser/service_worker/service_worker_fetch_stores.h"
6
7 #include <string>
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"
16 #include "content/public/browser/browser_thread.h"
17 #include "net/base/directory_lister.h"
18
19 namespace content {
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
146 ServiceWorkerFetchStores::ServiceWorkerFetchStores(
147 const base::FilePath& path,
148 bool memory_only,
149 const scoped_refptr<base::MessageLoopProxy>& callback_loop)
150 : initialized_(false), origin_path_(path), callback_loop_(callback_loop) {
151 if (memory_only)
152 stores_loader_.reset(new MemoryLoader());
153 else
154 stores_loader_.reset(new SimpleCacheLoader(origin_path_));
155 }
156
157 ServiceWorkerFetchStores::~ServiceWorkerFetchStores() {
158 }
159
160 void ServiceWorkerFetchStores::CreateStore(
161 const std::string& store_name,
162 const StoreAndErrorCallback& callback) {
163 LazyInit();
164
165 if (store_name.empty()) {
166 callback_loop_->PostTask(
167 FROM_HERE, base::Bind(callback, 0, FETCH_STORES_ERROR_EMPTY_KEY));
168 return;
169 }
170
171 if (GetLoadedStore(store_name)) {
172 callback_loop_->PostTask(
173 FROM_HERE, base::Bind(callback, 0, FETCH_STORES_ERROR_EXISTS));
174 return;
175 }
176
177 ServiceWorkerFetchStore* store = stores_loader_->CreateStore(store_name);
178
179 if (!store) {
180 callback_loop_->PostTask(
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;
231
232 callback_loop_->PostTask(
233 FROM_HERE,
234 base::Bind(
235 callback, has_store, FETCH_STORES_ERROR_NO_ERROR));
236 }
237
238 void ServiceWorkerFetchStores::DeleteStore(
239 const std::string& store_name,
240 const BoolAndErrorCallback& callback) {
241 LazyInit();
242
243 if (store_name.empty()) {
244 callback_loop_->PostTask(
245 FROM_HERE, base::Bind(callback, false, FETCH_STORES_ERROR_EMPTY_KEY));
246 return;
247 }
248
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
263 callback_loop_->PostTask(
264 FROM_HERE, base::Bind(callback, true, FETCH_STORES_ERROR_NO_ERROR));
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;
332 }
333
334 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698