Commit f1651c4a authored by michaeln@chromium.org's avatar michaeln@chromium.org

Store the service worker script and its imports on first load, read them on...

Store the service worker script and its imports on first load, read them on subsequent loads. The list of resource ids is stored with registration data. As registrations are deleted the old resources are also deleted.

BUG=364247,364318

Review URL: https://codereview.chromium.org/293483002

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@272418 0039d316-1c4b-4281-b951-d872f2087c98
parent 130f11a9
......@@ -412,7 +412,8 @@ ServiceWorkerDatabase::Status ServiceWorkerDatabase::ReadRegistration(
ServiceWorkerDatabase::Status ServiceWorkerDatabase::WriteRegistration(
const RegistrationData& registration,
const std::vector<ResourceRecord>& resources) {
const std::vector<ResourceRecord>& resources,
std::vector<int64>* newly_purgeable_resources) {
DCHECK(sequence_checker_.CalledOnValidSequencedThread());
Status status = LazyOpen(true);
if (status != STATUS_OK)
......@@ -441,7 +442,8 @@ ServiceWorkerDatabase::Status ServiceWorkerDatabase::WriteRegistration(
// suppported, so resource ids should not be overlapped between
// |registration| and |old_registration|.
// TODO(nhiroki): Add DCHECK to make sure the overlap does not exist.
status = DeleteResourceRecords(old_registration.version_id, &batch);
status = DeleteResourceRecords(
old_registration.version_id, newly_purgeable_resources, &batch);
if (status != STATUS_OK)
return status;
}
......@@ -519,7 +521,8 @@ ServiceWorkerDatabase::Status ServiceWorkerDatabase::UpdateLastCheckTime(
ServiceWorkerDatabase::Status ServiceWorkerDatabase::DeleteRegistration(
int64 registration_id,
const GURL& origin) {
const GURL& origin,
std::vector<int64>* newly_purgeable_resources) {
DCHECK(sequence_checker_.CalledOnValidSequencedThread());
Status status = LazyOpen(false);
if (IsNewOrNonexistentDatabase(status))
......@@ -551,7 +554,8 @@ ServiceWorkerDatabase::Status ServiceWorkerDatabase::DeleteRegistration(
for (std::vector<RegistrationData>::const_iterator itr =
registrations.begin(); itr != registrations.end(); ++itr) {
if (itr->registration_id == registration_id) {
status = DeleteResourceRecords(itr->version_id, &batch);
status = DeleteResourceRecords(
itr->version_id, newly_purgeable_resources, &batch);
if (status != STATUS_OK)
return status;
break;
......@@ -592,7 +596,8 @@ ServiceWorkerDatabase::ClearPurgeableResourceIds(const std::set<int64>& ids) {
}
ServiceWorkerDatabase::Status ServiceWorkerDatabase::DeleteAllDataForOrigin(
const GURL& origin) {
const GURL& origin,
std::vector<int64>* newly_purgeable_resources) {
DCHECK(sequence_checker_.CalledOnValidSequencedThread());
Status status = LazyOpen(false);
if (IsNewOrNonexistentDatabase(status))
......@@ -616,7 +621,8 @@ ServiceWorkerDatabase::Status ServiceWorkerDatabase::DeleteAllDataForOrigin(
for (std::vector<RegistrationData>::const_iterator itr =
registrations.begin(); itr != registrations.end(); ++itr) {
batch.Delete(CreateRegistrationKey(itr->registration_id, origin));
status = DeleteResourceRecords(itr->version_id, &batch);
status = DeleteResourceRecords(
itr->version_id, newly_purgeable_resources, &batch);
if (status != STATUS_OK)
return status;
}
......@@ -768,6 +774,7 @@ ServiceWorkerDatabase::Status ServiceWorkerDatabase::ReadResourceRecords(
ServiceWorkerDatabase::Status ServiceWorkerDatabase::DeleteResourceRecords(
int64 version_id,
std::vector<int64>* newly_purgeable_resources,
leveldb::WriteBatch* batch) {
DCHECK(batch);
......@@ -796,6 +803,7 @@ ServiceWorkerDatabase::Status ServiceWorkerDatabase::DeleteResourceRecords(
// Currently resource sharing across versions and registrations is not
// supported, so we can purge this without caring about it.
PutPurgeableResourceIdToBatch(resource_id, batch);
newly_purgeable_resources->push_back(resource_id);
}
return STATUS_OK;
}
......
......@@ -67,6 +67,9 @@ class CONTENT_EXPORT ServiceWorkerDatabase {
struct ResourceRecord {
int64 resource_id;
GURL url;
ResourceRecord() {}
ResourceRecord(int64 id, GURL url) : resource_id(id), url(url) {}
};
// Reads next available ids from the database. Returns OK if they are
......@@ -114,7 +117,8 @@ class CONTENT_EXPORT ServiceWorkerDatabase {
// Returns OK they are successfully written. Otherwise, returns an error.
Status WriteRegistration(
const RegistrationData& registration,
const std::vector<ResourceRecord>& resources);
const std::vector<ResourceRecord>& resources,
std::vector<int64>* newly_purgeable_resources);
// Updates a registration for |registration_id| to an active state. Returns OK
// if it's successfully updated. Otherwise, returns an error.
......@@ -134,7 +138,8 @@ class CONTENT_EXPORT ServiceWorkerDatabase {
// deleted or not found in the database. Otherwise, returns an error.
Status DeleteRegistration(
int64 registration_id,
const GURL& origin);
const GURL& origin,
std::vector<int64>* newly_purgeable_resources);
// As new resources are put into the diskcache, they go into an uncommitted
// list. When a registration is saved that refers to those ids, they're
......@@ -171,7 +176,9 @@ class CONTENT_EXPORT ServiceWorkerDatabase {
// resource records. Resources are moved to the purgeable list. Returns OK if
// they are successfully deleted or not found in the database. Otherwise,
// returns an error.
Status DeleteAllDataForOrigin(const GURL& origin);
Status DeleteAllDataForOrigin(
const GURL& origin,
std::vector<int64>* newly_purgeable_resources);
bool is_disabled() const { return is_disabled_; }
bool was_corruption_detected() const { return was_corruption_detected_; }
......@@ -214,6 +221,7 @@ class CONTENT_EXPORT ServiceWorkerDatabase {
// returns an error.
Status DeleteResourceRecords(
int64 version_id,
std::vector<int64>* newly_purgeable_resources,
leveldb::WriteBatch* batch);
// Reads resource ids for |id_key_prefix| from the database. Returns OK if
......
......@@ -16,11 +16,11 @@ namespace content {
// TODO(michaeln): If this reuse sticks, refactor/move the
// resused classes to a more common location.
class ServiceWorkerDiskCache
class CONTENT_EXPORT ServiceWorkerDiskCache
: public appcache::AppCacheDiskCache {
};
class ServiceWorkerResponseReader
class CONTENT_EXPORT ServiceWorkerResponseReader
: public appcache::AppCacheResponseReader {
protected:
// Should only be constructed by the storage class.
......@@ -30,7 +30,7 @@ class ServiceWorkerResponseReader
ServiceWorkerDiskCache* disk_cache);
};
class ServiceWorkerResponseWriter
class CONTENT_EXPORT ServiceWorkerResponseWriter
: public appcache::AppCacheResponseWriter {
protected:
// Should only be constructed by the storage class.
......@@ -40,7 +40,7 @@ class ServiceWorkerResponseWriter
ServiceWorkerDiskCache* disk_cache);
};
struct HttpResponseInfoIOBuffer
struct CONTENT_EXPORT HttpResponseInfoIOBuffer
: public appcache::HttpResponseInfoIOBuffer {
public:
HttpResponseInfoIOBuffer() : appcache::HttpResponseInfoIOBuffer() {}
......
......@@ -89,7 +89,6 @@ void ServiceWorkerRegisterJob::set_registration(
ServiceWorkerRegistration* ServiceWorkerRegisterJob::registration() {
DCHECK(phase_ >= REGISTER) << phase_;
DCHECK(internal_.registration);
return internal_.registration;
}
......
......@@ -50,8 +50,8 @@ void ServiceWorkerScriptCacheMap::GetResources(
DCHECK(resources->empty());
for (ResourceIDMap::const_iterator it = resource_ids_.begin();
it != resource_ids_.end(); ++it) {
ServiceWorkerDatabase::ResourceRecord record = { it->second, it->first };
resources->push_back(record);
resources->push_back(
ServiceWorkerDatabase::ResourceRecord(it->second, it->first));
}
}
......
......@@ -5,6 +5,7 @@
#ifndef CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_STORAGE_H_
#define CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_STORAGE_H_
#include <deque>
#include <map>
#include <set>
#include <vector>
......@@ -53,16 +54,6 @@ class CONTENT_EXPORT ServiceWorkerStorage {
void(ServiceWorkerStatusCode status, int result)>
CompareCallback;
struct InitialData {
int64 next_registration_id;
int64 next_version_id;
int64 next_resource_id;
std::set<GURL> origins;
InitialData();
~InitialData();
};
ServiceWorkerStorage(const base::FilePath& path,
base::WeakPtr<ServiceWorkerContextCore> context,
base::SequencedTaskRunner* database_task_runner,
......@@ -130,37 +121,72 @@ class CONTENT_EXPORT ServiceWorkerStorage {
private:
friend class ServiceWorkerStorageTest;
FRIEND_TEST_ALL_PREFIXES(ServiceWorkerStorageTest,
ResourceIdsAreStoredAndPurged);
struct InitialData {
int64 next_registration_id;
int64 next_version_id;
int64 next_resource_id;
std::set<GURL> origins;
InitialData();
~InitialData();
};
typedef std::vector<ServiceWorkerDatabase::RegistrationData> RegistrationList;
typedef std::vector<ServiceWorkerDatabase::ResourceRecord> ResourceList;
typedef std::map<int64, scoped_refptr<ServiceWorkerRegistration> >
RegistrationRefsById;
typedef base::Callback<void(
InitialData* data,
ServiceWorkerDatabase::Status status)> InitializeCallback;
typedef base::Callback<void(
const GURL& origin,
const std::vector<int64>& newly_purgeable_resources,
ServiceWorkerDatabase::Status status)> WriteRegistrationCallback;
typedef base::Callback<void(
bool origin_is_deletable,
const std::vector<int64>& newly_purgeable_resources,
ServiceWorkerDatabase::Status status)> DeleteRegistrationCallback;
typedef base::Callback<void(
const ServiceWorkerDatabase::RegistrationData& data,
const ResourceList& resources,
ServiceWorkerDatabase::Status status)> FindInDBCallback;
base::FilePath GetDatabasePath();
base::FilePath GetDiskCachePath();
bool LazyInitialize(
const base::Closure& callback);
void DidReadInitialData(
InitialData* data,
ServiceWorkerDatabase::Status status);
void DidGetRegistrationsForPattern(
const GURL& scope,
void DidFindRegistrationForDocument(
const GURL& document_url,
const FindRegistrationCallback& callback,
RegistrationList* registrations,
const ServiceWorkerDatabase::RegistrationData& data,
const ResourceList& resources,
ServiceWorkerDatabase::Status status);
void DidGetRegistrationsForDocument(
void DidFindRegistrationForPattern(
const GURL& scope,
const FindRegistrationCallback& callback,
RegistrationList* registrations,
const ServiceWorkerDatabase::RegistrationData& data,
const ResourceList& resources,
ServiceWorkerDatabase::Status status);
void DidReadRegistrationForId(
void DidFindRegistrationForId(
const FindRegistrationCallback& callback,
ServiceWorkerDatabase::RegistrationData* registration,
ResourceList* resources,
const ServiceWorkerDatabase::RegistrationData& data,
const ResourceList& resources,
ServiceWorkerDatabase::Status status);
void DidGetAllRegistrations(
const GetAllRegistrationInfosCallback& callback,
RegistrationList* registrations,
ServiceWorkerDatabase::Status status);
void DidStoreRegistration(
const GURL& origin,
const StatusCallback& callback,
const GURL& origin,
const std::vector<int64>& newly_purgeable_resources,
ServiceWorkerDatabase::Status status);
void DidUpdateToActiveState(
const StatusCallback& callback,
......@@ -169,10 +195,12 @@ class CONTENT_EXPORT ServiceWorkerStorage {
const GURL& origin,
const StatusCallback& callback,
bool origin_is_deletable,
const std::vector<int64>& newly_purgeable_resources,
ServiceWorkerDatabase::Status status);
scoped_refptr<ServiceWorkerRegistration> CreateRegistration(
const ServiceWorkerDatabase::RegistrationData& data);
scoped_refptr<ServiceWorkerRegistration> GetOrCreateRegistration(
const ServiceWorkerDatabase::RegistrationData& data,
const ResourceList& resources);
ServiceWorkerRegistration* FindInstallingRegistrationForDocument(
const GURL& document_url);
ServiceWorkerRegistration* FindInstallingRegistrationForPattern(
......@@ -180,13 +208,50 @@ class CONTENT_EXPORT ServiceWorkerStorage {
ServiceWorkerRegistration* FindInstallingRegistrationForId(
int64 registration_id);
// For finding registrations being installed.
typedef std::map<int64, scoped_refptr<ServiceWorkerRegistration> >
RegistrationRefsById;
RegistrationRefsById installing_registrations_;
// Lazy disk_cache getter.
ServiceWorkerDiskCache* disk_cache();
void OnDiskCacheInitialized(int rv);
void StartPurgingResources(const std::vector<int64>& ids);
void PurgeResource(int64 id);
void OnResourcePurged(int64 id, int rv);
// Static cross-thread helpers.
static void ReadInitialDataFromDB(
ServiceWorkerDatabase* database,
scoped_refptr<base::SequencedTaskRunner> original_task_runner,
const InitializeCallback& callback);
static void DeleteRegistrationFromDB(
ServiceWorkerDatabase* database,
scoped_refptr<base::SequencedTaskRunner> original_task_runner,
int64 registration_id,
const GURL& origin,
const DeleteRegistrationCallback& callback);
static void WriteRegistrationInDB(
ServiceWorkerDatabase* database,
scoped_refptr<base::SequencedTaskRunner> original_task_runner,
const ServiceWorkerDatabase::RegistrationData& registration,
const ResourceList& resources,
const WriteRegistrationCallback& callback);
static void FindForDocumentInDB(
ServiceWorkerDatabase* database,
scoped_refptr<base::SequencedTaskRunner> original_task_runner,
const GURL& document_url,
const FindInDBCallback& callback);
static void FindForPatternInDB(
ServiceWorkerDatabase* database,
scoped_refptr<base::SequencedTaskRunner> original_task_runner,
const GURL& scope,
const FindInDBCallback& callback);
static void FindForIdInDB(
ServiceWorkerDatabase* database,
scoped_refptr<base::SequencedTaskRunner> original_task_runner,
int64 registration_id,
const GURL& origin,
const FindInDBCallback& callback);
// For finding registrations being installed.
RegistrationRefsById installing_registrations_;
// Origins having registations.
std::set<GURL> registered_origins_;
......@@ -216,6 +281,8 @@ class CONTENT_EXPORT ServiceWorkerStorage {
scoped_refptr<base::MessageLoopProxy> disk_cache_thread_;
scoped_refptr<quota::QuotaManagerProxy> quota_manager_proxy_;
scoped_ptr<ServiceWorkerDiskCache> disk_cache_;
std::deque<int64> purgeable_reource_ids_;
bool is_purge_pending_;
base::WeakPtrFactory<ServiceWorkerStorage> weak_factory_;
......
......@@ -2,22 +2,32 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/browser/service_worker/service_worker_storage.h"
#include "base/logging.h"
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "content/browser/browser_thread_impl.h"
#include "content/browser/service_worker/service_worker_context_core.h"
#include "content/browser/service_worker/service_worker_disk_cache.h"
#include "content/browser/service_worker/service_worker_registration.h"
#include "content/browser/service_worker/service_worker_storage.h"
#include "content/browser/service_worker/service_worker_version.h"
#include "content/common/service_worker/service_worker_status_code.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
#include "net/http/http_response_headers.h"
#include "testing/gtest/include/gtest/gtest.h"
using net::IOBuffer;
using net::WrappedIOBuffer;
namespace content {
namespace {
typedef ServiceWorkerDatabase::RegistrationData RegistrationData;
typedef ServiceWorkerDatabase::ResourceRecord ResourceRecord;
void StatusCallback(bool* was_called,
ServiceWorkerStatusCode* result,
ServiceWorkerStatusCode status) {
......@@ -63,6 +73,74 @@ ServiceWorkerStorage::GetAllRegistrationInfosCallback MakeGetAllCallback(
return base::Bind(&GetAllCallback, was_called, all);
}
void OnIOComplete(int* rv_out, int rv) {
*rv_out = rv;
}
void WriteBasicResponse(ServiceWorkerStorage* storage, int64 id) {
scoped_ptr<ServiceWorkerResponseWriter> writer =
storage->CreateResponseWriter(id);
const char kHttpHeaders[] =
"HTTP/1.0 200 HONKYDORY\0Content-Length: 6\0\0";
const char kHttpBody[] = "Hello\0";
scoped_refptr<IOBuffer> body(new WrappedIOBuffer(kHttpBody));
std::string raw_headers(kHttpHeaders, arraysize(kHttpHeaders));
scoped_ptr<net::HttpResponseInfo> info(new net::HttpResponseInfo);
info->request_time = base::Time::Now();
info->response_time = base::Time::Now();
info->was_cached = false;
info->headers = new net::HttpResponseHeaders(raw_headers);
scoped_refptr<HttpResponseInfoIOBuffer> info_buffer =
new HttpResponseInfoIOBuffer(info.release());
int rv = -1234;
writer->WriteInfo(info_buffer, base::Bind(&OnIOComplete, &rv));
base::RunLoop().RunUntilIdle();
EXPECT_LT(0, rv);
rv = -1234;
writer->WriteData(body, arraysize(kHttpBody),
base::Bind(&OnIOComplete, &rv));
base::RunLoop().RunUntilIdle();
EXPECT_EQ(static_cast<int>(arraysize(kHttpBody)), rv);
}
bool VerifyBasicResponse(ServiceWorkerStorage* storage, int64 id,
bool expected_positive_result) {
const char kExpectedHttpBody[] = "Hello\0";
scoped_ptr<ServiceWorkerResponseReader> reader =
storage->CreateResponseReader(id);
scoped_refptr<HttpResponseInfoIOBuffer> info_buffer =
new HttpResponseInfoIOBuffer();
int rv = -1234;
reader->ReadInfo(info_buffer, base::Bind(&OnIOComplete, &rv));
base::RunLoop().RunUntilIdle();
if (expected_positive_result)
EXPECT_LT(0, rv);
if (rv <= 0)
return false;
const int kBigEnough = 512;
scoped_refptr<net::IOBuffer> buffer = new IOBuffer(kBigEnough);
rv = -1234;
reader->ReadData(buffer, kBigEnough, base::Bind(&OnIOComplete, &rv));
base::RunLoop().RunUntilIdle();
EXPECT_EQ(static_cast<int>(arraysize(kExpectedHttpBody)), rv);
if (rv <= 0)
return false;
bool status_match =
std::string("HONKYDORY") ==
info_buffer->http_info->headers->GetStatusText();
bool data_match =
std::string(kExpectedHttpBody) == std::string(buffer->data());
EXPECT_TRUE(status_match);
EXPECT_TRUE(data_match);
return status_match && data_match;
}
} // namespace
class ServiceWorkerStorageTest : public testing::Test {
......@@ -88,6 +166,19 @@ class ServiceWorkerStorageTest : public testing::Test {
ServiceWorkerStorage* storage() { return context_->storage(); }
// A static class method for friendliness.
static void VerifyPurgeableListStatusCallback(
ServiceWorkerDatabase* database,
std::set<int64> *purgeable_ids,
bool* was_called,
ServiceWorkerStatusCode* result,
ServiceWorkerStatusCode status) {
*was_called = true;
*result = status;
EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
database->GetPurgeableResourceIds(purgeable_ids));
}
protected:
scoped_ptr<ServiceWorkerContextCore> context_;
base::WeakPtr<ServiceWorkerContextCore> context_ptr_;
......@@ -95,9 +186,9 @@ class ServiceWorkerStorageTest : public testing::Test {
};
TEST_F(ServiceWorkerStorageTest, StoreFindUpdateDeleteRegistration) {
const GURL kScope("http://www.test.com/scope/*");
const GURL kScript("http://www.test.com/script.js");
const GURL kDocumentUrl("http://www.test.com/scope/document.html");
const GURL kScope("http://www.test.not/scope/*");
const GURL kScript("http://www.test.not/script.js");
const GURL kDocumentUrl("http://www.test.not/scope/document.html");
const int64 kRegistrationId = 0;
const int64 kVersionId = 0;
......@@ -310,9 +401,9 @@ TEST_F(ServiceWorkerStorageTest, StoreFindUpdateDeleteRegistration) {
}
TEST_F(ServiceWorkerStorageTest, InstallingRegistrationsAreFindable) {
const GURL kScope("http://www.test.com/scope/*");
const GURL kScript("http://www.test.com/script.js");
const GURL kDocumentUrl("http://www.test.com/scope/document.html");
const GURL kScope("http://www.test.not/scope/*");
const GURL kScript("http://www.test.not/script.js");
const GURL kDocumentUrl("http://www.test.not/scope/document.html");
const int64 kRegistrationId = 0;
const int64 kVersionId = 0;
......@@ -442,4 +533,80 @@ TEST_F(ServiceWorkerStorageTest, InstallingRegistrationsAreFindable) {
was_called = false;
}
TEST_F(ServiceWorkerStorageTest, ResourceIdsAreStoredAndPurged) {
storage()->LazyInitialize(base::Bind(&base::DoNothing));
base::RunLoop().RunUntilIdle();
const GURL kScope("http://www.test.not/scope/*");
const GURL kScript("http://www.test.not/script.js");
const GURL kImport("http://www.test.not/import.js");
const GURL kDocumentUrl("http://www.test.not/scope/document.html");
const int64 kRegistrationId = storage()->NewRegistrationId();
const int64 kVersionId = storage()->NewVersionId();
const int64 kResourceId1 = storage()->NewResourceId();
const int64 kResourceId2 = storage()->NewResourceId();
// Cons up a new registration+version with two script resources.
RegistrationData data;
data.registration_id = kRegistrationId;
data.scope = kScope;
data.script = kScript;
data.version_id = kVersionId;
data.is_active = false;
std::vector<ResourceRecord> resources;
resources.push_back(ResourceRecord(kResourceId1, kScript));
resources.push_back(ResourceRecord(kResourceId2, kImport));
scoped_refptr<ServiceWorkerRegistration> registration =
storage()->GetOrCreateRegistration(data, resources);
registration->pending_version()->SetStatus(ServiceWorkerVersion::NEW);
// Add the resources ids to the uncommitted list.
std::set<int64> resource_ids;
resource_ids.insert(kResourceId1);
resource_ids.insert(kResourceId2);
EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
storage()->database_->WriteUncommittedResourceIds(resource_ids));
// And dump something in the disk cache for them.
WriteBasicResponse(storage(), kResourceId1);
WriteBasicResponse(storage(), kResourceId2);
EXPECT_TRUE(VerifyBasicResponse(storage(), kResourceId1, true));
EXPECT_TRUE(VerifyBasicResponse(storage(), kResourceId2, true));
// Storing the registration/version should take the resources ids out
// of the uncommitted list.
bool was_called = false;
ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_FAILED;
storage()->StoreRegistration(registration, registration->pending_version(),
MakeStatusCallback(&was_called, &result));
base::RunLoop().RunUntilIdle();
ASSERT_TRUE(was_called);
EXPECT_EQ(SERVICE_WORKER_OK, result);
std::set<int64> verify_ids;
EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
storage()->database_->GetUncommittedResourceIds(&verify_ids));
EXPECT_TRUE(verify_ids.empty());
// Deleting it should result in the resources being added to the
// purgeable list and then doomed in the disk cache and removed from
// that list.
was_called = false;
verify_ids.clear();
storage()->DeleteRegistration(
registration->id(), kScope.GetOrigin(),
base::Bind(&VerifyPurgeableListStatusCallback,
base::Unretained(storage()->database_.get()),
&verify_ids, &was_called, &result));
base::RunLoop().RunUntilIdle();
ASSERT_TRUE(was_called);
EXPECT_EQ(SERVICE_WORKER_OK, result);
EXPECT_EQ(2u, verify_ids.size());
verify_ids.clear();
EXPECT_EQ(ServiceWorkerDatabase::STATUS_OK,
storage()->database_->GetPurgeableResourceIds(&verify_ids));
EXPECT_TRUE(verify_ids.empty());
EXPECT_FALSE(VerifyBasicResponse(storage(), kResourceId1, false));
EXPECT_FALSE(VerifyBasicResponse(storage(), kResourceId2, false));
}
} // namespace content
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment