chromium/third_party/blink/public/mojom/service_worker/service_worker.mojom

// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

module blink.mojom;

import "mojo/public/mojom/base/read_only_buffer.mojom";
import "mojo/public/mojom/base/string16.mojom";
import "mojo/public/mojom/base/time.mojom";
import "mojo/public/mojom/base/values.mojom";
import "services/network/public/mojom/cookie_manager.mojom";
import "services/network/public/mojom/url_loader_factory.mojom";
import "third_party/blink/public/mojom/associated_interfaces/associated_interfaces.mojom";
import "third_party/blink/public/mojom/background_fetch/background_fetch.mojom";
import "third_party/blink/public/mojom/devtools/console_message.mojom";
import "third_party/blink/public/mojom/fetch/fetch_api_response.mojom";
import "third_party/blink/public/mojom/frame/reporting_observer.mojom";
import "third_party/blink/public/mojom/loader/url_loader_factory_bundle.mojom";
import "third_party/blink/public/mojom/messaging/transferable_message.mojom";
import "third_party/blink/public/mojom/notifications/notification.mojom";
import "third_party/blink/public/mojom/payments/payment_app.mojom";
import "third_party/blink/public/mojom/push_messaging/push_messaging.mojom";
import "third_party/blink/public/mojom/service_worker/dispatch_fetch_event_params.mojom";
import "third_party/blink/public/mojom/service_worker/service_worker_ancestor_frame_type.mojom";
import "third_party/blink/public/mojom/service_worker/service_worker_client.mojom";
import "third_party/blink/public/mojom/service_worker/service_worker_error_type.mojom";
import "third_party/blink/public/mojom/service_worker/service_worker_event_status.mojom";
import "third_party/blink/public/mojom/service_worker/service_worker_fetch_response_callback.mojom";
import "third_party/blink/public/mojom/service_worker/service_worker_object.mojom";
import "third_party/blink/public/mojom/service_worker/service_worker_registration.mojom";
import "third_party/blink/public/mojom/service_worker/service_worker_router_rule.mojom";
import "third_party/blink/public/mojom/storage_key/storage_key.mojom";
import "url/mojom/origin.mojom";
import "url/mojom/url.mojom";

// Host for a running service worker execution context. Implemented in the
// browser process. The service worker running in the renderer process uses this
// interface to ask the browser process to do operations needed for
// ServiceWorkerGlobalScope functionalities.
interface ServiceWorkerHost {
  // Sets V8 code cache |data| for the given service worker script |url|, which
  // may be the main script or an imported script.
  SetCachedMetadata(url.mojom.Url url, mojo_base.mojom.ReadOnlyBuffer data);

  // Clears V8 code cache for |url| set by the above |SetCachedMetadata| before.
  ClearCachedMetadata(url.mojom.Url url);

  // Corresponds to Clients#matchAll(options). Gets information of all service
  // worker clients matching |options|.
  GetClients(ServiceWorkerClientQueryOptions options)
    => (array<ServiceWorkerClientInfo> clients);

  // Corresponds to Clients#get(id). Gets information of the service worker
  // client with |client_uuid|. |client| is null if it was not found or is not
  // same-origin with this service worker.
  GetClient(string client_uuid) => (ServiceWorkerClientInfo? client);

  // Corresponds to Clients#openWindow(url). Requests the browser to open a tab
  // with |url|.
  // If the tab was successfully opened, |success| is true. |client| contains
  // information about the newly opened window, but may be null if that
  // information could not be obtained (this can happen for a cross-origin
  // window, or if the browser process could not get the information in time
  // before the window was closed).
  // If |success| is false, |error_msg| describes the failure.
  OpenNewTab(url.mojom.Url url)
    => (bool success, ServiceWorkerClientInfo? client, string? error_msg);

  // Corresponds to PaymentRequestEvent#openWindow(url).
  // Spec: https://w3c.github.io/payment-handler/#openwindow-method
  // Requests the browser to open a payment handler window with |url|.
  // If the window was successfully opened, |success| is true. |client| contains
  // information about the newly opened window, but may be null if that
  // information could not be obtained (this can happen for a cross-origin
  // window, or if the browser process could not get the information in time
  // before the window was closed).
  // If |success| is false, |error_msg| describes the failure.
  OpenPaymentHandlerWindow(url.mojom.Url url)
    => (bool success, ServiceWorkerClientInfo? client, string? error_msg);

