// 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/hash_value.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 purgeable_resources; // A receiver which is associated with `id`. pending_receiver 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 version_reference; // Stored registration. ServiceWorkerRegistrationData registration; // Resources associated with |registration|. array 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? 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 versions) => (); // Returns all StorageKeys which have service worker registrations. GetRegisteredStorageKeys() => (array 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? 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 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 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 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 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? 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`. If `sha256_checksum` // is provided, it is used to verify the integrity of the resource data as it // is read from the cache. The result of this verification is recorded in the // ServiceWorker.ResourceChecksumMatch UMA metric. CreateResourceReader( int64 resource_id, network.mojom.SHA256HashValue? sha256_checksum, pending_receiver reader); // Creates a resource writer for the given |resource_id|. CreateResourceWriter(int64 resource_id, pending_receiver writer); // Creates a metadata writer for the given |resource_id|. CreateResourceMetadataWriter( int64 resource_id, pending_receiver 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 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 keys) => (ServiceWorkerDatabaseStatus status, array values); // Stores `user_data` on persistent storage. StoreUserData(int64 registration_id, blink.mojom.StorageKey key, array user_data) => (ServiceWorkerDatabaseStatus status); // Clears user data specified by |registration_id| and |keys|. ClearUserData(int64 registration_id, array 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 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 user_data); // Clears user data associated with the given |registration_id| filtered by // |key_prefix|. ClearUserDataByKeyPrefixes(int64 registratation_id, array key_prefixes) => (ServiceWorkerDatabaseStatus status); // Gets the user data from all registrations that have user data for |key|. GetUserDataForAllRegistrations(string key) => (ServiceWorkerDatabaseStatus status, array 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 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 policy_updates) => (ServiceWorkerDatabaseStatus status); // Gets resource ids which are scheduled to purge. GetPurgingResourceIdsForTest() => (ServiceWorkerDatabaseStatus status, array 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 resource_ids); // Gets resource ids which are purgeable. GetPurgeableResourceIdsForTest() => (ServiceWorkerDatabaseStatus status, array resource_ids); // Gets resource ids which are uncommitted. GetUncommittedResourceIdsForTest() => (ServiceWorkerDatabaseStatus status, array 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() => (); };