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

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

Issue 248803003: ServiceWorker: Store registration data in ServiceWorkerDatabase (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: review fix Created 6 years, 8 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 | Annotate | Revision Log
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_database.h" 5 #include "content/browser/service_worker/service_worker_database.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/location.h" 10 #include "base/location.h"
11 #include "base/logging.h" 11 #include "base/logging.h"
12 #include "base/strings/string_number_conversions.h" 12 #include "base/strings/string_number_conversions.h"
13 #include "base/strings/string_split.h"
14 #include "base/strings/string_util.h"
15 #include "base/strings/stringprintf.h"
16 #include "content/browser/service_worker/service_worker_database.pb.h"
13 #include "third_party/leveldatabase/src/helpers/memenv/memenv.h" 17 #include "third_party/leveldatabase/src/helpers/memenv/memenv.h"
14 #include "third_party/leveldatabase/src/include/leveldb/db.h" 18 #include "third_party/leveldatabase/src/include/leveldb/db.h"
15 #include "third_party/leveldatabase/src/include/leveldb/env.h" 19 #include "third_party/leveldatabase/src/include/leveldb/env.h"
16 #include "third_party/leveldatabase/src/include/leveldb/write_batch.h" 20 #include "third_party/leveldatabase/src/include/leveldb/write_batch.h"
17 21
18 // LevelDB database schema 22 // LevelDB database schema
19 // ======================= 23 // =======================
20 // 24 //
21 // NOTE 25 // NOTE
22 // - int64 value is serialized as a string by base::Int64ToString(). 26 // - int64 value is serialized as a string by base::Int64ToString().
23 // 27 //
24 // Version 1 (in sorted order) 28 // Version 1 (in sorted order)
25 // key: "DB_VERSION" 29 // key: "INITDATA_DB_VERSION"
26 // value: "1" 30 // value: "1"
27 // 31 //
28 // key: "NEXT_REGISTRATION_ID" 32 // key: "INITDATA_NEXT_REGISTRATION_ID"
29 // value: <int64 'next_available_registration_id'> 33 // value: <int64 'next_available_registration_id'>
30 // 34 //
31 // key: "NEXT_RESOURCE_ID" 35 // key: "INITDATA_NEXT_RESOURCE_ID"
32 // value: <int64 'next_available_resource_id'> 36 // value: <int64 'next_available_resource_id'>
33 // 37 //
34 // key: "NEXT_VERSION_ID" 38 // key: "INITDATA_NEXT_VERSION_ID"
35 // value: <int64 'next_available_version_id'> 39 // value: <int64 'next_available_version_id'>
40 //
41 // key: "INITDATA_UNIQUE_ORIGIN:" + <GURL 'origin' serialized by GURL::spec()>
42 // value: <empty>
43 //
44 // key: "REG:" + (1) + '\x00' + (2)
45 // (1) <GURL 'origin' serialized by GURL::spec()>
46 // (2) <int64 'registration_id'>
47 // (ex. "REG:http://example.com\x00123456")
48 // value: <ServiceWorkerRegistrationData serialized as a string>
36 49
37 namespace content { 50 namespace content {
38 51
39 namespace { 52 namespace {
40 53
41 const char kDatabaseVersionKey[] = "DB_VERSION"; 54 const char kDatabaseVersionKey[] = "INITDATA_DB_VERSION";
42 const char kNextRegIdKey[] = "NEXT_REGISTRATION_ID"; 55 const char kNextRegIdKey[] = "INITDATA_NEXT_REGISTRATION_ID";
43 const char kNextResIdKey[] = "NEXT_RESOURCE_ID"; 56 const char kNextResIdKey[] = "INITDATA_NEXT_RESOURCE_ID";
44 const char kNextVerIdKey[] = "NEXT_VERSION_ID"; 57 const char kNextVerIdKey[] = "INITDATA_NEXT_VERSION_ID";
58 const char kUniqueOriginKey[] = "INITDATA_UNIQUE_ORIGIN:";
59
60 const char kRegKeyPrefix[] = "REG:";
61 const char kKeySeparator = '\x00';
45 62
46 const int64 kCurrentSchemaVersion = 1; 63 const int64 kCurrentSchemaVersion = 1;
47 64
65 bool RemovePrefix(const std::string& str,
66 const std::string& prefix,
67 std::string* out) {
68 if (!StartsWithASCII(str, prefix, true))
69 return false;
70 if (out)
71 *out = str.substr(prefix.size());
72 return true;
73 }
74
75 std::string CreateRegistrationKey(int64 registration_id,
76 const GURL& origin) {
77 return base::StringPrintf("%s%s%c%s",
78 kRegKeyPrefix,
79 origin.spec().c_str(),
80 kKeySeparator,
81 base::Int64ToString(registration_id).c_str());
82 }
83
84 std::string CreateUniqueOriginKey(const GURL& origin) {
85 return base::StringPrintf("%s%s", kUniqueOriginKey, origin.spec().c_str());
86 }
87
88 void PutRegistrationDataToBatch(
89 const ServiceWorkerDatabase::RegistrationData& input,
90 leveldb::WriteBatch* batch) {
91 DCHECK(batch);
92
93 // Convert RegistrationData to ServiceWorkerRegistrationData.
94 ServiceWorkerRegistrationData data;
95 data.set_registration_id(input.registration_id);
96 data.set_scope_url(input.scope.spec());
97 data.set_script_url(input.script.spec());
98 data.set_version_id(input.version_id);
99 data.set_is_active(input.is_active);
100 data.set_has_fetch_handler(input.has_fetch_handler);
101 data.set_last_update_check_time(input.last_update_check.ToInternalValue());
102
103 std::string value;
104 bool success = data.SerializeToString(&value);
105 DCHECK(success);
106 GURL origin = GURL(data.scope_url()).GetOrigin();
michaeln 2014/04/26 00:29:02 could use input.scope.GetOrigin()
nhiroki 2014/04/28 04:15:59 Done.
107 batch->Put(CreateRegistrationKey(data.registration_id(), origin), value);
108 }
109
110 void PutUniqueOriginToBatch(const GURL& origin,
111 leveldb::WriteBatch* batch) {
112 // Value should be empty.
113 batch->Put(CreateUniqueOriginKey(origin), "");
114 }
115
116 bool ParseRegistrationData(
117 const std::string& serialized,
118 ServiceWorkerDatabase::RegistrationData* out) {
119 DCHECK(out);
120 ServiceWorkerRegistrationData data;
121 if (!data.ParseFromString(serialized))
122 return false;
123
124 GURL scope_url(data.scope_url());
125 GURL script_url(data.script_url());
126 if (scope_url.GetOrigin() != script_url.GetOrigin())
127 return false;
128
129 // Convert ServiceWorkerRegistrationData to RegistrationData.
130 out->registration_id = data.registration_id();
131 out->scope = scope_url;
132 out->script = script_url;
133 out->version_id = data.version_id();
134 out->is_active = data.is_active();
135 out->has_fetch_handler = data.has_fetch_handler();
136 out->last_update_check =
137 base::Time::FromInternalValue(data.last_update_check_time());
138 return true;
139 }
140
48 } // namespace 141 } // namespace
49 142
50 ServiceWorkerDatabase::RegistrationData::RegistrationData() 143 ServiceWorkerDatabase::RegistrationData::RegistrationData()
51 : registration_id(-1), 144 : registration_id(-1),
52 version_id(-1), 145 version_id(-1),
53 is_active(false), 146 is_active(false),
54 has_fetch_handler(false) { 147 has_fetch_handler(false) {
55 } 148 }
56 149
57 ServiceWorkerDatabase::RegistrationData::~RegistrationData() { 150 ServiceWorkerDatabase::RegistrationData::~RegistrationData() {
58 } 151 }
59 152
60 ServiceWorkerDatabase::ServiceWorkerDatabase(const base::FilePath& path) 153 ServiceWorkerDatabase::ServiceWorkerDatabase(const base::FilePath& path)
61 : path_(path), 154 : path_(path),
155 next_avail_registration_id_(0),
156 next_avail_resource_id_(0),
157 next_avail_version_id_(0),
62 is_disabled_(false), 158 is_disabled_(false),
63 was_corruption_detected_(false) { 159 was_corruption_detected_(false) {
64 } 160 }
65 161
66 ServiceWorkerDatabase::~ServiceWorkerDatabase() { 162 ServiceWorkerDatabase::~ServiceWorkerDatabase() {
67 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 163 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
68 db_.reset(); 164 db_.reset();
69 } 165 }
70 166
71 bool ServiceWorkerDatabase::GetNextAvailableIds( 167 bool ServiceWorkerDatabase::GetNextAvailableIds(
72 int64* next_avail_registration_id, 168 int64* next_avail_registration_id,
73 int64* next_avail_version_id, 169 int64* next_avail_version_id,
74 int64* next_avail_resource_id) { 170 int64* next_avail_resource_id) {
75 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 171 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
76 DCHECK(next_avail_registration_id); 172 DCHECK(next_avail_registration_id);
77 DCHECK(next_avail_version_id); 173 DCHECK(next_avail_version_id);
78 DCHECK(next_avail_resource_id); 174 DCHECK(next_avail_resource_id);
79 175
80 if (!LazyOpen(false) || is_disabled_) 176 if (!LazyOpen(false) || is_disabled_)
81 return false; 177 return false;
82 178
83 int64 reg_id = -1; 179 if (!ReadNextAvailableId(kNextRegIdKey, &next_avail_registration_id_) ||
84 int64 ver_id = -1; 180 !ReadNextAvailableId(kNextVerIdKey, &next_avail_version_id_) ||
85 int64 res_id = -1; 181 !ReadNextAvailableId(kNextResIdKey, &next_avail_resource_id_)) {
182 return false;
183 }
86 184
87 if (!ReadNextAvailableId(kNextRegIdKey, &reg_id) || 185 *next_avail_registration_id = next_avail_registration_id_;
88 !ReadNextAvailableId(kNextVerIdKey, &ver_id) || 186 *next_avail_version_id = next_avail_version_id_;
89 !ReadNextAvailableId(kNextResIdKey, &res_id)) 187 *next_avail_resource_id = next_avail_resource_id_;
188 return true;
189 }
190
191 bool ServiceWorkerDatabase::GetOriginsWithRegistrations(
192 std::set<GURL>* origins) {
193 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
194 DCHECK(origins);
195
196 if (!LazyOpen(false) || is_disabled_)
90 return false; 197 return false;
91 198
92 *next_avail_registration_id = reg_id; 199 scoped_ptr<leveldb::Iterator> itr(db_->NewIterator(leveldb::ReadOptions()));
93 *next_avail_version_id = ver_id; 200 for (itr->Seek(kUniqueOriginKey); itr->Valid(); itr->Next()) {
94 *next_avail_resource_id = res_id; 201 if (!itr->status().ok()) {
202 HandleError(FROM_HERE, itr->status());
203 origins->clear();
204 return false;
205 }
206
207 std::string origin;
208 if (!RemovePrefix(itr->key().ToString(), kUniqueOriginKey, &origin))
209 break;
210 origins->insert(GURL(origin));
211 }
95 return true; 212 return true;
96 } 213 }
97 214
215 bool ServiceWorkerDatabase::GetRegistrationsForOrigin(
216 const GURL& origin,
217 std::vector<RegistrationData>* registrations) {
218 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
219 DCHECK(registrations);
220
221 if (!LazyOpen(false) || is_disabled_)
222 return false;
223
224 // Create a key prefix for registrations.
225 std::string prefix = base::StringPrintf(
226 "%s%s%c", kRegKeyPrefix, origin.spec().c_str(), kKeySeparator);
227
228 scoped_ptr<leveldb::Iterator> itr(db_->NewIterator(leveldb::ReadOptions()));
229 for (itr->Seek(prefix); itr->Valid(); itr->Next()) {
230 if (!itr->status().ok()) {
231 HandleError(FROM_HERE, itr->status());
232 registrations->clear();
233 return false;
234 }
235
236 if (!RemovePrefix(itr->key().ToString(), prefix, NULL))
237 break;
238
239 RegistrationData registration;
240 if (!ParseRegistrationData(itr->value().ToString(), &registration)) {
241 HandleError(FROM_HERE, leveldb::Status::Corruption("failed to parse"));
242 registrations->clear();
243 return false;
244 }
245 registrations->push_back(registration);
246 }
247 return true;
248 }
249
250 bool ServiceWorkerDatabase::ReadRegistration(
251 int64 registration_id,
252 const GURL& origin,
253 RegistrationData* registration,
254 std::vector<ResourceRecord>* resources) {
255 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
256 DCHECK(registration);
257 DCHECK(resources);
258
259 if (!LazyOpen(false) || is_disabled_)
260 return false;
261
262 RegistrationData value;
263 if (!ReadRegistrationData(registration_id, origin, &value))
264 return false;
265
266 // TODO(nhiroki): Read ResourceRecords tied with this registration.
267
268 *registration = value;
269 return true;
270 }
271
272 bool ServiceWorkerDatabase::WriteRegistration(
273 const RegistrationData& registration,
274 const std::vector<ResourceRecord>& resources) {
275 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
276 if (!LazyOpen(true) || is_disabled_)
277 return false;
278
279 leveldb::WriteBatch batch;
280 BumpNextRegistrationIdIfNeeded(registration.registration_id, &batch);
281 BumpNextVersionIdIfNeeded(registration.version_id, &batch);
282
283 // TODO(nhiroki): Skip to add the origin into the unique origin list if it
284 // has already been added.
285 PutUniqueOriginToBatch(registration.scope.GetOrigin(), &batch);
286
287 PutRegistrationDataToBatch(registration, &batch);
288
289 // TODO(nhiroki): Write |resources| into the database.
290 return WriteBatch(&batch);
291 }
292
293 bool ServiceWorkerDatabase::UpdateVersionToActive(int64 registration_id,
294 const GURL& origin) {
295 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
296 if (!LazyOpen(false) || is_disabled_)
297 return false;
298
299 RegistrationData registration;
300 if (!ReadRegistrationData(registration_id, origin, &registration))
301 return false;
302
303 registration.is_active = true;
304
305 leveldb::WriteBatch batch;
306 PutRegistrationDataToBatch(registration, &batch);
307 return WriteBatch(&batch);
308 }
309
310 bool ServiceWorkerDatabase::UpdateLastCheckTime(int64 registration_id,
311 const GURL& origin,
312 const base::Time& time) {
313 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
314 if (!LazyOpen(false) || is_disabled_)
315 return false;
316
317 RegistrationData registration;
318 if (!ReadRegistrationData(registration_id, origin, &registration))
319 return false;
320
321 registration.last_update_check = time;
322
323 leveldb::WriteBatch batch;
324 PutRegistrationDataToBatch(registration, &batch);
325 return WriteBatch(&batch);
326 }
327
328 bool ServiceWorkerDatabase::DeleteRegistration(int64 registration_id,
329 const GURL& origin) {
330 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
331 if (!LazyOpen(false) || is_disabled_)
332 return false;
333
334 leveldb::WriteBatch batch;
335
336 // Remove |origin| from unique origins if a registration specified by
337 // |registration_id| is the only one for |origin|.
338 // TODO(nhiroki): Check the uniqueness by more efficient way.
339 std::vector<RegistrationData> registrations;
340 if (!GetRegistrationsForOrigin(origin, &registrations))
341 return false;
342 if (registrations.size() == 1 &&
343 registrations[0].registration_id == registration_id) {
344 batch.Delete(CreateUniqueOriginKey(origin));
345 }
346
347 batch.Delete(CreateRegistrationKey(registration_id, origin));
348
349 // TODO(nhiroki): Delete ResourceRecords tied with this registration.
350 return WriteBatch(&batch);
351 }
352
98 bool ServiceWorkerDatabase::LazyOpen(bool create_if_needed) { 353 bool ServiceWorkerDatabase::LazyOpen(bool create_if_needed) {
99 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 354 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
100 if (IsOpen()) 355 if (IsOpen())
101 return true; 356 return true;
102 357
103 // Do not try to open a database if we tried and failed once. 358 // Do not try to open a database if we tried and failed once.
104 if (is_disabled_) 359 if (is_disabled_)
105 return false; 360 return false;
106 361
107 // When |path_| is empty, open a database in-memory. 362 // When |path_| is empty, open a database in-memory.
(...skipping 19 matching lines...) Expand all
127 leveldb::Status status = 382 leveldb::Status status =
128 leveldb::DB::Open(options, path_.AsUTF8Unsafe(), &db); 383 leveldb::DB::Open(options, path_.AsUTF8Unsafe(), &db);
129 if (!status.ok()) { 384 if (!status.ok()) {
130 DCHECK(!db); 385 DCHECK(!db);
131 // TODO(nhiroki): Should we retry to open the database? 386 // TODO(nhiroki): Should we retry to open the database?
132 HandleError(FROM_HERE, status); 387 HandleError(FROM_HERE, status);
133 return false; 388 return false;
134 } 389 }
135 db_.reset(db); 390 db_.reset(db);
136 391
137 if (IsEmpty() && !PopulateInitialData()) { 392 int64 db_version;
nhiroki 2014/04/25 11:05:01 fyi: Removed all write operations from LazyOpen().
michaeln 2014/04/26 00:29:02 fantastique ;)
138 DLOG(ERROR) << "Failed to populate the database."; 393 if (!ReadDatabaseVersion(&db_version))
139 db_.reset();
140 return false; 394 return false;
141 } 395 if (db_version > 0)
396 is_initialized_ = true;
142 return true; 397 return true;
143 } 398 }
144 399
145 bool ServiceWorkerDatabase::PopulateInitialData() {
146 leveldb::WriteBatch batch;
147 batch.Put(kDatabaseVersionKey, base::Int64ToString(kCurrentSchemaVersion));
148 batch.Put(kNextRegIdKey, base::Int64ToString(0));
149 batch.Put(kNextResIdKey, base::Int64ToString(0));
150 batch.Put(kNextVerIdKey, base::Int64ToString(0));
151 return WriteBatch(&batch);
152 }
153
154 bool ServiceWorkerDatabase::ReadNextAvailableId( 400 bool ServiceWorkerDatabase::ReadNextAvailableId(
155 const char* id_key, int64* next_avail_id) { 401 const char* id_key, int64* next_avail_id) {
156 DCHECK(id_key); 402 DCHECK(id_key);
157 DCHECK(next_avail_id); 403 DCHECK(next_avail_id);
158 404
159 std::string value; 405 std::string value;
160 leveldb::Status status = db_->Get(leveldb::ReadOptions(), id_key, &value); 406 leveldb::Status status = db_->Get(leveldb::ReadOptions(), id_key, &value);
407 if (status.IsNotFound()) {
408 // Nobody has gotten the next resource id for |id_key|.
409 *next_avail_id = 0;
410 return true;
411 }
412
161 if (!status.ok()) { 413 if (!status.ok()) {
162 HandleError(FROM_HERE, status); 414 HandleError(FROM_HERE, status);
163 return false; 415 return false;
164 } 416 }
165 417
166 int64 parsed; 418 int64 parsed;
167 if (!base::StringToInt64(value, &parsed)) { 419 if (!base::StringToInt64(value, &parsed)) {
168 HandleError(FROM_HERE, leveldb::Status::Corruption("failed to parse")); 420 HandleError(FROM_HERE, leveldb::Status::Corruption("failed to parse"));
169 return false; 421 return false;
170 } 422 }
171 423
172 *next_avail_id = parsed; 424 *next_avail_id = parsed;
173 return true; 425 return true;
174 } 426 }
175 427
428 bool ServiceWorkerDatabase::ReadRegistrationData(
429 int64 registration_id,
430 const GURL& origin,
431 RegistrationData* registration) {
432 DCHECK(registration);
433
434 std::string key = CreateRegistrationKey(registration_id, origin);
435
436 std::string value;
437 leveldb::Status status = db_->Get(leveldb::ReadOptions(), key, &value);
438 if (!status.ok()) {
439 if (!status.IsNotFound())
440 HandleError(FROM_HERE, status);
441 return false;
442 }
443
444 RegistrationData parsed;
445 if (!ParseRegistrationData(value, &parsed)) {
446 HandleError(FROM_HERE, leveldb::Status::Corruption("failed to parse"));
447 return false;
448 }
449
450 *registration = parsed;
451 return true;
452 }
453
454 bool ServiceWorkerDatabase::ReadDatabaseVersion(int64* db_version) {
455 std::string value;
456 leveldb::Status status =
457 db_->Get(leveldb::ReadOptions(), kDatabaseVersionKey, &value);
458 if (status.IsNotFound()) {
459 // The database hasn't been initialized yet.
460 *db_version = 0;
461 return true;
462 }
463 if (!status.ok()) {
464 HandleError(FROM_HERE, status);
465 return false;
466 }
467
468 int64 parsed;
469 if (!base::StringToInt64(value, &parsed)) {
470 HandleError(FROM_HERE, leveldb::Status::Corruption("failed to parse"));
471 return false;
472 }
473
michaeln 2014/04/26 00:29:02 ?? const int kFirstValidVersion = 1; if (parsed <
nhiroki 2014/04/28 04:15:59 Done.
474 *db_version = parsed;
475 return true;
476 }
477
176 bool ServiceWorkerDatabase::WriteBatch(leveldb::WriteBatch* batch) { 478 bool ServiceWorkerDatabase::WriteBatch(leveldb::WriteBatch* batch) {
177 DCHECK(batch); 479 DCHECK(batch);
178 DCHECK(!is_disabled_); 480 DCHECK(!is_disabled_);
481
482 if (!is_initialized_) {
483 // Write the database schema version.
484 batch->Put(kDatabaseVersionKey, base::Int64ToString(kCurrentSchemaVersion));
485 is_initialized_ = true;
486 }
487
179 leveldb::Status status = db_->Write(leveldb::WriteOptions(), batch); 488 leveldb::Status status = db_->Write(leveldb::WriteOptions(), batch);
180 if (!status.ok()) { 489 if (!status.ok()) {
181 HandleError(FROM_HERE, status); 490 HandleError(FROM_HERE, status);
182 return false; 491 return false;
183 } 492 }
184 return true; 493 return true;
185 } 494 }
186 495
496 void ServiceWorkerDatabase::BumpNextRegistrationIdIfNeeded(
497 int64 used_id, leveldb::WriteBatch* batch) {
498 DCHECK(batch);
499 if (next_avail_registration_id_ <= used_id) {
500 next_avail_registration_id_ = used_id + 1;
501 batch->Put(kNextRegIdKey, base::Int64ToString(next_avail_registration_id_));
502 }
503 }
504
505 void ServiceWorkerDatabase::BumpNextVersionIdIfNeeded(
506 int64 used_id, leveldb::WriteBatch* batch) {
507 DCHECK(batch);
508 if (next_avail_version_id_ <= used_id) {
509 next_avail_version_id_ = used_id + 1;
510 batch->Put(kNextVerIdKey, base::Int64ToString(next_avail_version_id_));
511 }
512 }
513
187 bool ServiceWorkerDatabase::IsOpen() { 514 bool ServiceWorkerDatabase::IsOpen() {
188 return db_.get() != NULL; 515 return db_.get() != NULL;
189 } 516 }
190 517
191 bool ServiceWorkerDatabase::IsEmpty() {
192 scoped_ptr<leveldb::Iterator> itr(db_->NewIterator(leveldb::ReadOptions()));
193 itr->SeekToFirst();
194 // TODO(nhiroki): Handle an error.
195 DCHECK(itr->status().ok());
196 return !itr->Valid();
197 }
198
199 void ServiceWorkerDatabase::HandleError( 518 void ServiceWorkerDatabase::HandleError(
200 const tracked_objects::Location& from_here, 519 const tracked_objects::Location& from_here,
201 const leveldb::Status& status) { 520 const leveldb::Status& status) {
202 // TODO(nhiroki): Add an UMA histogram. 521 // TODO(nhiroki): Add an UMA histogram.
203 DLOG(ERROR) << "Failed at: " << from_here.ToString() 522 DLOG(ERROR) << "Failed at: " << from_here.ToString()
204 << " with error: " << status.ToString(); 523 << " with error: " << status.ToString();
205 is_disabled_ = true; 524 is_disabled_ = true;
206 if (status.IsCorruption()) 525 if (status.IsCorruption())
207 was_corruption_detected_ = true; 526 was_corruption_detected_ = true;
208 db_.reset(); 527 db_.reset();
209 } 528 }
210 529
211 } // namespace content 530 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698