  // Corresponds to Client#postMessage(). Requests the browser to post |message|
  // to the client with |client_uuid|.
  PostMessageToClient(string client_uuid, TransferableMessage message);

  // Corresponds to WindowClient#focus(). Requests the browser to focus the
  // client with |client_uuid|.
  // On success, |client| contains service worker client information of the
  // focused window.
  // Otherwise, |client| is null.
  FocusClient(string client_uuid) => (ServiceWorkerClientInfo? client);

  // Corresponds to WindowClient#navigate(). Requests the browser to navigate
  // the client with |client_uuid| to |url|.
  // If the navigation was successful, |success| is true. |client| contains
  // information about the navigated window, but may be null if that
  // information could not be obtained (this can happen for a cross-origin
  // window, or if the browser process could not get the information in time
  // before the window was closed).
  // If |success| is false, |error_msg| describes the failure.
  NavigateClient(string client_uuid, url.mojom.Url url)
    => (bool success, ServiceWorkerClientInfo? client, string? error_msg);

  // Corresponds to ServiceWorkerGlobalScope#skipWaiting(). Allows this service
  // worker to progress from the registration's waiting position to active even
  // while service worker clients are using the registration.
  // The callback is called with |success| true when the skipWaiting() promise
  // should be resolved. If |success| is false, the operation failed fatally,
  // but per spec the skipWaiting() promise should be left unresolved as it can
  // never reject.
  SkipWaiting() => (bool success);

  // Corresponds to Clients#claim(). Allows an active service worker to set
  // itself as the controller for all clients within its scope.
  // On success, |error| is kNone without |error_msg| set.
  // Otherwise, |error| and |error_msg| describe the failure.
  ClaimClients() => (ServiceWorkerErrorType error, string? error_msg);

  // Corresponds to InstallEvent#addRoutes(). Adds service worker router rules,
  // which are evaluated before the regular navigation path. i.e. evaluated
  // before the service worker fetch handler is invoked.
  //
  // The callback with |is_parse_error| true indicates that the evaluator faced
  // a parse error of regex, and could not initialize the router evaluator.
  // Otherwise, |is_parse_error| is false to indicate that the evaluator is
  // initialized.
  AddRoutes(ServiceWorkerRouterRules rules) => (bool is_parse_error);
};

struct ExtendableMessageEvent {
  TransferableMessage message;
  url.mojom.Origin source_origin;
  // Exactly one of |source_info_for_client| and
  // |source_info_for_service_worker| should be non-null.
  ServiceWorkerClientInfo? source_info_for_client;
  ServiceWorkerObjectInfo? source_info_for_service_worker;
};

// Indicates whether a service worker has a fetch event handler.  The presence
// of the fetch event handler is determined when the service worker finishes
// installing.
// TODO(crbug.com/945505): Convert enum constants to kUnknown style.
enum FetchHandlerExistence {
  // The service worker has not yet finished installing.
  UNKNOWN,
  // The service worker finished installing and added a fetch event handler.
  EXISTS,
  // The service worker finished installing without a fetch event handler.
  DOES_NOT_EXIST,
};

// The number of seconds for which a 'push' and the 'pushsubsciptionchange'
// event should be allowed to run. This is not in the spec but for a
// Chrome-specific timeout. Each event dispatched to service workers has a 5
// minute timeout in the Chrome implementation, but this makes the timeout for
// push events shorter.
const int32 kPushEventTimeoutSeconds = 90;

// The default number of seconds for idle timeouts. A service worker requests
// termination when no event is running on the thread with a delay. This is the
// default value for the delay, and the delay can be updated by SetIdleDelay()
// in blink.mojom.ServiceWorker interface.
const int32 kServiceWorkerDefaultIdleDelayInSeconds = 30;

