chromium/third_party/blink/public/mojom/bluetooth/web_bluetooth.mojom

// Copyright 2016 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 "device/bluetooth/public/mojom/uuid.mojom";

// Bluetooth Terminology:
//
// https://en.wikipedia.org/wiki/Bluetooth_low_energy is a good resource
// describing the Bluetooth concepts used in this file:
// Generic Attribute Profile (GATT), device, services, characteristics,
// descriptors, and UUIDs.

// Instance ID Note:
//
// Structs and parameters use 'instance_id' string values as unique identifiers
// for Bluetooth GATT object instances. UUIDs are used to refer to e.g. a type
// of service (such as a battery service), while the instance ID refers to the
// unique instance of that service (there may be more than one).
//
// Subsequent calls from and to the client code use the ids to refer to
// previously disclosed objects.
//
// Device IDs are exposed to web content, valid to persist, and have a dedicated
// type, WebBluetoothDeviceId. See comments on that struct.
//
// Service, characteristic, and descriptor IDs are simply strings not exposed to
// web content and use platform specific values. They are only used for
// comparison and not intended to be parsed by code, serialized, or exposed to
// web content.
//
// For example:
// RemoteServerGetPrimaryServices() may return a struct of type
// WebBluetoothRemoteGATTService with an instance_id of "service1".
// To retrieve characteristics of that service use that id when calling
// RemoteServiceGetCharacteristics("service1", ...).

// Result codes that can occur during Web Bluetooth execution.
// Transformed to a DOMException in Source/modules/bluetooth/BluetoothError.cpp.
//
// These errors all produce constant message strings. If a particular message
// needs a dynamic component, we should add a separate enum so type-checking the
// IPC ensures the dynamic component is passed.
enum WebBluetoothResult {
  SUCCESS,
  // AbortError:
  WATCH_ADVERTISEMENTS_ABORTED,
  // InvalidModificationError:
  GATT_INVALID_ATTRIBUTE_LENGTH,
  CONNECT_INVALID_ARGS,
  // InvalidStateError:
  SERVICE_NO_LONGER_EXISTS,
  CHARACTERISTIC_NO_LONGER_EXISTS,
  PROMPT_CANCELED,
  CONNECT_DOES_NOT_EXIST,
  // NetworkError:
  CONNECT_ALREADY_IN_PROGRESS,
  CONNECT_AUTH_CANCELED,
  CONNECT_AUTH_FAILED,
  CONNECT_AUTH_REJECTED,
  CONNECT_AUTH_TIMEOUT,
  CONNECT_UNKNOWN_ERROR,
  CONNECT_UNKNOWN_FAILURE,
  CONNECT_UNSUPPORTED_DEVICE,
  DEVICE_NO_LONGER_IN_RANGE,
  GATT_NOT_PAIRED,
  GATT_OPERATION_IN_PROGRESS,
  CONNECT_CONN_FAILED,
  CONNECT_NOT_READY,
  CONNECT_ALREADY_CONNECTED,
  CONNECT_ALREADY_EXISTS,
  CONNECT_NOT_CONNECTED,
  CONNECT_NON_AUTH_TIMEOUT,
  CONNECT_NO_MEMORY,
  CONNECT_JNI_ENVIRONMENT,
  CONNECT_JNI_THREAD_ATTACH,
  CONNECT_WAKELOCK,
  CONNECT_UNEXPECTED_STATE,
  CONNECT_SOCKET_ERROR,
  // NotFoundError:
  NO_BLUETOOTH_ADAPTER,
  CHOSEN_DEVICE_VANISHED,
  CHOOSER_CANCELLED,
  CHOOSER_NOT_SHOWN_API_GLOBALLY_DISABLED,
  CHOOSER_NOT_SHOWN_API_LOCALLY_DISABLED,
  CHOOSER_NOT_SHOWN_USER_DENIED_PERMISSION_TO_SCAN,
  SERVICE_NOT_FOUND,
  NO_SERVICES_FOUND,
  CHARACTERISTIC_NOT_FOUND,
  NO_CHARACTERISTICS_FOUND,
  DESCRIPTOR_NOT_FOUND,
  NO_DESCRIPTORS_FOUND,
  WEB_BLUETOOTH_NOT_SUPPORTED,
  BLUETOOTH_LOW_ENERGY_NOT_AVAILABLE,
  // NotSupportedError:
  GATT_UNKNOWN_ERROR,
  GATT_UNKNOWN_FAILURE,
  GATT_NOT_PERMITTED,
  GATT_NOT_SUPPORTED,
  GATT_UNTRANSLATED_ERROR_CODE,
  // SecurityError:
  GATT_NOT_AUTHORIZED,
  BLOCKLISTED_DESCRIPTOR_UUID,
  BLOCKLISTED_CHARACTERISTIC_UUID,
  BLOCKLISTED_READ,
  BLOCKLISTED_WRITE,
  NOT_ALLOWED_TO_ACCESS_ANY_SERVICE,
  NOT_ALLOWED_TO_ACCESS_SERVICE,
  REQUEST_DEVICE_WITH_BLOCKLISTED_UUID_OR_MANUFACTURER_DATA,
  DESCRIPTOR_NO_LONGER_EXISTS,
  PERMISSIONS_POLICY_VIOLATION,
  // NotAllowedError:
  SCANNING_BLOCKED,
};

