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_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" |
(...skipping 24 matching lines...) Expand all Loading... |
35 // | 35 // |
36 // key: "INITDATA_NEXT_RESOURCE_ID" | 36 // key: "INITDATA_NEXT_RESOURCE_ID" |
37 // value: <int64 'next_available_resource_id'> | 37 // value: <int64 'next_available_resource_id'> |
38 // | 38 // |
39 // key: "INITDATA_NEXT_VERSION_ID" | 39 // key: "INITDATA_NEXT_VERSION_ID" |
40 // value: <int64 'next_available_version_id'> | 40 // value: <int64 'next_available_version_id'> |
41 // | 41 // |
42 // key: "INITDATA_UNIQUE_ORIGIN:" + <GURL 'origin'> | 42 // key: "INITDATA_UNIQUE_ORIGIN:" + <GURL 'origin'> |
43 // value: <empty> | 43 // value: <empty> |
44 // | 44 // |
| 45 // key: "PRES:" + <int64 'purgeable_resource_id'> |
| 46 // value: <empty> |
| 47 // |
45 // key: "REG:" + <GURL 'origin'> + '\x00' + <int64 'registration_id'> | 48 // key: "REG:" + <GURL 'origin'> + '\x00' + <int64 'registration_id'> |
46 // (ex. "REG:http://example.com\x00123456") | 49 // (ex. "REG:http://example.com\x00123456") |
47 // value: <ServiceWorkerRegistrationData serialized as a string> | 50 // value: <ServiceWorkerRegistrationData serialized as a string> |
| 51 // |
| 52 // key: "URES:" + <int64 'uncommitted_resource_id'> |
| 53 // value: <empty> |
48 | 54 |
49 namespace content { | 55 namespace content { |
50 | 56 |
51 namespace { | 57 namespace { |
52 | 58 |
53 const char kDatabaseVersionKey[] = "INITDATA_DB_VERSION"; | 59 const char kDatabaseVersionKey[] = "INITDATA_DB_VERSION"; |
54 const char kNextRegIdKey[] = "INITDATA_NEXT_REGISTRATION_ID"; | 60 const char kNextRegIdKey[] = "INITDATA_NEXT_REGISTRATION_ID"; |
55 const char kNextResIdKey[] = "INITDATA_NEXT_RESOURCE_ID"; | 61 const char kNextResIdKey[] = "INITDATA_NEXT_RESOURCE_ID"; |
56 const char kNextVerIdKey[] = "INITDATA_NEXT_VERSION_ID"; | 62 const char kNextVerIdKey[] = "INITDATA_NEXT_VERSION_ID"; |
57 const char kUniqueOriginKey[] = "INITDATA_UNIQUE_ORIGIN:"; | 63 const char kUniqueOriginKey[] = "INITDATA_UNIQUE_ORIGIN:"; |
58 | 64 |
59 const char kRegKeyPrefix[] = "REG:"; | 65 const char kRegKeyPrefix[] = "REG:"; |
60 const char kKeySeparator = '\x00'; | 66 const char kKeySeparator = '\x00'; |
61 | 67 |
| 68 const char kUncommittedResIdKeyPrefix[] = "URES:"; |
| 69 const char kPurgeableResIdKeyPrefix[] = "PRES:"; |
| 70 |
62 const int64 kCurrentSchemaVersion = 1; | 71 const int64 kCurrentSchemaVersion = 1; |
63 | 72 |
64 bool RemovePrefix(const std::string& str, | 73 bool RemovePrefix(const std::string& str, |
65 const std::string& prefix, | 74 const std::string& prefix, |
66 std::string* out) { | 75 std::string* out) { |
67 if (!StartsWithASCII(str, prefix, true)) | 76 if (!StartsWithASCII(str, prefix, true)) |
68 return false; | 77 return false; |
69 if (out) | 78 if (out) |
70 *out = str.substr(prefix.size()); | 79 *out = str.substr(prefix.size()); |
71 return true; | 80 return true; |
72 } | 81 } |
73 | 82 |
74 std::string CreateRegistrationKey(int64 registration_id, | 83 std::string CreateRegistrationKey(int64 registration_id, |
75 const GURL& origin) { | 84 const GURL& origin) { |
76 return base::StringPrintf("%s%s%c%s", | 85 return base::StringPrintf("%s%s%c%s", |
77 kRegKeyPrefix, | 86 kRegKeyPrefix, |
78 origin.spec().c_str(), | 87 origin.spec().c_str(), |
79 kKeySeparator, | 88 kKeySeparator, |
80 base::Int64ToString(registration_id).c_str()); | 89 base::Int64ToString(registration_id).c_str()); |
81 } | 90 } |
82 | 91 |
83 std::string CreateUniqueOriginKey(const GURL& origin) { | 92 std::string CreateUniqueOriginKey(const GURL& origin) { |
84 return base::StringPrintf("%s%s", kUniqueOriginKey, origin.spec().c_str()); | 93 return base::StringPrintf("%s%s", kUniqueOriginKey, origin.spec().c_str()); |
85 } | 94 } |
86 | 95 |
| 96 std::string CreateResourceIdKey(const char* key_prefix, int64 resource_id) { |
| 97 return base::StringPrintf( |
| 98 "%s%s", key_prefix, base::Int64ToString(resource_id).c_str()); |
| 99 } |
| 100 |
87 void PutRegistrationDataToBatch( | 101 void PutRegistrationDataToBatch( |
88 const ServiceWorkerDatabase::RegistrationData& input, | 102 const ServiceWorkerDatabase::RegistrationData& input, |
89 leveldb::WriteBatch* batch) { | 103 leveldb::WriteBatch* batch) { |
90 DCHECK(batch); | 104 DCHECK(batch); |
91 | 105 |
92 // Convert RegistrationData to ServiceWorkerRegistrationData. | 106 // Convert RegistrationData to ServiceWorkerRegistrationData. |
93 ServiceWorkerRegistrationData data; | 107 ServiceWorkerRegistrationData data; |
94 data.set_registration_id(input.registration_id); | 108 data.set_registration_id(input.registration_id); |
95 data.set_scope_url(input.scope.spec()); | 109 data.set_scope_url(input.scope.spec()); |
96 data.set_script_url(input.script.spec()); | 110 data.set_script_url(input.script.spec()); |
(...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
343 registrations[0].registration_id == registration_id) { | 357 registrations[0].registration_id == registration_id) { |
344 batch.Delete(CreateUniqueOriginKey(origin)); | 358 batch.Delete(CreateUniqueOriginKey(origin)); |
345 } | 359 } |
346 | 360 |
347 batch.Delete(CreateRegistrationKey(registration_id, origin)); | 361 batch.Delete(CreateRegistrationKey(registration_id, origin)); |
348 | 362 |
349 // TODO(nhiroki): Delete ResourceRecords tied with this registration. | 363 // TODO(nhiroki): Delete ResourceRecords tied with this registration. |
350 return WriteBatch(&batch); | 364 return WriteBatch(&batch); |
351 } | 365 } |
352 | 366 |
| 367 bool ServiceWorkerDatabase::GetUncommittedResourceIds(std::set<int64>* ids) { |
| 368 return ReadResourceIds(kUncommittedResIdKeyPrefix, ids); |
| 369 } |
| 370 |
| 371 bool ServiceWorkerDatabase::WriteUncommittedResourceIds( |
| 372 const std::set<int64>& ids) { |
| 373 return WriteResourceIds(kUncommittedResIdKeyPrefix, ids); |
| 374 } |
| 375 |
| 376 bool ServiceWorkerDatabase::ClearUncommittedResourceIds( |
| 377 const std::set<int64>& ids) { |
| 378 return DeleteResourceIds(kUncommittedResIdKeyPrefix, ids); |
| 379 } |
| 380 |
| 381 bool ServiceWorkerDatabase::GetPurgeableResourceIds(std::set<int64>* ids) { |
| 382 return ReadResourceIds(kPurgeableResIdKeyPrefix, ids); |
| 383 } |
| 384 |
| 385 bool ServiceWorkerDatabase::WritePurgeableResourceIds( |
| 386 const std::set<int64>& ids) { |
| 387 return WriteResourceIds(kPurgeableResIdKeyPrefix, ids); |
| 388 } |
| 389 |
| 390 bool ServiceWorkerDatabase::ClearPurgeableResourceIds( |
| 391 const std::set<int64>& ids) { |
| 392 return DeleteResourceIds(kPurgeableResIdKeyPrefix, ids); |
| 393 } |
| 394 |
353 bool ServiceWorkerDatabase::LazyOpen(bool create_if_needed) { | 395 bool ServiceWorkerDatabase::LazyOpen(bool create_if_needed) { |
354 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); | 396 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); |
355 if (IsOpen()) | 397 if (IsOpen()) |
356 return true; | 398 return true; |
357 | 399 |
358 // Do not try to open a database if we tried and failed once. | 400 // Do not try to open a database if we tried and failed once. |
359 if (is_disabled_) | 401 if (is_disabled_) |
360 return false; | 402 return false; |
361 | 403 |
362 // When |path_| is empty, open a database in-memory. | 404 // When |path_| is empty, open a database in-memory. |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
444 RegistrationData parsed; | 486 RegistrationData parsed; |
445 if (!ParseRegistrationData(value, &parsed)) { | 487 if (!ParseRegistrationData(value, &parsed)) { |
446 HandleError(FROM_HERE, leveldb::Status::Corruption("failed to parse")); | 488 HandleError(FROM_HERE, leveldb::Status::Corruption("failed to parse")); |
447 return false; | 489 return false; |
448 } | 490 } |
449 | 491 |
450 *registration = parsed; | 492 *registration = parsed; |
451 return true; | 493 return true; |
452 } | 494 } |
453 | 495 |
| 496 bool ServiceWorkerDatabase::ReadResourceIds(const char* id_key_prefix, |
| 497 std::set<int64>* ids) { |
| 498 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); |
| 499 DCHECK(id_key_prefix); |
| 500 DCHECK(ids); |
| 501 |
| 502 if (!LazyOpen(false) || is_disabled_) |
| 503 return false; |
| 504 |
| 505 scoped_ptr<leveldb::Iterator> itr(db_->NewIterator(leveldb::ReadOptions())); |
| 506 for (itr->Seek(id_key_prefix); itr->Valid(); itr->Next()) { |
| 507 if (!itr->status().ok()) { |
| 508 HandleError(FROM_HERE, itr->status()); |
| 509 ids->clear(); |
| 510 return false; |
| 511 } |
| 512 |
| 513 std::string unprefixed; |
| 514 if (!RemovePrefix(itr->key().ToString(), id_key_prefix, &unprefixed)) |
| 515 break; |
| 516 |
| 517 int64 resource_id; |
| 518 if (!base::StringToInt64(unprefixed, &resource_id)) { |
| 519 HandleError(FROM_HERE, leveldb::Status::Corruption("failed to parse")); |
| 520 ids->clear(); |
| 521 return false; |
| 522 } |
| 523 ids->insert(resource_id); |
| 524 } |
| 525 return true; |
| 526 } |
| 527 |
| 528 bool ServiceWorkerDatabase::WriteResourceIds(const char* id_key_prefix, |
| 529 const std::set<int64>& ids) { |
| 530 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); |
| 531 DCHECK(id_key_prefix); |
| 532 |
| 533 if (!LazyOpen(true) || is_disabled_) |
| 534 return false; |
| 535 if (ids.empty()) |
| 536 return true; |
| 537 |
| 538 leveldb::WriteBatch batch; |
| 539 for (std::set<int64>::const_iterator itr = ids.begin(); |
| 540 itr != ids.end(); ++itr) { |
| 541 // Value should be empty. |
| 542 batch.Put(CreateResourceIdKey(id_key_prefix, *itr), ""); |
| 543 } |
| 544 return WriteBatch(&batch); |
| 545 } |
| 546 |
| 547 bool ServiceWorkerDatabase::DeleteResourceIds(const char* id_key_prefix, |
| 548 const std::set<int64>& ids) { |
| 549 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); |
| 550 DCHECK(id_key_prefix); |
| 551 |
| 552 if (!LazyOpen(true) || is_disabled_) |
| 553 return false; |
| 554 if (ids.empty()) |
| 555 return true; |
| 556 |
| 557 leveldb::WriteBatch batch; |
| 558 for (std::set<int64>::const_iterator itr = ids.begin(); |
| 559 itr != ids.end(); ++itr) { |
| 560 batch.Delete(CreateResourceIdKey(id_key_prefix, *itr)); |
| 561 } |
| 562 return WriteBatch(&batch); |
| 563 } |
| 564 |
454 bool ServiceWorkerDatabase::ReadDatabaseVersion(int64* db_version) { | 565 bool ServiceWorkerDatabase::ReadDatabaseVersion(int64* db_version) { |
455 std::string value; | 566 std::string value; |
456 leveldb::Status status = | 567 leveldb::Status status = |
457 db_->Get(leveldb::ReadOptions(), kDatabaseVersionKey, &value); | 568 db_->Get(leveldb::ReadOptions(), kDatabaseVersionKey, &value); |
458 if (status.IsNotFound()) { | 569 if (status.IsNotFound()) { |
459 // The database hasn't been initialized yet. | 570 // The database hasn't been initialized yet. |
460 *db_version = 0; | 571 *db_version = 0; |
461 return true; | 572 return true; |
462 } | 573 } |
463 if (!status.ok()) { | 574 if (!status.ok()) { |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
527 // TODO(nhiroki): Add an UMA histogram. | 638 // TODO(nhiroki): Add an UMA histogram. |
528 DLOG(ERROR) << "Failed at: " << from_here.ToString() | 639 DLOG(ERROR) << "Failed at: " << from_here.ToString() |
529 << " with error: " << status.ToString(); | 640 << " with error: " << status.ToString(); |
530 is_disabled_ = true; | 641 is_disabled_ = true; |
531 if (status.IsCorruption()) | 642 if (status.IsCorruption()) |
532 was_corruption_detected_ = true; | 643 was_corruption_detected_ = true; |
533 db_.reset(); | 644 db_.reset(); |
534 } | 645 } |
535 | 646 |
536 } // namespace content | 647 } // namespace content |
OLD | NEW |