// An interface for talking to a running service worker thread. The browser
// process uses this interface to request the renderer to do things like
// dispatch events to the service worker. This interface is bound on the
// service worker thread and is implemented by ServiceWorkerGlobalScope.
//
// This is the master interface for the Mojo message pipe between the browser
// process and the service worker thread in the renderer process. Other service
// worker-related interfaces bound on the service worker thread are associated
// with this interface. These include:
// - ServiceWorkerHost for this service worker.
// - ServiceWorkerRegistrationObject(Host) for this service worker's
//   self.registration property.
// - ServiceWorkerObjects(Host) for that registration's properties.
//
// A similar (but non-associated) interface is ControllerServiceWorker. That
// interface is used by service worker clients (inside renderer processes) to
// talk directly to their controller service worker, without going through the
// browser.
//
// USAGE TIP: Those DispatchEvent* messages expecting a
// (ServiceWorkerEventStatus, mojo_base.mojom.TimeTicks) callback
// are considered 'simple events'.
// ServiceWorkerVersion::CreateSimpleEventCallback can be used to create the
// callback for these.
interface ServiceWorker {
  // The first message sent on this interface. It is used to associate service
  // worker-related interfaces together on the service worker thread, as
  // ServiceWorker is the first interface available on the
  // service worker thread. It establishes the |service_worker_host| connection
  // and passes information used to populate
  // ServiceWorkerGlobalScope#registration object and
  // ServiceWorkerGlobalScope#serviceWorker object. JavaScript execution of the
  // service worker does not start until this message is received.
  // |reporting_observer_receiver| will be set to the worker global scope so
  // that reports queued to the remote of |reporting_observer_receiver| will
  // be notified to ReportingObservers registered with the global scope.
  InitializeGlobalScope(
      pending_associated_remote<ServiceWorkerHost> service_worker_host,
      pending_associated_remote<blink.mojom.AssociatedInterfaceProvider> associated_interfaces_to_browser,
      pending_associated_receiver<blink.mojom.AssociatedInterfaceProvider> associated_interfaces_from_browser,
      ServiceWorkerRegistrationObjectInfo registration_info,
      ServiceWorkerObjectInfo service_worker_info,
      FetchHandlerExistence fetch_handler_existence,
      pending_receiver<ReportingObserver>? reporting_observer_receiver,
      AncestorFrameType ancestor_frame_type,
      blink.mojom.StorageKey storage_key);

  // These methods dispatch InstallEvent and ActivateEvent to the
  // ServiceWorkerGlobalScope.
  // The |fetch_count| return value is the number of network fetches performed
  // from the service worker context during the event handler.  This is used
  // for metrics.
  DispatchInstallEvent()
      => (ServiceWorkerEventStatus status, uint32 fetch_count);
  DispatchActivateEvent()
      => (ServiceWorkerEventStatus status);

  // These methods dispatch to the ServiceWorkerGlobalScope the events listed on
  // https://wicg.github.io/background-fetch/#service-worker-global-events.
  // The callbacks are called once the event handler has run and waitUntil()
  // promise has settled. |developer_id| and |unique_id| are documented in
  // content::BackgroundFetchRegistrationId.
  DispatchBackgroundFetchAbortEvent(
      BackgroundFetchRegistration registration)
      => (ServiceWorkerEventStatus status);
  DispatchBackgroundFetchClickEvent(
      BackgroundFetchRegistration registration)
      => (ServiceWorkerEventStatus status);
  DispatchBackgroundFetchFailEvent(
      BackgroundFetchRegistration registration)
      => (ServiceWorkerEventStatus status);
  DispatchBackgroundFetchSuccessEvent(
      BackgroundFetchRegistration registration)
      => (ServiceWorkerEventStatus status);

  // Dispatches the cookie change events in the Async Cookie API specification.
  // https://github.com/WICG/cookie-store/
  // The callback is called once the event handler has run and the waitUntil()
  // promise has settled.
  DispatchCookieChangeEvent(network.mojom.CookieChangeInfo change)
      => (ServiceWorkerEventStatus status);

  // The Dispatch*FetchEvent() callback is called once the event finishes,
  // which means the event handler ran and all outstanding respondWith() and
  // waitUntil() promises have settled. |response_callback| is called once the
  // promise to respondWith() settles, or when the event handler ran without
  // calling respondWith().
  DispatchFetchEventForMainResource(
      DispatchFetchEventParams params,
      pending_remote<ServiceWorkerFetchResponseCallback> response_callback)
      => (ServiceWorkerEventStatus status);

