summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormek <mek@chromium.org>2015-01-12 12:13:54 -0800
committerCommit bot <commit-bot@chromium.org>2015-01-12 20:14:56 +0000
commit966e2c1cd38694c28ba9d56367ea8a67a05fc071 (patch)
tree66766e2e5d315a1971cf56b3f3613feb9d6f3295
parent4220e9d120bf34bf5a8fbe84f4ce3b808ce585cd (diff)
downloadchromium_src-966e2c1cd38694c28ba9d56367ea8a67a05fc071.zip
chromium_src-966e2c1cd38694c28ba9d56367ea8a67a05fc071.tar.gz
chromium_src-966e2c1cd38694c28ba9d56367ea8a67a05fc071.tar.bz2
Add method and storage to get a ServiceWorkerRegistration from ID only.
BUG=None Review URL: https://codereview.chromium.org/825763002 Cr-Commit-Position: refs/heads/master@{#311094}
-rw-r--r--content/browser/service_worker/service_worker_database.cc112
-rw-r--r--content/browser/service_worker/service_worker_database.h10
-rw-r--r--content/browser/service_worker/service_worker_database_unittest.cc95
-rw-r--r--content/browser/service_worker/service_worker_storage.cc67
-rw-r--r--content/browser/service_worker/service_worker_storage.h13
-rw-r--r--content/browser/service_worker/service_worker_storage_unittest.cc36
6 files changed, 324 insertions, 9 deletions
diff --git a/content/browser/service_worker/service_worker_database.cc b/content/browser/service_worker/service_worker_database.cc
index b6eaeeb..2d0e2f2 100644
--- a/content/browser/service_worker/service_worker_database.cc
+++ b/content/browser/service_worker/service_worker_database.cc
@@ -66,7 +66,11 @@
//
// key: "URES:" + <int64 'uncommitted_resource_id'>
// value: <empty>
-
+//
+// Version 2
+//
+// key: "REGID_TO_ORIGIN:" + <int64 'registration_id'>
+// value: <GURL 'origin'>
namespace content {
namespace {
@@ -80,13 +84,14 @@ const char kUniqueOriginKey[] = "INITDATA_UNIQUE_ORIGIN:";
const char kRegKeyPrefix[] = "REG:";
const char kRegUserDataKeyPrefix[] = "REG_USER_DATA:";
const char kRegHasUserDataKeyPrefix[] = "REG_HAS_USER_DATA:";
+const char kRegIdToOriginKeyPrefix[] = "REGID_TO_ORIGIN:";
const char kResKeyPrefix[] = "RES:";
const char kKeySeparator = '\x00';
const char kUncommittedResIdKeyPrefix[] = "URES:";
const char kPurgeableResIdKeyPrefix[] = "PRES:";
-const int64 kCurrentSchemaVersion = 1;
+const int64 kCurrentSchemaVersion = 2;
bool RemovePrefix(const std::string& str,
const std::string& prefix,
@@ -152,6 +157,11 @@ std::string CreateHasUserDataKey(int64 registration_id,
.append(base::Int64ToString(registration_id));
}
+std::string CreateRegistrationIdToOriginKey(int64 registration_id) {
+ return base::StringPrintf("%s%s", kRegIdToOriginKeyPrefix,
+ base::Int64ToString(registration_id).c_str());
+}
+
void PutRegistrationDataToBatch(
const ServiceWorkerDatabase::RegistrationData& input,
leveldb::WriteBatch* batch) {
@@ -523,6 +533,40 @@ ServiceWorkerDatabase::Status ServiceWorkerDatabase::ReadRegistration(
return STATUS_OK;
}
+ServiceWorkerDatabase::Status ServiceWorkerDatabase::ReadRegistrationOrigin(
+ int64 registration_id,
+ GURL* origin) {
+ DCHECK(sequence_checker_.CalledOnValidSequencedThread());
+ DCHECK(origin);
+
+ Status status = LazyOpen(true);
+ if (IsNewOrNonexistentDatabase(status))
+ return STATUS_ERROR_NOT_FOUND;
+ if (status != STATUS_OK)
+ return status;
+
+ std::string value;
+ status = LevelDBStatusToStatus(
+ db_->Get(leveldb::ReadOptions(),
+ CreateRegistrationIdToOriginKey(registration_id), &value));
+ if (status != STATUS_OK) {
+ HandleReadResult(FROM_HERE,
+ status == STATUS_ERROR_NOT_FOUND ? STATUS_OK : status);
+ return status;
+ }
+
+ GURL parsed(value);
+ if (!parsed.is_valid()) {
+ status = STATUS_ERROR_CORRUPTED;
+ HandleReadResult(FROM_HERE, status);
+ return status;
+ }
+
+ *origin = parsed;
+ HandleReadResult(FROM_HERE, STATUS_OK);
+ return STATUS_OK;
+}
+
ServiceWorkerDatabase::Status ServiceWorkerDatabase::WriteRegistration(
const RegistrationData& registration,
const std::vector<ResourceRecord>& resources,
@@ -550,6 +594,8 @@ ServiceWorkerDatabase::Status ServiceWorkerDatabase::WriteRegistration(
<< "sizes of the resources.";
#endif
PutRegistrationDataToBatch(registration, &batch);
+ batch.Put(CreateRegistrationIdToOriginKey(registration.registration_id),
+ registration.scope.GetOrigin().spec());
// Used for avoiding multiple writes for the same resource id or url.
std::set<int64> pushed_resources;
@@ -680,6 +726,7 @@ ServiceWorkerDatabase::Status ServiceWorkerDatabase::DeleteRegistration(
// Delete a registration specified by |registration_id|.
batch.Delete(CreateRegistrationKey(registration_id, origin));
+ batch.Delete(CreateRegistrationIdToOriginKey(registration_id));
// Delete resource records and user data associated with the registration.
for (const auto& registration : registrations) {
@@ -892,6 +939,7 @@ ServiceWorkerDatabase::Status ServiceWorkerDatabase::DeleteAllDataForOrigins(
// Delete registrations, resource records and user data.
for (const RegistrationData& data : registrations) {
batch.Delete(CreateRegistrationKey(data.registration_id, origin));
+ batch.Delete(CreateRegistrationIdToOriginKey(data.registration_id));
status = DeleteResourceRecords(
data.version_id, newly_purgeable_resources, &batch);
@@ -970,6 +1018,21 @@ ServiceWorkerDatabase::Status ServiceWorkerDatabase::LazyOpen(
if (status != STATUS_OK)
return status;
DCHECK_LE(0, db_version);
+
+ if (db_version > 0 && db_version < kCurrentSchemaVersion) {
+ switch (db_version) {
+ case 1:
+ status = UpgradeDatabaseSchemaFromV1ToV2();
+ if (status != STATUS_OK)
+ return status;
+ db_version = 2;
+ // Intentionally fall-through to other version upgrade cases.
+ }
+ // Either the database got upgraded to the current schema version, or some
+ // upgrade step failed which would have caused this method to abort.
+ DCHECK_EQ(db_version, kCurrentSchemaVersion);
+ }
+
if (db_version > 0)
state_ = INITIALIZED;
return STATUS_OK;
@@ -984,6 +1047,51 @@ bool ServiceWorkerDatabase::IsNewOrNonexistentDatabase(
return false;
}
+ServiceWorkerDatabase::Status
+ServiceWorkerDatabase::UpgradeDatabaseSchemaFromV1ToV2() {
+ Status status = STATUS_OK;
+ leveldb::WriteBatch batch;
+
+ // Version 2 introduced REGID_TO_ORIGIN, add for all existing registrations.
+ scoped_ptr<leveldb::Iterator> itr(db_->NewIterator(leveldb::ReadOptions()));
+ for (itr->Seek(kRegKeyPrefix); itr->Valid(); itr->Next()) {
+ status = LevelDBStatusToStatus(itr->status());
+ if (status != STATUS_OK) {
+ HandleReadResult(FROM_HERE, status);
+ return status;
+ }
+
+ std::string key;
+ if (!RemovePrefix(itr->key().ToString(), kRegKeyPrefix, &key))
+ break;
+
+ std::vector<std::string> parts;
+ base::SplitStringDontTrim(key, kKeySeparator, &parts);
+ if (parts.size() != 2) {
+ status = STATUS_ERROR_CORRUPTED;
+ HandleReadResult(FROM_HERE, status);
+ return status;
+ }
+
+ int64 registration_id;
+ status = ParseId(parts[1], &registration_id);
+ if (status != STATUS_OK) {
+ HandleReadResult(FROM_HERE, status);
+ return status;
+ }
+
+ batch.Put(CreateRegistrationIdToOriginKey(registration_id), parts[0]);
+ }
+
+ // Update schema version manually instead of relying on WriteBatch to make
+ // sure each upgrade step only updates it to the actually correct version.
+ batch.Put(kDatabaseVersionKey, base::Int64ToString(2));
+ status = LevelDBStatusToStatus(
+ db_->Write(leveldb::WriteOptions(), &batch));
+ HandleWriteResult(FROM_HERE, status);
+ return status;
+}
+
ServiceWorkerDatabase::Status ServiceWorkerDatabase::ReadNextAvailableId(
const char* id_key,
int64* next_avail_id) {
diff --git a/content/browser/service_worker/service_worker_database.h b/content/browser/service_worker/service_worker_database.h
index 0c88925..13c0ed4 100644
--- a/content/browser/service_worker/service_worker_database.h
+++ b/content/browser/service_worker/service_worker_database.h
@@ -121,6 +121,11 @@ class CONTENT_EXPORT ServiceWorkerDatabase {
RegistrationData* registration,
std::vector<ResourceRecord>* resources);
+ // Looks up the origin for the registration with |registration_id|. Returns OK
+ // if a registration was found and read successfully. Otherwise, returns an
+ // error.
+ Status ReadRegistrationOrigin(int64 registration_id, GURL* origin);
+
// Writes |registration| and |resources| into the database and does following
// things:
// - If an old version of the registration exists, deletes it and sets
@@ -242,6 +247,10 @@ class CONTENT_EXPORT ServiceWorkerDatabase {
// the database is new or nonexistent, that is, it has never been used.
bool IsNewOrNonexistentDatabase(Status status);
+ // Upgrades the database schema from version 1 to version 2. Called by
+ // LazyOpen() when the stored schema is older than version 2.
+ Status UpgradeDatabaseSchemaFromV1ToV2();
+
// Reads the next available id for |id_key|. Returns OK if it's successfully
// read. Fills |next_avail_id| with an initial value and returns OK if it's
// not found in the database. Otherwise, returns an error.
@@ -367,6 +376,7 @@ class CONTENT_EXPORT ServiceWorkerDatabase {
FRIEND_TEST_ALL_PREFIXES(ServiceWorkerDatabaseTest,
UserData_UninitializedDatabase);
FRIEND_TEST_ALL_PREFIXES(ServiceWorkerDatabaseTest, DestroyDatabase);
+ FRIEND_TEST_ALL_PREFIXES(ServiceWorkerDatabaseTest, UpgradeSchemaToVersion2);
DISALLOW_COPY_AND_ASSIGN(ServiceWorkerDatabase);
};
diff --git a/content/browser/service_worker/service_worker_database_unittest.cc b/content/browser/service_worker/service_worker_database_unittest.cc
index fb79827..e67a5ba 100644
--- a/content/browser/service_worker/service_worker_database_unittest.cc
+++ b/content/browser/service_worker/service_worker_database_unittest.cc
@@ -9,9 +9,11 @@
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/stl_util.h"
+#include "base/strings/string_number_conversions.h"
#include "content/browser/service_worker/service_worker_database.pb.h"
#include "content/common/service_worker/service_worker_types.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/leveldatabase/src/include/leveldb/write_batch.h"
namespace content {
@@ -132,6 +134,62 @@ TEST(ServiceWorkerDatabaseTest, DatabaseVersion) {
EXPECT_LT(0, db_version);
}
+TEST(ServiceWorkerDatabaseTest, UpgradeSchemaToVersion2) {
+ base::ScopedTempDir database_dir;
+ ASSERT_TRUE(database_dir.CreateUniqueTempDir());
+ scoped_ptr<ServiceWorkerDatabase> database(
+ CreateDatabase(database_dir.path()));
+
+ GURL origin("http://example.com");
+
+ // Add a registration to the database.
+ std::vector<ServiceWorkerDatabase::ResourceRecord> resources;
+ ServiceWorkerDatabase::RegistrationData deleted_version;
+ std::vector<int64> newly_purgeable_resources;
+ ServiceWorkerDatabase::RegistrationData data;
+ data.registration_id = 100;
+ data.scope = URL(origin, "/foo");
+ data.script = URL(origin, "/script1.js");
+ data.version_id = 200;
+ ASSERT_EQ(ServiceWorkerDatabase::STATUS_OK,
+ database->WriteRegistration(data, resources, &deleted_version,
+ &newly_purgeable_resources));
+
+ // Sanity check on current version.
+ int64 db_version = -1;
+ EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
+ database->ReadDatabaseVersion(&db_version));
+ EXPECT_LE(2, db_version);
+
+ // Now delete the data that will be created in an upgrade to schema version 2,
+ // and reset the schema version to 1.
+ leveldb::WriteBatch batch;
+ batch.Delete("REGID_TO_ORIGIN:" + base::Int64ToString(data.registration_id));
+ batch.Put("INITDATA_DB_VERSION", base::Int64ToString(1));
+ ASSERT_EQ(ServiceWorkerDatabase::STATUS_OK, database->WriteBatch(&batch));
+
+ // Make sure correct data got deleted.
+ GURL origin_out;
+ EXPECT_EQ(
+ ServiceWorkerDatabase::STATUS_ERROR_NOT_FOUND,
+ database->ReadRegistrationOrigin(data.registration_id, &origin_out));
+
+ // Close and reopen the database to verify the schema got updated.
+ database.reset(CreateDatabase(database_dir.path()));
+ EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK, database->LazyOpen(true));
+
+ // Verify version number.
+ EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
+ database->ReadDatabaseVersion(&db_version));
+ EXPECT_LE(2, db_version);
+
+ // And check that looking up origin for registration works.
+ EXPECT_EQ(
+ ServiceWorkerDatabase::STATUS_OK,
+ database->ReadRegistrationOrigin(data.registration_id, &origin_out));
+ EXPECT_EQ(origin, origin_out);
+}
+
TEST(ServiceWorkerDatabaseTest, GetNextAvailableIds) {
base::ScopedTempDir database_dir;
ASSERT_TRUE(database_dir.CreateUniqueTempDir());
@@ -501,6 +559,11 @@ TEST(ServiceWorkerDatabaseTest, Registration_Basic) {
data.registration_id, origin, &data_out, &resources_out));
VerifyRegistrationData(data, data_out);
VerifyResourceRecords(resources, resources_out);
+ GURL origin_out;
+ EXPECT_EQ(
+ ServiceWorkerDatabase::STATUS_OK,
+ database->ReadRegistrationOrigin(data.registration_id, &origin_out));
+ EXPECT_EQ(origin, origin_out);
// Make sure that the resource is removed from the uncommitted list.
uncommitted_ids_out.clear();
@@ -524,6 +587,9 @@ TEST(ServiceWorkerDatabaseTest, Registration_Basic) {
database->ReadRegistration(
data.registration_id, origin, &data_out, &resources_out));
EXPECT_TRUE(resources_out.empty());
+ EXPECT_EQ(
+ ServiceWorkerDatabase::STATUS_ERROR_NOT_FOUND,
+ database->ReadRegistrationOrigin(data.registration_id, &origin_out));
// Resources should be purgeable because these are no longer referred.
std::set<int64> purgeable_ids_out;
@@ -698,6 +764,11 @@ TEST(ServiceWorkerDatabaseTest, Registration_Multiple) {
data1.registration_id, origin, &data_out, &resources_out));
VerifyRegistrationData(data1, data_out);
VerifyResourceRecords(resources1, resources_out);
+ GURL origin_out;
+ EXPECT_EQ(
+ ServiceWorkerDatabase::STATUS_OK,
+ database->ReadRegistrationOrigin(data1.registration_id, &origin_out));
+ EXPECT_EQ(origin, origin_out);
// Make sure that registration2 is also stored.
resources_out.clear();
@@ -705,6 +776,10 @@ TEST(ServiceWorkerDatabaseTest, Registration_Multiple) {
data2.registration_id, origin, &data_out, &resources_out));
VerifyRegistrationData(data2, data_out);
VerifyResourceRecords(resources2, resources_out);
+ EXPECT_EQ(
+ ServiceWorkerDatabase::STATUS_OK,
+ database->ReadRegistrationOrigin(data2.registration_id, &origin_out));
+ EXPECT_EQ(origin, origin_out);
std::set<int64> purgeable_ids_out;
EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
@@ -725,6 +800,9 @@ TEST(ServiceWorkerDatabaseTest, Registration_Multiple) {
database->ReadRegistration(
data1.registration_id, origin, &data_out, &resources_out));
EXPECT_TRUE(resources_out.empty());
+ EXPECT_EQ(
+ ServiceWorkerDatabase::STATUS_ERROR_NOT_FOUND,
+ database->ReadRegistrationOrigin(data1.registration_id, &origin_out));
purgeable_ids_out.clear();
EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
@@ -739,6 +817,10 @@ TEST(ServiceWorkerDatabaseTest, Registration_Multiple) {
data2.registration_id, origin, &data_out, &resources_out));
VerifyRegistrationData(data2, data_out);
VerifyResourceRecords(resources2, resources_out);
+ EXPECT_EQ(
+ ServiceWorkerDatabase::STATUS_OK,
+ database->ReadRegistrationOrigin(data2.registration_id, &origin_out));
+ EXPECT_EQ(origin, origin_out);
}
TEST(ServiceWorkerDatabaseTest, Registration_UninitializedDatabase) {
@@ -753,6 +835,9 @@ TEST(ServiceWorkerDatabaseTest, Registration_UninitializedDatabase) {
100, origin, &data_out, &resources_out));
EXPECT_EQ(kInvalidServiceWorkerRegistrationId, data_out.registration_id);
EXPECT_TRUE(resources_out.empty());
+ GURL origin_out;
+ EXPECT_EQ(ServiceWorkerDatabase::STATUS_ERROR_NOT_FOUND,
+ database->ReadRegistrationOrigin(100, &origin_out));
// Deleting non-existent registration should succeed.
RegistrationData deleted_version;
@@ -773,6 +858,8 @@ TEST(ServiceWorkerDatabaseTest, Registration_UninitializedDatabase) {
100, origin, &data_out, &resources_out));
EXPECT_EQ(kInvalidServiceWorkerRegistrationId, data_out.registration_id);
EXPECT_TRUE(resources_out.empty());
+ EXPECT_EQ(ServiceWorkerDatabase::STATUS_ERROR_NOT_FOUND,
+ database->ReadRegistrationOrigin(100, &origin_out));
// Deleting non-existent registration should succeed.
EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
@@ -1349,6 +1436,10 @@ TEST(ServiceWorkerDatabaseTest, DeleteAllDataForOrigin) {
EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
database->GetRegistrationsForOrigin(origin1, &registrations));
EXPECT_TRUE(registrations.empty());
+ GURL origin_out;
+ EXPECT_EQ(
+ ServiceWorkerDatabase::STATUS_ERROR_NOT_FOUND,
+ database->ReadRegistrationOrigin(data1.registration_id, &origin_out));
// The registration for |origin2| should not be removed.
RegistrationData data_out;
@@ -1357,6 +1448,10 @@ TEST(ServiceWorkerDatabaseTest, DeleteAllDataForOrigin) {
data3.registration_id, origin2, &data_out, &resources_out));
VerifyRegistrationData(data3, data_out);
VerifyResourceRecords(resources3, resources_out);
+ EXPECT_EQ(
+ ServiceWorkerDatabase::STATUS_OK,
+ database->ReadRegistrationOrigin(data3.registration_id, &origin_out));
+ EXPECT_EQ(origin2, origin_out);
// The resources associated with |origin1| should be purgeable.
std::set<int64> purgeable_ids_out;
diff --git a/content/browser/service_worker/service_worker_storage.cc b/content/browser/service_worker/service_worker_storage.cc
index 5e4e315..7c998c6 100644
--- a/content/browser/service_worker/service_worker_storage.cc
+++ b/content/browser/service_worker/service_worker_storage.cc
@@ -39,6 +39,11 @@ void CompleteFindNow(
const scoped_refptr<ServiceWorkerRegistration>& registration,
ServiceWorkerStatusCode status,
const ServiceWorkerStorage::FindRegistrationCallback& callback) {
+ if (registration && registration->is_deleted()) {
+ // It's past the point of no return and no longer findable.
+ callback.Run(SERVICE_WORKER_ERROR_NOT_FOUND, nullptr);
+ return;
+ }
callback.Run(status, registration);
}
@@ -47,7 +52,8 @@ void CompleteFindSoon(
const scoped_refptr<ServiceWorkerRegistration>& registration,
ServiceWorkerStatusCode status,
const ServiceWorkerStorage::FindRegistrationCallback& callback) {
- RunSoon(from_here, base::Bind(callback, status, registration));
+ RunSoon(from_here,
+ base::Bind(&CompleteFindNow, registration, status, callback));
}
const base::FilePath::CharType kDatabaseName[] =
@@ -412,6 +418,39 @@ void ServiceWorkerStorage::FindRegistrationForId(
weak_factory_.GetWeakPtr(), callback)));
}
+void ServiceWorkerStorage::FindRegistrationForIdOnly(
+ int64 registration_id,
+ const FindRegistrationCallback& callback) {
+ if (!LazyInitialize(
+ base::Bind(&ServiceWorkerStorage::FindRegistrationForIdOnly,
+ weak_factory_.GetWeakPtr(), registration_id, callback))) {
+ if (state_ != INITIALIZING || !context_) {
+ CompleteFindNow(nullptr, SERVICE_WORKER_ERROR_FAILED, callback);
+ }
+ return;
+ }
+ DCHECK_EQ(INITIALIZED, state_);
+
+ scoped_refptr<ServiceWorkerRegistration> registration =
+ context_->GetLiveRegistration(registration_id);
+ if (registration) {
+ // Delegate to FindRegistrationForId to make sure the same subset of live
+ // registrations is returned.
+ // TODO(mek): CompleteFindNow should really do all the required checks, so
+ // calling that directly here should be enough.
+ FindRegistrationForId(registration_id, registration->pattern().GetOrigin(),
+ callback);
+ return;
+ }
+
+ database_task_manager_->GetTaskRunner()->PostTask(
+ FROM_HERE,
+ base::Bind(&FindForIdOnlyInDB, database_.get(),
+ base::MessageLoopProxy::current(), registration_id,
+ base::Bind(&ServiceWorkerStorage::DidFindRegistrationForId,
+ weak_factory_.GetWeakPtr(), callback)));
+}
+
void ServiceWorkerStorage::GetRegistrationsForOrigin(
const GURL& origin, const GetRegistrationsInfosCallback& callback) {
if (!LazyInitialize(base::Bind(
@@ -1033,12 +1072,7 @@ void ServiceWorkerStorage::ReturnFoundRegistration(
const ResourceList& resources) {
scoped_refptr<ServiceWorkerRegistration> registration =
GetOrCreateRegistration(data, resources);
- if (registration->is_deleted()) {
- // It's past the point of no return and no longer findable.
- callback.Run(SERVICE_WORKER_ERROR_NOT_FOUND, NULL);
- return;
- }
- callback.Run(SERVICE_WORKER_OK, registration);
+ CompleteFindNow(registration, SERVICE_WORKER_OK, callback);
}
void ServiceWorkerStorage::DidGetRegistrations(
@@ -1634,6 +1668,25 @@ void ServiceWorkerStorage::FindForIdInDB(
FROM_HERE, base::Bind(callback, data, resources, status));
}
+void ServiceWorkerStorage::FindForIdOnlyInDB(
+ ServiceWorkerDatabase* database,
+ scoped_refptr<base::SequencedTaskRunner> original_task_runner,
+ int64 registration_id,
+ const FindInDBCallback& callback) {
+ GURL origin;
+ ServiceWorkerDatabase::Status status =
+ database->ReadRegistrationOrigin(registration_id, &origin);
+ if (status != ServiceWorkerDatabase::STATUS_OK) {
+ original_task_runner->PostTask(
+ FROM_HERE,
+ base::Bind(callback, ServiceWorkerDatabase::RegistrationData(),
+ ResourceList(), status));
+ return;
+ }
+ FindForIdInDB(database, original_task_runner, registration_id, origin,
+ callback);
+}
+
void ServiceWorkerStorage::GetUserDataInDB(
ServiceWorkerDatabase* database,
scoped_refptr<base::SequencedTaskRunner> original_task_runner,
diff --git a/content/browser/service_worker/service_worker_storage.h b/content/browser/service_worker/service_worker_storage.h
index 8bf080c..623bf75 100644
--- a/content/browser/service_worker/service_worker_storage.h
+++ b/content/browser/service_worker/service_worker_storage.h
@@ -98,6 +98,14 @@ class CONTENT_EXPORT ServiceWorkerStorage
const GURL& origin,
const FindRegistrationCallback& callback);
+ // Generally |FindRegistrationForId| should be used to look up a registration
+ // by |registration_id| since it's more efficient. But if a |registration_id|
+ // is all that is available this method can be used instead.
+ // Like |FindRegistrationForId| this method may complete immediately (the
+ // callback may be called prior to the method returning) or asynchronously.
+ void FindRegistrationForIdOnly(int64 registration_id,
+ const FindRegistrationCallback& callback);
+
ServiceWorkerRegistration* GetUninstallingRegistration(const GURL& scope);
// Returns info about all stored and initially installing registrations for
@@ -406,6 +414,11 @@ class CONTENT_EXPORT ServiceWorkerStorage
int64 registration_id,
const GURL& origin,
const FindInDBCallback& callback);
+ static void FindForIdOnlyInDB(
+ ServiceWorkerDatabase* database,
+ scoped_refptr<base::SequencedTaskRunner> original_task_runner,
+ int64 registration_id,
+ const FindInDBCallback& callback);
static void GetUserDataInDB(
ServiceWorkerDatabase* database,
scoped_refptr<base::SequencedTaskRunner> original_task_runner,
diff --git a/content/browser/service_worker/service_worker_storage_unittest.cc b/content/browser/service_worker/service_worker_storage_unittest.cc
index 909bcd8..8b52207 100644
--- a/content/browser/service_worker/service_worker_storage_unittest.cc
+++ b/content/browser/service_worker/service_worker_storage_unittest.cc
@@ -416,6 +416,18 @@ class ServiceWorkerStorageTest : public testing::Test {
return result;
}
+ ServiceWorkerStatusCode FindRegistrationForIdOnly(
+ int64 registration_id,
+ scoped_refptr<ServiceWorkerRegistration>* registration) {
+ bool was_called = false;
+ ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_FAILED;
+ storage()->FindRegistrationForIdOnly(
+ registration_id, MakeFindCallback(&was_called, &result, registration));
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(was_called);
+ return result;
+ }
+
scoped_ptr<ServiceWorkerContextCore> context_;
base::WeakPtr<ServiceWorkerContextCore> context_ptr_;
TestBrowserThreadBundle browser_thread_bundle_;
@@ -495,6 +507,14 @@ TEST_F(ServiceWorkerStorageTest, StoreFindUpdateDeleteRegistration) {
EXPECT_EQ(live_registration, found_registration);
found_registration = NULL;
+ // Can be found by just the id too.
+ EXPECT_EQ(SERVICE_WORKER_OK,
+ FindRegistrationForIdOnly(kRegistrationId, &found_registration));
+ ASSERT_TRUE(found_registration.get());
+ EXPECT_EQ(kRegistrationId, found_registration->id());
+ EXPECT_EQ(live_registration, found_registration);
+ found_registration = NULL;
+
// Drop the live registration, but keep the version live.
live_registration = NULL;
@@ -588,6 +608,9 @@ TEST_F(ServiceWorkerStorageTest, StoreFindUpdateDeleteRegistration) {
FindRegistrationForId(
kRegistrationId, kScope.GetOrigin(), &found_registration));
EXPECT_FALSE(found_registration.get());
+ EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND,
+ FindRegistrationForIdOnly(kRegistrationId, &found_registration));
+ EXPECT_FALSE(found_registration.get());
// Deleting an unstored registration should succeed.
EXPECT_EQ(SERVICE_WORKER_OK,
@@ -620,6 +643,10 @@ TEST_F(ServiceWorkerStorageTest, InstallingRegistrationsAreFindable) {
EXPECT_FALSE(found_registration.get());
EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND,
+ FindRegistrationForIdOnly(kRegistrationId, &found_registration));
+ EXPECT_FALSE(found_registration.get());
+
+ EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND,
FindRegistrationForDocument(kDocumentUrl, &found_registration));
EXPECT_FALSE(found_registration.get());
@@ -651,6 +678,11 @@ TEST_F(ServiceWorkerStorageTest, InstallingRegistrationsAreFindable) {
found_registration = NULL;
EXPECT_EQ(SERVICE_WORKER_OK,
+ FindRegistrationForIdOnly(kRegistrationId, &found_registration));
+ EXPECT_EQ(live_registration, found_registration);
+ found_registration = NULL;
+
+ EXPECT_EQ(SERVICE_WORKER_OK,
FindRegistrationForDocument(kDocumentUrl, &found_registration));
EXPECT_EQ(live_registration, found_registration);
found_registration = NULL;
@@ -685,6 +717,10 @@ TEST_F(ServiceWorkerStorageTest, InstallingRegistrationsAreFindable) {
EXPECT_FALSE(found_registration.get());
EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND,
+ FindRegistrationForIdOnly(kRegistrationId, &found_registration));
+ EXPECT_FALSE(found_registration.get());
+
+ EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND,
FindRegistrationForDocument(kDocumentUrl, &found_registration));
EXPECT_FALSE(found_registration.get());