// To match a filter, a Bluetooth device must:
// - support all the UUIDs in the services list if that member is present,
// - have a name equal to name if that member is present,
// - have a name starting with name_prefix if that member is present,
// - advertise manufacturer data matching all of the values in
//   manufacturer_data if that member is present.
struct WebBluetoothLeScanFilter {
  array<bluetooth.mojom.UUID>? services;
  string? name;
  string? name_prefix;
  map<WebBluetoothCompany, array<WebBluetoothDataFilter>>? manufacturer_data;
};

// A Bluetooth company identifier is a unique number assigned by the Bluetooth
// SIG to member companies. This struct is currently required in
// WebBluetoothLeScanFilter because WTF::HashMap doesn't allow integer keys of 0
// and -1, 0xffff being -1 in a uint16t. See crbug.com/1204960
struct WebBluetoothCompany {
  uint16 id;
};

// This struct is used as elements of an array to filter Bluetooth device data
// such as manufacturer data and service data. Bluetooth device data matches
// if for each bit in mask, the corresponding bit in Bluetooth device data is
// equal to the corresponding bit in |data|.
struct WebBluetoothDataFilter {
  uint8 data;
  uint8 mask;
};

struct WebBluetoothRequestDeviceOptions {
  array<WebBluetoothLeScanFilter>? filters;
  array<WebBluetoothLeScanFilter>? exclusion_filters;
  array<bluetooth.mojom.UUID> optional_services;
  array<uint16> optional_manufacturer_data;
  bool accept_all_devices;
};

struct WebBluetoothRequestLEScanOptions {
  array<WebBluetoothLeScanFilter>? filters;
  bool keep_repeated_devices;
  bool accept_all_advertisements;
};

// Indicates if the function will return a single or multiple
// GATT objects.
enum WebBluetoothGATTQueryQuantity {
  SINGLE,
  MULTIPLE
};

// An identifier uniquely identifying a Bluetooth device. This identifier is
// safe to provide to web content and is unique per origin, even if referring
// to a common device. Web content may persist this identifier for future
// sessions to identify the same device.
struct WebBluetoothDeviceId {
  array<uint8, 16> device_id;
};

struct WebBluetoothDevice {
  WebBluetoothDeviceId id;
  string? name;
};

struct WebBluetoothRemoteGATTService {
  string instance_id; // See Instance ID Note above.
  bluetooth.mojom.UUID uuid;
};

struct WebBluetoothRemoteGATTCharacteristic {
  string instance_id; // See Instance ID Note above.
  bluetooth.mojom.UUID uuid;
  uint32 properties;
};