  DispatchNotificationClickEvent(
      string notification_id,
      NotificationData notification_data,
      int32 action_index,
      mojo_base.mojom.String16? reply)
      => (ServiceWorkerEventStatus status);
  DispatchNotificationCloseEvent(
      string notification_id,
      NotificationData notification_data)
      => (ServiceWorkerEventStatus status);
  // The payload of a push message can be valid with content, valid with empty
  // content, or null.
  DispatchPushEvent(string? payload)
      => (ServiceWorkerEventStatus status);
  // Whenever a PushSubscription changes, a change event is generated with
  // (optionally) the previous subscription and the new subscription.
  // |old_subscription| can be null when there was a partial database corruption
  // so that the full subscription information about the subscription that is
  // going to become invalid cannot be found anymore.
  // |new_subscription| is the subscription that is going to replace the
  // |old_subscription| and is null when permission is revoked or the
  // subscription is lost.
  // Ref: https://w3c.github.io/push-api/#dfn-pushsubscriptionchange
  DispatchPushSubscriptionChangeEvent(
      PushSubscription? old_subscription,
      PushSubscription? new_subscription)
      => (ServiceWorkerEventStatus status);
  // Arguments are passed to the event handler as parameters of SyncEvent.
  // Ref: https://wicg.github.io/BackgroundSync/spec/#sync-event
  // |timeout| is the amount of time to allow this event to finish.
  DispatchSyncEvent(string tag,
                    bool last_chance,
                    mojo_base.mojom.TimeDelta timeout)
      => (ServiceWorkerEventStatus status);
  // |timeout| is the amount of time to allow this event to finish.
  // TODO(crbug.com/925297): Link to spec.
  DispatchPeriodicSyncEvent(string tag,
                            mojo_base.mojom.TimeDelta timeout)
      => (ServiceWorkerEventStatus status);
  DispatchAbortPaymentEvent(
      pending_remote<payments.mojom.PaymentHandlerResponseCallback>
          result_of_abort_payment)
      => (ServiceWorkerEventStatus status);
  DispatchCanMakePaymentEvent(
      payments.mojom.CanMakePaymentEventData event_data,
      pending_remote<payments.mojom.PaymentHandlerResponseCallback>
          result_of_can_make_payment)
      => (ServiceWorkerEventStatus status);
  DispatchPaymentRequestEvent(
      payments.mojom.PaymentRequestEventData request_data,
      pending_remote<payments.mojom.PaymentHandlerResponseCallback>
          response_callback)
      => (ServiceWorkerEventStatus status);
  DispatchExtendableMessageEvent(ExtendableMessageEvent event)
      => (ServiceWorkerEventStatus status);
  // Ref: https://github.com/rknoll/content-index
  DispatchContentDeleteEvent(string id) => (ServiceWorkerEventStatus status);

  // Pings the service worker to check if it is responsive. If the callback is
  // not called within a certain period of time, the browser will terminate the
  // worker.
  Ping() => ();

  // Changes the delay until the idle timer requests termination after all
  // events are handled.
  SetIdleDelay(mojo_base.mojom.TimeDelta delay);

  // Resets the members for idle timeouts to cancel the idle callback.
  AddKeepAlive();

  // Check if the event queue is empty.
  // Schedules idle timeout callback if there is no ongoing event.
  ClearKeepAlive();

  // Adds a message to DevTools console which is associated with this worker.
  AddMessageToConsole(ConsoleMessageLevel level, string message);

  // Executes the given `javascript` in the context of the running worker.
  // `wants_result` indicates whether a result from the executing `javascript`
  // should be returned via the provided callback.
  // Currently, this only supports synchronous script execution, and the
  // returned value is the result of the final execution in the provided
  // javascript.
  // If an exception is thrown, a stringified version is returned through the
  // error parameter.
  // TODO(devlin): Expand this to allow returning a promise for asynchronous
  // execution.
  ExecuteScriptForTest(
      mojo_base.mojom.BigString16 javascript,
      bool wants_result)
      => (mojo_base.mojom.Value result, string? error);
};