// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
module storage.mojom;
import "components/services/storage/public/mojom/service_worker_database.mojom";
import "components/services/storage/public/mojom/storage_policy_update.mojom";
import "mojo/public/mojom/base/big_buffer.mojom";
import "mojo/public/mojom/base/byte_string.mojom";
import "mojo/public/mojom/base/time.mojom";
import "services/network/public/mojom/url_response_head.mojom";
import "third_party/blink/public/mojom/service_worker/service_worker_fetch_handler_type.mojom";
import "third_party/blink/public/mojom/storage_key/storage_key.mojom";
import "url/mojom/url.mojom";
// An interface that is used to keep track of which service worker versions are
// being used by clients of the storage service. This is an empty interface that
// is mapped internally by the storage service to a single version.
//
// This is used to decide when it's safe to purge resources for a service worker
// version whose registration has been deleted. A service worker version can be
// still be used and may need to be started and stopped multiple times after
// unregistration. The client of the storage service should hold on to the
// reference as long as it's using the version, i.e., by making the reference
// owned by the C++ ServiceWorkerVersion instance.
interface ServiceWorkerLiveVersionRef {};
// Conveys information about a live service worker version. Sent from the
// browser to the Storage Service to recover resource purging state after a
// Storage Service restart.
struct ServiceWorkerLiveVersionInfo {
// Version id.
int64 id;
// Contains resource ids which are purgeable when `reference` is disconnected.
// Non-empty only when the associated service worker registration has been
// deleted from the storage but the corresponding service worker version is
// still being used.
array<int64> purgeable_resources;
// A receiver which is associated with `id`.
pending_receiver<ServiceWorkerLiveVersionRef> reference;
};
// Conveys a result of finding a registration.
// The Storage Service (components/services/storage) supplies this
// information and the //content consumes the information.
struct ServiceWorkerFindRegistrationResult {
// A reference to a service worker version associated with
// |registration->version_id|.
pending_remote<ServiceWorkerLiveVersionRef> version_reference;
// Stored registration.
ServiceWorkerRegistrationData registration;
// Resources associated with |registration|.
array<ServiceWorkerResourceRecord> resources;
};
// Used to tell the browser process or embedders if there are registrations
// after ServiceWorkerStorageControl::DeleteRegistration().
enum ServiceWorkerStorageStorageKeyState {
// Registrations may exist for the StorageKey. It cannot be deleted.
kKeep,
// No registrations exist for the StorageKey. It can be deleted.
kDelete,
};
// An interface that reads a service worker script (resource) to storage.
// This is hosted in the browser process and should be only used from the
// browser process, and relies on the callers to satisfy the calling order
// invariant below.
//
// A valid use of this interface is that
// 1. Exactly one call to ReadResponseHead().
// 2. A call to PrepareReadData() followed by a call to ReadData().
// Step 2 can be repeated multiple times.
// Each call must not be overlapped.
//
// TODO(crbug.com/40858529): Clarify whether we should really support multiple
// `PrepareReadData()` calls.
//
// TODO(crbug.com/40858529): Enforce the calling order requirement. See
// https://chromium-review.googlesource.com/c/chromium/src/+/3823684/comments/fd5170e2_19c5fb5e
interface ServiceWorkerResourceReader {
// Reads the response head of the resource associated with this reader.
// |status| is the number of bytes read, or a //net error.
// Also returns metadata associated with the resource if it exists.
ReadResponseHead() =>
(int32 status,
network.mojom.URLResponseHead? response_head,
mojo_base.mojom.BigBuffer? metadata);
// Prepare for reading the content of the resource associated with this
// reader. `pipe` can be empty when creating a data pipe fails.
// TODO(crbug.com/40858529): Clarify the meaning of `size` parameter.
PrepareReadData(int64 size) =>
(handle<data_pipe_consumer>? pipe);
// Actually reads the content, and returns when finished.
// On success, |status| is the number of bytes written.
// On failure, |status| is a //net error, which is a negative number.
ReadData() => (int32 status);
};
// An interface that writes a service worker script (resource) to storage.
// A valid use of this interface is that exactly one call to
// WriteResponseHead(), followed by at most one call to WriteData(). These calls
// must not be overlapped.
interface ServiceWorkerResourceWriter {
// Writes the response head to storage. Returns the number of bytes written,
// or a //net error.
WriteResponseHead(network.mojom.URLResponseHead response_head)
=> (int32 status);
// Writes the content of the resource to storage. Returns the number of bytes
// written, or a //net error.
WriteData(mojo_base.mojom.BigBuffer data) => (int32 status);
};
// An interface that writes a metadata (script cache) of a service worker script
// to storage. WriteMetadata() should be called at most once.
interface ServiceWorkerResourceMetadataWriter {
// Writes the metadata of the resource associated with this writer. Returns
// the number of bytes written, or a //net error.
WriteMetadata(mojo_base.mojom.BigBuffer data) => (int32 status);
};
// Represents an entry of user data which is stored with a service worker
// registration. An entry of user data is an arbitrary key-value pair. The
// lifetime of user data is tied up with the registration.
// It will be deleted when the corresponding registration is deleted.
struct ServiceWorkerUserData {
int64 registration_id;
string key;
mojo_base.mojom.ByteString value;
};
// Controls the state of service worker storage within a partition. This is a
// privileged interface and must not be brokered to untrusted clients.
//
// Currently this is consumed and implemented in the browser process, but the
// implementation will eventually live in the Storage Service.
interface ServiceWorkerStorageControl {
// Disables the storage. The callback is invoked after the storage is
// disabled.
Disable() => ();
// Deletes the whole storage.
Delete() => (ServiceWorkerDatabaseStatus status);
// Called by the browser after a Storage Service restart. Tells the Storage
// Service which service worker versions are being used, which is needed to
// decide when it's safe to purge resources for service worker versions that
// have been deleted.
Recover(array<ServiceWorkerLiveVersionInfo> versions) => ();
// Returns all StorageKeys which have service worker registrations.
GetRegisteredStorageKeys() => (array<blink.mojom.StorageKey> keys);
// Reads a stored registration for `client_url` that is associated
// with `key`. `scopes` contains all of the service worker's
// registration scopes that are relevant to the `key` so that we can
// cache scope URLs in the UI thread. The 'scopes' is valid only when
// the status is `kOk` or `kErrorNotFound`. The `scopes` must be
// optional because `scopes` can be empty if the scope count exceeds
// the threshold even when there are scopes in DB so that we can avoid
// sending too large information via mojo API. When this API returns
// null for `scopes`, the caller of this API can't cache the
// scopes. This means that the caller needs to fall back to the slow
// code path that queries the registration from the DB.
FindRegistrationForClientUrl(url.mojom.Url client_url,
blink.mojom.StorageKey key) =>
(ServiceWorkerDatabaseStatus status,
ServiceWorkerFindRegistrationResult? result,
array<url.mojom.Url>? scopes);
// Reads a stored registration for `scope` that is associated with `key`.
FindRegistrationForScope(url.mojom.Url scope, blink.mojom.StorageKey key) =>
(ServiceWorkerDatabaseStatus status,
ServiceWorkerFindRegistrationResult? result);
// Reads a stored registration for `registration_id`. `key` is to
// be used as a hint to look up the registration faster.
FindRegistrationForId(int64 registration_id, blink.mojom.StorageKey? key) =>
(ServiceWorkerDatabaseStatus status,
ServiceWorkerFindRegistrationResult? result);
// Returns all stored registrations for a given StorageKey.
GetRegistrationsForStorageKey(blink.mojom.StorageKey key) =>
(ServiceWorkerDatabaseStatus status,
array<ServiceWorkerFindRegistrationResult> registrations);
// Returns the total resource size for a given StorageKey.
GetUsageForStorageKey(blink.mojom.StorageKey key) =>
(ServiceWorkerDatabaseStatus status, int64 usage);
// Returns all stored registrations.
// NOTE: Don't use this method for new code. Reading all registrations
// from storage doesn't scale. See https://crbug.com/807440 for details.
GetAllRegistrationsDeprecated() =>
(ServiceWorkerDatabaseStatus status,
array<ServiceWorkerRegistrationData> registrations);
// Stores |registration_data| and |resources|. If exists, the previous
// registration for `registration.registration_id` will be deleted when
// storing succeeds. `deleted_resources_size` carries the total size of
// deleted resources.
StoreRegistration(ServiceWorkerRegistrationData registration,
array<ServiceWorkerResourceRecord> resources) =>
(ServiceWorkerDatabaseStatus status, uint64 deleted_resources_size);
// Deletes the registration specified by `registration_id`.
// `deleted_resources_size` carries the total size of deleted resources.
// `storage_key_state` is kDelete if there is no registration for `key` after
// deletion.
DeleteRegistration(int64 registration_id, blink.mojom.StorageKey key) =>
(ServiceWorkerDatabaseStatus status,
uint64 deleted_resources_size,
ServiceWorkerStorageStorageKeyState storage_key_state);
// Updates the state of the registration's stored version to active.
UpdateToActiveState(int64 registration_id, blink.mojom.StorageKey key) =>
(ServiceWorkerDatabaseStatus status);
// Updates the last update check time on the storage.
UpdateLastUpdateCheckTime(int64 registration_id,
blink.mojom.StorageKey key,
mojo_base.mojom.Time last_update_check_time) =>
(ServiceWorkerDatabaseStatus status);
// Updates the registration's navigation preload enabled flag in storage.
UpdateNavigationPreloadEnabled(int64 registration_id,
blink.mojom.StorageKey key,
bool enable) =>
(ServiceWorkerDatabaseStatus status);
// Updates the registration's navigation preload header in storage.
UpdateNavigationPreloadHeader(int64 registration_id,
blink.mojom.StorageKey key,
string value) =>
(ServiceWorkerDatabaseStatus status);
// Updates the fetch handler type in storage.
UpdateFetchHandlerType(int64 registration_id,
blink.mojom.StorageKey key,
blink.mojom.ServiceWorkerFetchHandlerType type) =>
(ServiceWorkerDatabaseStatus status);
// Updates sha256 checksum fields in resource records.
UpdateResourceSha256Checksums(int64 registratation_id,
blink.mojom.StorageKey key,
map<int64, string> updated_sha256_checksums) =>
(ServiceWorkerDatabaseStatus status);
// Returns a new registration id which is guaranteed to be unique in the
// storage. Returns blink::mojom::kInvalidServiceWorkerRegistrationId if the
// storage is disabled.
GetNewRegistrationId() => (int64 registration_id);
// Returns a new service worker version id, which is guaranteed to be unique
// in the storage, and a reference to the version id.
// blink::mojom::kInvalidServiceWorkerVersionId and null reference are
// returned if the storage is disabled.
GetNewVersionId() =>
(int64 version_id,
pending_remote<ServiceWorkerLiveVersionRef>? version_reference);
// Returns a new resource id which is guaranteed to be unique in the storage.
// Returns blink::mojom::kInvalidServiceWorkerResourceId if the storage
// is disabled.
GetNewResourceId() => (int64 resource_id);
// Creates a resource reader for the given |resource_id|.
CreateResourceReader(int64 resource_id,
pending_receiver<ServiceWorkerResourceReader> reader);
// Creates a resource writer for the given |resource_id|.
CreateResourceWriter(int64 resource_id,
pending_receiver<ServiceWorkerResourceWriter> writer);
// Creates a metadata writer for the given |resource_id|.
CreateResourceMetadataWriter(
int64 resource_id,
pending_receiver<ServiceWorkerResourceMetadataWriter> writer);
// Puts |resource_id| on the uncommitted resource list in storage. Once
// |resource_id| is put on the uncommitted resource list, the corresponding
// resource is considered to be existing in storage but it's not associated
// with any registration yet.
// StoreRegistration() or DoomUncommittedResources() needs to be
// called later to clear the |resource_id| from the uncommitted resource list.
StoreUncommittedResourceId(int64 resource_id) =>
(ServiceWorkerDatabaseStatus status);
// Removes |resource_ids| from the uncommitted resource list.
DoomUncommittedResources(array<int64> resource_ids) =>
(ServiceWorkerDatabaseStatus status);
// Gets user data associated with the given |registration_id|.
// Succeeds only when all keys are found. On success, the size and the order
// of |values| are the same as |keys|.
GetUserData(int64 registration_id, array<string> keys) =>
(ServiceWorkerDatabaseStatus status,
array<mojo_base.mojom.ByteString> values);
// Stores `user_data` on persistent storage.
StoreUserData(int64 registration_id,
blink.mojom.StorageKey key,
array<ServiceWorkerUserData> user_data) =>
(ServiceWorkerDatabaseStatus status);
// Clears user data specified by |registration_id| and |keys|.
ClearUserData(int64 registration_id, array<string> keys) =>
(ServiceWorkerDatabaseStatus status);
// Gets user data values associated with the given |registration_id|
// filtered by |key_prefix|.
GetUserDataByKeyPrefix(int64 registration_id, string key_prefix) =>
(ServiceWorkerDatabaseStatus status,
array<mojo_base.mojom.ByteString> values);
// Gets user data associated with the given |registration_id| filtered by
// |key_prefix|. Returns user data as key-value pairs.
GetUserKeysAndDataByKeyPrefix(int64 registration_id, string key_prefix) =>
(ServiceWorkerDatabaseStatus status,
map<string, mojo_base.mojom.ByteString> user_data);
// Clears user data associated with the given |registration_id| filtered by
// |key_prefix|.
ClearUserDataByKeyPrefixes(int64 registratation_id,
array<string> key_prefixes) =>
(ServiceWorkerDatabaseStatus status);
// Gets the user data from all registrations that have user data for |key|.
GetUserDataForAllRegistrations(string key) =>
(ServiceWorkerDatabaseStatus status,
array<ServiceWorkerUserData> values);
// Gets the user data from all registrations that have user data for
// |key_prefix| where |key_prefix| is a prefix of keys.
GetUserDataForAllRegistrationsByKeyPrefix(string key_prefix) =>
(ServiceWorkerDatabaseStatus status,
array<ServiceWorkerUserData> values);
// Clears the user data from all registrations using |key_prefix| as a prefix
// of keys.
ClearUserDataForAllRegistrationsByKeyPrefix(string key_prefix) =>
(ServiceWorkerDatabaseStatus status);
// Removes traces of deleted data on disk.
PerformStorageCleanup() => ();
// Applies changes to data retention policy which are relevant at shutdown.
// This is analogous to LocalStorageControl::ApplyPolicyUpdates.
ApplyPolicyUpdates(array<StoragePolicyUpdate> policy_updates) =>
(ServiceWorkerDatabaseStatus status);
// Gets resource ids which are scheduled to purge.
GetPurgingResourceIdsForTest() => (ServiceWorkerDatabaseStatus status,
array<int64> resource_ids);
// Gets resource ids which will be scheduled to purge once the version with
// the given id is no longer alive.
GetPurgingResourceIdsForLiveVersionForTest(int64 version_id) =>
(ServiceWorkerDatabaseStatus status,
array<int64> resource_ids);
// Gets resource ids which are purgeable.
GetPurgeableResourceIdsForTest() => (ServiceWorkerDatabaseStatus status,
array<int64> resource_ids);
// Gets resource ids which are uncommitted.
GetUncommittedResourceIdsForTest() => (ServiceWorkerDatabaseStatus status,
array<int64> resource_ids);
// Sets a callback which is executed when purging resources completes.
// Only a single callback can be set at a time. Overlapped calls are not
// allowed.
SetPurgingCompleteCallbackForTest() => ();
};