struct WebBluetoothAdvertisingEvent {
  WebBluetoothDevice device;
  string? name;
  array<bluetooth.mojom.UUID> uuids;
  bool appearance_is_set;
  uint16 appearance;
  bool tx_power_is_set;
  uint8 tx_power;
  bool rssi_is_set;
  uint8 rssi;
  map<uint16, array<uint8>> manufacturer_data;
  map<bluetooth.mojom.UUID, array<uint8>> service_data;
};

struct WebBluetoothRemoteGATTDescriptor {
  string instance_id; // See Instance ID Note above.
  bluetooth.mojom.UUID uuid;
};

// Parameter for WebBluetoothService.RemoteCharacteristicWriteValue
enum WebBluetoothWriteType {
  kWriteDefaultDeprecated,
  kWriteWithResponse,
  kWriteWithoutResponse,
};

// Web Bluetooth Interface implemented by the browser process and provided to
// Blink in the renderer for Bluetooth GATT Operations on Bluetooth Devices. An
// instance of this interface is 1:1 with Document.
interface WebBluetoothService {
  // Checks if Web Bluetooth is allowed and if a Bluetooth radio is available.
  GetAvailability() => (bool is_available);

  // Requests access to a Bluetooth device. A chooser dialog is displayed with
  // a list of nearby devices. If |options->accept_all_devices| is false, the
  // list is filtered to contain only the ones that match |options->filters|
  // and exclude |options->exclusion_filters|. Access is limited to the current
  // origin, and to the union of |options->filters->services| and
  // |options->optional_services|. Multiple devices may be discoverable that
  // match and one must be selected via a chooser user interface.
  RequestDevice(WebBluetoothRequestDeviceOptions options)
    => (WebBluetoothResult result, WebBluetoothDevice? device);

  // Returns a list of permitted Bluetooth devices that the current origin can
  // access services on. These devices are granted access via RequestDevice(),
  // but the permission can be revoked at any time by the user through the
  // browser's UI or by the website through ForgetDevice().
  GetDevices() => (array<WebBluetoothDevice> devices);

  // Attempts to revoke the permission to the Device identified by |device_id|.
  // It will fail silently if the permission cannot be revoked.
  ForgetDevice(WebBluetoothDeviceId device_id) => ();

  // Creates a GATT Connection to a Bluetooth Device identified by |device_id|
  // if a connection to the device didn't exist already. If a GATT connection
  // existed already then this function increases the ref count to keep that
  // connection alive.
  // Returns the result of the connection request.
  RemoteServerConnect(
    WebBluetoothDeviceId device_id,
    pending_associated_remote<WebBluetoothServerClient> client) => (
    WebBluetoothResult result);

  // If a GATT connection exists for Device identified by |device_id| then
  // decreases the ref count for that connection.
  RemoteServerDisconnect(WebBluetoothDeviceId device_id);

  // Returns the Services of a GATT Device identified by |device_id|.
  // If |services_uuid| is present, filters services by |services_uuid|.
  // Otherwise returns all non-blocklisted services.
  // If |quantity| == WebBluetoothGATTQueryQuantity::SINGLE, at most one
  // service will be returned.
  RemoteServerGetPrimaryServices(
    WebBluetoothDeviceId device_id,
    WebBluetoothGATTQueryQuantity quantity,
    bluetooth.mojom.UUID? services_uuid) => (
      WebBluetoothResult result,
      array<WebBluetoothRemoteGATTService>? services);

  // Returns the Characteristics of a GATT Service identified by
  // |service_instance_id|.
  // If |characteristics_uuid| is present, filters characteristics by
  // |characteristics_uuid|. Otherwise returns all non-blocklisted services.
  // If |quantity| == WebBluetoothGATTQueryQuantity::SINGLE, at most one
  // characteristic will be returned.
  RemoteServiceGetCharacteristics(
    string service_instance_id,
    WebBluetoothGATTQueryQuantity quantity,
    bluetooth.mojom.UUID? characteristics_uuid) => (
      WebBluetoothResult result,
      array<WebBluetoothRemoteGATTCharacteristic>? characteristics);

