Commit f4f83402 authored by Kenichi Ishibashi's avatar Kenichi Ishibashi Committed by Commit Bot

Add store/delete methods to ServiceWorkerStorageControl

This CL adds StoreRegistration() and DeleteRegistration()
mojo methods which wrap corresponding ServiceWorkerStorage methods.

ServiceWorkerStorage's methods return a deleted version and resource
ids that can be purged after storing/deleting a registration. This CL
doesn't expose these values as mojo return values. Purging resources
should be done only when no browser/embedders use them. The storage
service will manage purging resources but the mechanism hasn't been
implemented yet.

Bug: 1055677
Change-Id: I1bcd8bad4172a3c759e89692f8d7948da33219b5
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2126432
Commit-Queue: Kenichi Ishibashi <bashi@chromium.org>
Reviewed-by: default avatarMakoto Shimazu <shimazu@chromium.org>
Reviewed-by: default avatarKinuko Yasuda <kinuko@chromium.org>
Cr-Commit-Position: refs/heads/master@{#754853}
parent 911926da
......@@ -19,6 +19,15 @@ struct ServiceWorkerFindRegistrationResult {
array<ServiceWorkerResourceRecord> resources;
};
// Used to tell the browser process or embedders if there are registrations
// after ServiceWorkerStorageControl::DeleteRegistration().
enum ServiceWorkerStorageOriginState {
// Registrations may exist for the origin. It cannot be deleted.
kKeep,
// No registrations exist for the origin. It can be deleted.
kDelete,
};
// Controls the state of service worker storage within a partition. This is a
// privileged interface and must not be brokered to untrusted clients.
//
......@@ -37,4 +46,15 @@ interface ServiceWorkerStorageControl {
// Reads a stored registration for |registration_id|.
FindRegistrationForId(int64 registration_id, url.mojom.Url origin) =>
(ServiceWorkerFindRegistrationResult result);
// Stores |registration_data| and |resources| on persistent storage.
StoreRegistration(ServiceWorkerRegistrationData registration,
array<ServiceWorkerResourceRecord> resources) =>
(ServiceWorkerDatabaseStatus status);
// Deletes the registration specified by |registration_id|. |origin_state| is
// kDelete if there is no registration for |origin| after deletion.
DeleteRegistration(int64 registration_id, url.mojom.Url origin) =>
(ServiceWorkerDatabaseStatus status,
ServiceWorkerStorageOriginState origin_state);
};
......@@ -22,6 +22,7 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "components/services/storage/public/mojom/local_storage_control.mojom.h"
#include "components/services/storage/public/mojom/service_worker_storage_control.mojom.h"
#include "content/browser/service_worker/service_worker_database.h"
#include "content/browser/service_worker/service_worker_metrics.h"
#include "content/common/content_export.h"
......@@ -62,12 +63,7 @@ FORWARD_DECLARE_TEST(ServiceWorkerStorageTest, DisabledStorage);
// restarted.
class CONTENT_EXPORT ServiceWorkerStorage {
public:
enum class OriginState {
// Registrations may exist at this origin. It cannot be deleted.
kKeep,
// No registrations exist at this origin. It can be deleted.
kDelete
};
using OriginState = storage::mojom::ServiceWorkerStorageOriginState;
using RegistrationList =
std::vector<storage::mojom::ServiceWorkerRegistrationDataPtr>;
......
......@@ -26,6 +26,25 @@ void DidFindRegistration(
status, std::move(data), std::move(resource_list)));
}
void DidStoreRegistration(
ServiceWorkerStorageControlImpl::StoreRegistrationCallback callback,
storage::mojom::ServiceWorkerDatabaseStatus status,
int64_t deleted_version_id,
const std::vector<int64_t>& newly_purgeable_resources) {
// TODO(bashi): Figure out how to purge resources.
std::move(callback).Run(status);
}
void DidDeleteRegistration(
ServiceWorkerStorageControlImpl::DeleteRegistrationCallback callback,
storage::mojom::ServiceWorkerDatabaseStatus status,
ServiceWorkerStorage::OriginState origin_state,
int64_t deleted_version_id,
const std::vector<int64_t>& newly_purgeable_resources) {
// TODO(bashi): Figure out how to purge resources.
std::move(callback).Run(status, origin_state);
}
} // namespace
ServiceWorkerStorageControlImpl::ServiceWorkerStorageControlImpl(
......@@ -36,6 +55,10 @@ ServiceWorkerStorageControlImpl::ServiceWorkerStorageControlImpl(
ServiceWorkerStorageControlImpl::~ServiceWorkerStorageControlImpl() = default;
void ServiceWorkerStorageControlImpl::LazyInitializeForTest() {
storage_->LazyInitializeForTest();
}
void ServiceWorkerStorageControlImpl::FindRegistrationForClientUrl(
const GURL& client_url,
FindRegistrationForClientUrlCallback callback) {
......@@ -59,4 +82,26 @@ void ServiceWorkerStorageControlImpl::FindRegistrationForId(
base::BindOnce(&DidFindRegistration, std::move(callback)));
}
void ServiceWorkerStorageControlImpl::StoreRegistration(
storage::mojom::ServiceWorkerRegistrationDataPtr registration,
std::vector<storage::mojom::ServiceWorkerResourceRecordPtr> resources,
StoreRegistrationCallback callback) {
// TODO(bashi): Change the signature of
// ServiceWorkerStorage::StoreRegistrationData() to take a const reference.
storage_->StoreRegistrationData(
std::move(registration),
std::make_unique<ServiceWorkerStorage::ResourceList>(
std::move(resources)),
base::BindOnce(&DidStoreRegistration, std::move(callback)));
}
void ServiceWorkerStorageControlImpl::DeleteRegistration(
int64_t registration_id,
const GURL& origin,
DeleteRegistrationCallback callback) {
storage_->DeleteRegistration(
registration_id, origin,
base::BindOnce(&DidDeleteRegistration, std::move(callback)));
}
} // namespace content
......@@ -31,6 +31,8 @@ class CONTENT_EXPORT ServiceWorkerStorageControlImpl
~ServiceWorkerStorageControlImpl() override;
void LazyInitializeForTest();
private:
// storage::mojom::ServiceWorkerStorageControl implementations:
void FindRegistrationForClientUrl(
......@@ -42,6 +44,13 @@ class CONTENT_EXPORT ServiceWorkerStorageControlImpl
void FindRegistrationForId(int64_t registration_id,
const GURL& origin,
FindRegistrationForIdCallback callback) override;
void StoreRegistration(
storage::mojom::ServiceWorkerRegistrationDataPtr registration,
std::vector<storage::mojom::ServiceWorkerResourceRecordPtr> resources,
StoreRegistrationCallback callback) override;
void DeleteRegistration(int64_t registration_id,
const GURL& origin,
DeleteRegistrationCallback callback) override;
const std::unique_ptr<ServiceWorkerStorage> storage_;
};
......
......@@ -12,6 +12,7 @@
#include "content/public/test/test_utils.h"
#include "net/disk_cache/disk_cache.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/mojom/service_worker/navigation_preload_state.mojom.h"
namespace content {
......@@ -45,6 +46,8 @@ class ServiceWorkerStorageControlImplTest : public testing::Test {
return storage_impl_.get();
}
void LazyInitializeForTest() { storage_impl_->LazyInitializeForTest(); }
FindRegistrationResult FindRegistrationForClientUrl(const GURL& client_url) {
FindRegistrationResult return_value;
base::RunLoop loop;
......@@ -84,6 +87,38 @@ class ServiceWorkerStorageControlImplTest : public testing::Test {
return return_value;
}
void StoreRegistration(
storage::mojom::ServiceWorkerRegistrationDataPtr registration,
std::vector<storage::mojom::ServiceWorkerResourceRecordPtr> resources,
DatabaseStatus& out_status) {
base::RunLoop loop;
storage()->StoreRegistration(
std::move(registration), std::move(resources),
base::BindLambdaForTesting([&](DatabaseStatus status) {
out_status = status;
loop.Quit();
}));
loop.Run();
}
void DeleteRegistration(
int64_t registration_id,
const GURL& origin,
DatabaseStatus& out_status,
storage::mojom::ServiceWorkerStorageOriginState& out_origin_state) {
base::RunLoop loop;
storage()->DeleteRegistration(
registration_id, origin,
base::BindLambdaForTesting(
[&](DatabaseStatus status,
storage::mojom::ServiceWorkerStorageOriginState origin_state) {
out_status = status;
out_origin_state = origin_state;
loop.Quit();
}));
loop.Run();
}
private:
base::ScopedTempDir user_data_directory_;
BrowserTaskEnvironment task_environment_;
......@@ -97,6 +132,8 @@ TEST_F(ServiceWorkerStorageControlImplTest, FindRegistration_NoRegistration) {
const GURL kClientUrl("https://www.example.com/scope/document.html");
const int64_t kRegistrationId = 0;
LazyInitializeForTest();
{
FindRegistrationResult result = FindRegistrationForClientUrl(kClientUrl);
EXPECT_EQ(result->status, DatabaseStatus::kErrorNotFound);
......@@ -114,4 +151,78 @@ TEST_F(ServiceWorkerStorageControlImplTest, FindRegistration_NoRegistration) {
}
}
// Tests that storing/finding/deleting a registration work.
TEST_F(ServiceWorkerStorageControlImplTest, StoreAndDeleteRegistration) {
const GURL kScope("https://www.example.com/scope/");
const GURL kScriptUrl("https://www.example.com/scope/sw.js");
const GURL kClientUrl("https://www.example.com/scope/document.html");
const int64_t kRegistrationId = 0;
const int64_t kScriptSize = 10;
LazyInitializeForTest();
// Create a registration data with a single resource.
std::vector<storage::mojom::ServiceWorkerResourceRecordPtr> resources;
resources.push_back(storage::mojom::ServiceWorkerResourceRecord::New(
kRegistrationId, kScriptUrl, kScriptSize));
auto data = storage::mojom::ServiceWorkerRegistrationData::New();
data->registration_id = kRegistrationId;
data->scope = kScope;
data->script = kScriptUrl;
data->navigation_preload_state = blink::mojom::NavigationPreloadState::New();
int64_t resources_total_size_bytes = 0;
for (auto& resource : resources) {
resources_total_size_bytes += resource->size_bytes;
}
data->resources_total_size_bytes = resources_total_size_bytes;
// Store the registration data.
{
DatabaseStatus status;
StoreRegistration(std::move(data), std::move(resources), status);
ASSERT_EQ(status, DatabaseStatus::kOk);
}
// Find the registration. Find operations should succeed.
{
FindRegistrationResult result = FindRegistrationForClientUrl(kClientUrl);
ASSERT_EQ(result->status, DatabaseStatus::kOk);
EXPECT_EQ(result->registration->registration_id, kRegistrationId);
EXPECT_EQ(result->registration->scope, kScope);
EXPECT_EQ(result->registration->script, kScriptUrl);
EXPECT_EQ(result->registration->resources_total_size_bytes,
resources_total_size_bytes);
EXPECT_EQ(result->resources.size(), 1UL);
result = FindRegistrationForScope(kScope);
EXPECT_EQ(result->status, DatabaseStatus::kOk);
result = FindRegistrationForId(kRegistrationId, kScope.GetOrigin());
EXPECT_EQ(result->status, DatabaseStatus::kOk);
}
// Delete the registration.
{
DatabaseStatus status;
storage::mojom::ServiceWorkerStorageOriginState origin_state;
DeleteRegistration(kRegistrationId, kScope.GetOrigin(), status,
origin_state);
ASSERT_EQ(status, DatabaseStatus::kOk);
EXPECT_EQ(origin_state,
storage::mojom::ServiceWorkerStorageOriginState::kDelete);
}
// Try to find the deleted registration. These operation should result in
// kErrorNotFound.
{
FindRegistrationResult result = FindRegistrationForClientUrl(kClientUrl);
EXPECT_EQ(result->status, DatabaseStatus::kErrorNotFound);
result = FindRegistrationForScope(kScope);
EXPECT_EQ(result->status, DatabaseStatus::kErrorNotFound);
result = FindRegistrationForId(kRegistrationId, kScope.GetOrigin());
EXPECT_EQ(result->status, DatabaseStatus::kErrorNotFound);
}
}
} // 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