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

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

Issue 254733002: ServiceWorker: Manipulate uncommitted/purgeable resource ids (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: address comments Created 6 years, 7 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"
(...skipping 24 matching lines...) Expand all
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
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 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
369 if (!LazyOpen(false) || is_disabled_)
370 return false;
371 return ReadResourceIds(kUncommittedResIdKeyPrefix, ids);
372 }
373
374 bool ServiceWorkerDatabase::WriteUncommittedResourceIds(
375 const std::set<int64>& ids) {
376 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
377 if (!LazyOpen(true) || is_disabled_)
378 return false;
379 return WriteResourceIds(kUncommittedResIdKeyPrefix, ids);
380 }
381
382 bool ServiceWorkerDatabase::ClearUncommittedResourceIds(
383 const std::set<int64>& ids) {
384 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
385 if (!LazyOpen(true) || is_disabled_)
386 return false;
387 return DeleteResourceIds(kUncommittedResIdKeyPrefix, ids);
388 }
389
390 bool ServiceWorkerDatabase::GetPurgeableResourceIds(std::set<int64>* ids) {
391 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
392 if (!LazyOpen(false) || is_disabled_)
393 return false;
394 return ReadResourceIds(kPurgeableResIdKeyPrefix, ids);
395 }
396
397 bool ServiceWorkerDatabase::WritePurgeableResourceIds(
398 const std::set<int64>& ids) {
399 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
400 if (!LazyOpen(true) || is_disabled_)
401 return false;
402 return WriteResourceIds(kPurgeableResIdKeyPrefix, ids);
403 }
404
405 bool ServiceWorkerDatabase::ClearPurgeableResourceIds(
406 const std::set<int64>& ids) {
407 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
408 if (!LazyOpen(true) || is_disabled_)
michaeln 2014/04/30 03:23:57 These tests and the dcheck could also be in the co
nhiroki 2014/04/30 04:04:06 That's just my preference. Basically I prefer such
409 return false;
410 return DeleteResourceIds(kPurgeableResIdKeyPrefix, ids);
411 }
412
353 bool ServiceWorkerDatabase::LazyOpen(bool create_if_needed) { 413 bool ServiceWorkerDatabase::LazyOpen(bool create_if_needed) {
354 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 414 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
355 if (IsOpen()) 415 if (IsOpen())
356 return true; 416 return true;
357 417
358 // Do not try to open a database if we tried and failed once. 418 // Do not try to open a database if we tried and failed once.
359 if (is_disabled_) 419 if (is_disabled_)
360 return false; 420 return false;
361 421
362 // When |path_| is empty, open a database in-memory. 422 // When |path_| is empty, open a database in-memory.
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
444 RegistrationData parsed; 504 RegistrationData parsed;
445 if (!ParseRegistrationData(value, &parsed)) { 505 if (!ParseRegistrationData(value, &parsed)) {
446 HandleError(FROM_HERE, leveldb::Status::Corruption("failed to parse")); 506 HandleError(FROM_HERE, leveldb::Status::Corruption("failed to parse"));
447 return false; 507 return false;
448 } 508 }
449 509
450 *registration = parsed; 510 *registration = parsed;
451 return true; 511 return true;
452 } 512 }
453 513
514 bool ServiceWorkerDatabase::ReadResourceIds(const char* id_key_prefix,
515 std::set<int64>* ids) {
516 DCHECK(id_key_prefix);
517 DCHECK(ids);
518
519 scoped_ptr<leveldb::Iterator> itr(db_->NewIterator(leveldb::ReadOptions()));
520 for (itr->Seek(id_key_prefix); itr->Valid(); itr->Next()) {
521 if (!itr->status().ok()) {
522 HandleError(FROM_HERE, itr->status());
523 ids->clear();
524 return false;
525 }
526
527 std::string unprefixed;
528 if (!RemovePrefix(itr->key().ToString(), id_key_prefix, &unprefixed))
529 break;
530
531 int64 resource_id;
532 if (!base::StringToInt64(unprefixed, &resource_id)) {
533 HandleError(FROM_HERE, leveldb::Status::Corruption("failed to parse"));
534 ids->clear();
535 return false;
536 }
537 ids->insert(resource_id);
538 }
539 return true;
540 }
541
542 bool ServiceWorkerDatabase::WriteResourceIds(const char* id_key_prefix,
543 const std::set<int64>& ids) {
544 DCHECK(id_key_prefix);
545 if (ids.empty())
546 return true;
547 leveldb::WriteBatch batch;
548 for (std::set<int64>::const_iterator itr = ids.begin();
549 itr != ids.end(); ++itr) {
550 // Value should be empty.
551 batch.Put(CreateResourceIdKey(id_key_prefix, *itr), "");
552 }
553 return WriteBatch(&batch);
554 }
555
556 bool ServiceWorkerDatabase::DeleteResourceIds(const char* id_key_prefix,
557 const std::set<int64>& ids) {
558 DCHECK(id_key_prefix);
559 if (ids.empty())
560 return true;
561 leveldb::WriteBatch batch;
562 for (std::set<int64>::const_iterator itr = ids.begin();
563 itr != ids.end(); ++itr) {
564 batch.Delete(CreateResourceIdKey(id_key_prefix, *itr));
565 }
566 return WriteBatch(&batch);
567 }
568
454 bool ServiceWorkerDatabase::ReadDatabaseVersion(int64* db_version) { 569 bool ServiceWorkerDatabase::ReadDatabaseVersion(int64* db_version) {
455 std::string value; 570 std::string value;
456 leveldb::Status status = 571 leveldb::Status status =
457 db_->Get(leveldb::ReadOptions(), kDatabaseVersionKey, &value); 572 db_->Get(leveldb::ReadOptions(), kDatabaseVersionKey, &value);
458 if (status.IsNotFound()) { 573 if (status.IsNotFound()) {
459 // The database hasn't been initialized yet. 574 // The database hasn't been initialized yet.
460 *db_version = 0; 575 *db_version = 0;
461 return true; 576 return true;
462 } 577 }
463 if (!status.ok()) { 578 if (!status.ok()) {
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
527 // TODO(nhiroki): Add an UMA histogram. 642 // TODO(nhiroki): Add an UMA histogram.
528 DLOG(ERROR) << "Failed at: " << from_here.ToString() 643 DLOG(ERROR) << "Failed at: " << from_here.ToString()
529 << " with error: " << status.ToString(); 644 << " with error: " << status.ToString();
530 is_disabled_ = true; 645 is_disabled_ = true;
531 if (status.IsCorruption()) 646 if (status.IsCorruption())
532 was_corruption_detected_ = true; 647 was_corruption_detected_ = true;
533 db_.reset(); 648 db_.reset();
534 } 649 }
535 650
536 } // namespace content 651 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698