  // Reads the value for the characteristic identified by
  // |characteristic_instance_id|. If the value is successfully read the
  // callback will be run with WebBluetoothResult::SUCCESS and the
  // characteristic's value. If the value is not successfully read the
  // callback with be run with the corresponding error and nullptr for value.
  RemoteCharacteristicReadValue(
    string characteristic_instance_id) => (
    WebBluetoothResult result,
    array<uint8>? value);

  // Writes a value to the characteristic identified by
  // |characteristic_instance_id|. The callback is run with
  // WebBluetoothResult::SUCCESS if the value was successfully
  // written.
  RemoteCharacteristicWriteValue(
    string characteristic_instance_id,
    array<uint8> value,
    WebBluetoothWriteType write_type) => (WebBluetoothResult result);

  // Starts notifications for the characteristic identified by
  // |characteristic_instance_id|.
  // Returns the result of the connection request.
  RemoteCharacteristicStartNotifications(
    string characteristic_instance_id,
    pending_associated_remote<WebBluetoothCharacteristicClient> client) => (
      WebBluetoothResult result);

  // Stops notifications for the characteristic identified by
  // |characteristic_instance_id|.
  RemoteCharacteristicStopNotifications(
    string characteristic_instance_id) => ();

  // Returns the Descriptors of a GATT Characteristic identified by
  // |characteristics_instance_id|.
  // If |descriptor_uuid| is present, filters descriptors by
  // |descriptor_uuid|. Otherwise returns all non-blocklisted descriptors.
  // If |quantity| == WebBluetoothGATTQueryQuantity::SINGLE, at most one
  // characteristic will be returned.
  RemoteCharacteristicGetDescriptors(
    string characteristics_instance_id,
    WebBluetoothGATTQueryQuantity quantity,
    bluetooth.mojom.UUID? descriptor_uuid) => (
      WebBluetoothResult result,
      array<WebBluetoothRemoteGATTDescriptor>? descriptors);

  // Reads the value for the descriptor identified by
  // |descriptor_instance_id|. If the value is successfully read the callback
  // will be run with WebBluetoothResult::SUCCESS and the descriptor's value. If
  // the value is not successfully read the callback with be run with the
  // corresponding error and nullptr for value
  RemoteDescriptorReadValue(
    string descriptor_instance_id) => (
    WebBluetoothResult result,
    array<uint8>? value);

  // Writes a value to the descriptor identified by
  // |descriptor_instance_id|. The callback is run with
  // WebBluetoothResult::SUCCESS if the value was successfully
  // written.
  RemoteDescriptorWriteValue(
    string descriptor_instance_id,
    array<uint8> value) => (WebBluetoothResult result);

  // Starts scanning for low energy devices.
  RequestScanningStart(
    pending_associated_remote<WebBluetoothAdvertisementClient> client,
    WebBluetoothRequestLEScanOptions options) => (
    WebBluetoothResult result);

  // Starts scanning for advertisements packets from the device associated with
  // |device_id|. |client| will be notified when advertisement packets are
  // detected for the device. The scan will be terminated if |client| is
  // disconnected.
  WatchAdvertisementsForDevice(
    WebBluetoothDeviceId device_id,
    pending_associated_remote<WebBluetoothAdvertisementClient> client)
    => (WebBluetoothResult result);
};

// Classes that implement this interface will be notified of device events.
interface WebBluetoothServerClient {
  // Called when a device disconnects.
  GATTServerDisconnected();
};

// Classes that implement this interface will be notified of characteristic
// events.
interface WebBluetoothCharacteristicClient {
  // Called when we receive a notification for the characteristic.
  RemoteCharacteristicValueChanged(array<uint8> value);
};

// Classes that implement this interface will be notified of device
// advertisement events.
interface WebBluetoothAdvertisementClient {
  // Called when we receive a device advertisement.
  AdvertisingEvent(WebBluetoothAdvertisingEvent result);
};