chromium/chromeos/ash/services/nearby/public/mojom/nearby_connections.mojom

// 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 nearby.connections.mojom;

import "chromeos/ash/services/nearby/public/mojom/nearby_connections_types.mojom";
import "chromeos/ash/services/nearby/public/mojom/nearby_presence.mojom";
import "mojo/public/mojom/base/file.mojom";
import "mojo/public/mojom/base/read_only_file.mojom";

// Listener invoked during endpoint discovery. This interface is used by the
// browser process to listen for remote endpoints status during endpoint
// discovery.
interface EndpointDiscoveryListener {
  // Called when a remote endpoint is discovered.
  //
  // endpoint_id - The ID of the remote endpoint that was discovered.
  // info        - Further information about the remote endpoint which may
  //               include the human readable name if it is advertising in high
  //               visibility mode.
  OnEndpointFound(string endpoint_id, DiscoveredEndpointInfo info);

  // Called when a remote endpoint is no longer discoverable; only called for
  // endpoints that previously had been passed to OnEndpointFound().
  //
  // endpoint_id - The ID of the remote endpoint that was lost.
  OnEndpointLost(string endpoint_id);
};

// Listener for lifecycle events associated with a connection to a remote
// endpoint. Methods in this interface are called from utility process, and is
// used by the browser process to listen for connection status associated with
// remote endpoints.
interface ConnectionLifecycleListener {
  // A basic encrypted channel has been created between this device and the
  // the remote endpoint. Both sides are now asked if they wish to accept or
  // reject the connection before any data can be sent over this channel.
  //
  // Optionally, caller can verify if this device is connected to the correct
  // remote before accepting the connection. Typically this involves showing
  // ConnectionInfo::authentication_token on both devices and having the users
  // manually compare and confirm. Both devices are given an identical
  // authentication token.
  //
  // Call NearbyConnections::AcceptConnection() to accept the connection, or
  // NearbyConnections::RejectConnection() to close the connection.
  //
  // endpoint_id - The identifier for the remote endpoint.
  // info        -  Other relevant information about the connection.
  OnConnectionInitiated(string endpoint_id, ConnectionInfo info);

  // Called after both sides have accepted the connection.
  //
  // endpoint_id - The identifier for the remote endpoint.
  OnConnectionAccepted(string endpoint_id);

  // Called when either side rejected the connection.
  // Call NearbyConnections::DisconnectFromEndpoint() to terminate connection.
  //
  // endpoint_id - The identifier for the remote endpoint.
  // status      - The result of the connection. Valid values are
  //               Status::kSuccess and Status::kConnectionRejected}.
  OnConnectionRejected(string endpoint_id, Status status);

  // Called when a remote endpoint is disconnected or has become unreachable.
  // At this point service (re-)discovery may start again.
  //
  // endpoint_id - The identifier for the remote endpoint.
  OnDisconnected(string endpoint_id);

  // Called when the connection's available bandwidth has changed.
  //
  // endpoint_id - The identifier for the remote endpoint.
  // quality     - The new quality for the connection.
  OnBandwidthChanged(string endpoint_id, Medium medium);
};

// Listener for payload status. Methods in this interface are called from
// utility process, and is used by the browser process to listen for payload
// status associated with remote endpoints.
interface PayloadListener {
  // Called when a Payload is received from a remote endpoint. Depending on the
  // type of the Payload, all of the data may or may not have been received at
  // the time of this call. Use OnPayloadTransferUpdate() to get updates on the
  // status of the data received.
  //
  // endpoint_id - The identifier for the remote endpoint that sent the
  //               payload.
  // payload     - The Payload object received.
  OnPayloadReceived(string endpoint_id, Payload payload);

  // Called with progress information about an active Payload transfer, either
  // incoming or outgoing.
  //
  // endpoint_id - The identifier for the remote endpoint that is sending or
  //               receiving this payload.
  // update      - The PayloadTransferUpdate structure describing the status of
  //               the transfer.
  OnPayloadTransferUpdate(string endpoint_id, PayloadTransferUpdate update);
};

// Listener for lifecycle events associated with a connection to a remote
// device. Methods in this interface are called from utility process, and is
// used by the browser process to listen for connection status associated with
// remote devices.
//
// This should stay aligned with v3::ConnectionListener defined at:
// //third_party/nearby/src/connections/v3/listeners.h
interface ConnectionListenerV3 {
  // A basic encrypted channel has been created between you and the device.
  // Both sides are now asked if they wish to accept or reject the connection
  // before any data can be sent over this channel.
  //
  // This is your chance, before you accept the connection, to confirm that you
  // connected to the correct device. Both devices are given an identical token;
  // it's up to you to decide how to verify it before proceeding. Typically this
  // involves showing the token on both devices and having the users manually
  // compare and confirm; however, this is only required if you desire a secure
  // connection between the devices.
  //
  // For Presence, devices are authenticated using the devices' credentials to
  // confirm that the remote device has the correct key pairing detected during
  // advertising. There is no need to do an additional verification of keys
  // during this step if this is successful. See (go/np-nc-handshake) for more
  // details.
  //
  // Whichever route you decide to take (including not authenticating the other
  // device), call Core::AcceptConnectionV3() when you're ready to talk, or
  // Core::RejectConnectionV3() to close the connection.
  //
  // endpoint_id   - The endpoint identifier for the remote device.
  // info          - Other relevant information about the connection.
  OnConnectionInitiatedV3(string endpoint_id, InitialConnectionInfoV3 info);

  // Called when both sides have accepted or either side has rejected the
  // connection. If the `ConnectionResolution` status is `kSuccess`, both sides
  // have accepted the connection and may now send `Payload` to each other.
  // Otherwise, the connection was rejected.
  //
  // endpoint_id   - The endpoint identifier for the remote device.
  // resolution    - The resolution of the connection (accepted or rejected).
  OnConnectionResultV3(string endpoint_id, Status resolution);

  // Called when a remote device is disconnected or has become unreachable.
  // At this point service (re-)discovery may start again.
  //
  // endpoint_id   - The endpoint identifier for the remote device.
  OnDisconnectedV3(string endpoint_id);

  // Called when the connection's available bandwidth has changed.
  //
  // endpoint_id    - The endpoint identifier for the remote device.
  // bandwidth_info - Bandwidth info about the new medium that was upgraded to.
  OnBandwidthChangedV3(string endpoint_id, BandwidthInfo bandwidth_info);
};

// Listener for payload status, used by the V3 APIs. Methods in this interface
// are called from utility process, and is used by the browser process to listen
// for payload status associated with remote endpoints.
//
// This should stay loosely aligned with `v3::PayloadListener` defined at:
// //third_party/nearby/src/connections/v3/listeners.h
interface PayloadListenerV3 {
  // Called when a Payload is received from a remote endpoint. Depending
  // on the type of the Payload, all of the data may or may not have been
  // received at the time of this call. Use `OnPayloadTransferUpdateV3()` to
  // get updates on the status of the data received.
  //
  // endpoint_id - The identifier for the remote endpoint that is sending or
  //               receiving this payload.
  // payload     - The Payload object received.
  OnPayloadReceivedV3(string endpoint_id, Payload payload);

  // Called with progress information about an active Payload transfer, either
  // incoming or outgoing.
  //
  // endpoint_id - The identifier for the remote endpoint that is sending or
  //               receiving this payload.
  // update      - The PayloadTransferUpdate structure describing the status
  //               of the transfer.
  OnPayloadTransferUpdateV3(string endpoint_id, PayloadTransferUpdate update);
};

// Main interface to control the NearbyConnections library. Implemented in a
// sandboxed process. This interface is used by the browser process to connect
// to remote devices and send / receive raw data packets. Parsing of those
// packets is not part of the NearbyConnections library and is done in a
// separate interface.
interface NearbyConnections {
  // Starts advertising an endpoint with the specified service ID. Only one
  // advertisement can be active at a time and calling StartAdvertising() while
  // advertising will fail and return Status::kAlreadyAdvertising.
  //
  // service_id    - An identifier to advertise your app to other endpoints.
  //                 This can be an arbitrary string, so long as it uniquely
  //                 identifies your service. A good default is to use your
  //                 app's package name.
  // endpoint_info - The local info to be broadcasted. May contain a human
  //                 readable name to appear on other devices if broadcasting
  //                 in high visibility mode.
  // options       - The options for advertising.
  // listener      - An interface notified when remote endpoints request a
  //                 connection to this endpoint.
  // Possible return values include:
  //   Status::kSuccess if advertising started successfully.
  //   Status::kAlreadyAdvertising if the app is already advertising.
  //   Status::kOutOfOrderApiCall if the app is currently connected to remote
  //       endpoints; call StopAllEndpoints first.
  StartAdvertising(string service_id, array<uint8> endpoint_info,
                   AdvertisingOptions options,
                   pending_remote<ConnectionLifecycleListener> listener)
      => (Status status);

  // Stops advertising the local endpoint. Should be called after calling
  // StartAdvertising, as soon as the application no longer needs to advertise
  // itself or goes inactive. Payloads can still be sent to connected
  // endpoints after advertising ends.
  //
  // service_id - Identifier used in the preceding StartAdvertising() call.
  //
  // Possible return values include:
  //   Status::kSuccess returned after advertising got stopped.
  StopAdvertising(string service_id) => (Status status);

  // Starts discovery for remote endpoints with the specified service ID.
  //
  // service_id - The ID for the service to be discovered, as specified in
  //              the corresponding call to StartAdvertising.
  // options    - The options for discovery.
  // listener   - An interface notified when a remote endpoint is discovered.
  // Possible status codes include:
  //   Status::kSuccess if discovery started successfully.
  //   Status::kAlreadyDiscovering if the app is already
  //       discovering the specified service.
  //   Status::kOutOfOrderApiCall if the app is currently
  //       connected to remote endpoints; call StopAllEndpoints first.
  StartDiscovery(string service_id, DiscoveryOptions options,
                 pending_remote<EndpointDiscoveryListener> listener)
      => (Status status);

  // Stops discovery for remote endpoints, after a previous call to
  // StartDiscovery, when the client no longer needs to discover endpoints or
  // goes inactive. Payloads can still be sent to connected endpoints after
  // discovery ends.
  //
  // service_id - Identifier used in the preceding StartDiscovery() call.
  //
  // Possible return values include:
  //   Status::kSuccess returned after discovery got stopped.
  StopDiscovery(string service_id) => (Status status);

  // Attempts an out-of-band discovery from a previous call to StartDiscovery()
  // which included the is_out_of_band_discovery option. If successful, this
  // call results in the EndpointDiscoveryListener::OnEndpointFound() callback
  // corresponding to the |listener| parameter to StartDiscovery() being
  // invoked.
  //
  // Before invoking this function, StartDiscovery() should have been called
  // with DiscoveryOptions that set |is_out_of_band_connection| to true.
  // After this call completes, it is safe to invoke StopDiscovery().
  //
  // service_id                   - Identifier used in the preceding
  //                                StartDiscovery() call.
  // endpoint_id                  - String of length 4 which should be randomly
  //                                generated to uniquely identify this request.
  //                                Note that there is only a single caller of
  //                                this function, so collisions are highly
  //                                unlikely since this field is randomly-
  //                                generated.
  // endpoint_info                - Describes the injected endpoint; will be
  //                                passed to the OnEndpointFound() callback.
  //                                Should uniquely identify this request so
  //                                that clients can identify the injected
  //                                endpoint. Must be >0 bytes and <131 bytes.
  // remote_bluetooth_mac_address - MAC address of the injected device.
  // Possible return values include:
  //   Status::kSuccess if endpoint injection was attempted.
  //   Status::kError if |remote_bluetooth_mac_address| is malformed.
  //   Status::kOutOfOrderApiCall if the app is not discovering.
  InjectBluetoothEndpoint(
      string service_id,
      string endpoint_id,
      array<uint8> endpoint_info,
      array<uint8, 6> remote_bluetooth_mac_address) => (Status status);

  // Sends a request to connect to a remote endpoint.
  //
  // service_id    - Service ID used to discover the endpoint.
  // endpoint_info - The local info including a human readable name to appear on
  //                 the remote endpoint.
  // endpoint_id   - The identifier for the remote endpoint to which a
  //                 connection request will be sent. Should match the value
  //                 provided in a call to
  //                 EndpointDiscoveryListener::OnEndpointFound().
  // options       - The options for connection.
  // listener      - An interface notified when the remote endpoint sends a
  //                 response to the connection request.
  // Possible return values include:
  //   Status::kSuccess if the connection request was sent.
  //   Status::kAlreadyConnectedToEndpoint if the app already
  //       has a connection to the specified endpoint.
  //   Status::kBluetoothError if we failed to connect because of an
  //       issue with Bluetooth.
  //   Status::kWifiLanError if we failed to connect because of an
  //       issue with WiFi.
  //   Status::kError if we failed to connect for any other reason.
  RequestConnection(string service_id,
                    array<uint8> endpoint_info,
                    string endpoint_id,
                    ConnectionOptions options,
                    pending_remote<ConnectionLifecycleListener> listener)
      => (Status status);

  // Accepts a connection to a remote endpoint. This method must be called
  // before Payloads can be exchanged with the remote endpoint.
  //
  // service_id  - Service ID used to bootstrap the connection.
  // endpoint_id - The identifier for the remote endpoint. Should match the
  //               value provided in a call to
  //               ConnectionsLifecycleListener::OnConnectionInitiated().
  // listener    - An interface for payloads exchanged with the remote endpoint.
  // Possible return values include:
  //   Status::kSuccess if the connection request was accepted.
  //   Status::kAlreadyConnectedToEndpoint if the app already as a connection
  //       to the specified endpoint.
  //   Status::kOutOfOrderApiCall if
  //       ConnectionsLifecycleListener::OnConnectionInitiated() has not been
  //       called for the |endpoint_id|.
  AcceptConnection(string service_id,
                   string endpoint_id,
                   pending_remote<PayloadListener> listener)
      => (Status status);

  // Rejects a connection to a remote endpoint.
  //
  // service_id  - Service ID used to bootstrap the connection.
  // endpoint_id - The identifier for the remote endpoint. Should match the
  //               value provided in a call to
  //               ConnectionsLifecycleListener::OnConnectionInitiated().
  // Possible return values include:
  //   Status::kSuccess if the connection request was rejected.
  //   Status::kAlreadyConnectedToEndpoint if the app already has a connection
  //       to the specified endpoint.
  //   Status::kOutOfOrderApiCall if
  //       ConnectionsLifecycleListener::OnConnectionInitiated() has not been
  //       called for the |endpoint_id|.
  RejectConnection(string service_id, string endpoint_id) => (Status status);

  // Disconnects from a remote endpoint. Payloads can no longer be sent
  // to or received from the endpoint after this method is called.
  //
  // service_id  - Service ID used to bootstrap the connection.
  // endpoint_id - The identifier for the remote endpoint to disconnect from.
  // Possible return values include:
  //   Status::kSuccess disconnected successfully.
  DisconnectFromEndpoint(string service_id,
                         string endpoint_id) => (Status status);

  // Sends a Payload to a list of remote endpoints. Payloads can only be sent to
  // remote endpoints once a notice of connection acceptance has been delivered
  // via ConnectionsLifecycleListener::OnConnectionResult().
  //
  // service_id   - Service ID used to bootstrap the connection.
  // endpoint_ids - Array of remote endpoint identifiers for to which the
  //                payload should be sent.
  // payload      - The Payload to be sent.
  // Possible return values include:
  //   Status::kOutOfOrderApiCall if the device has not first performed
  //       advertisement or discovery (to set the Strategy).
  //   Status::kEndpointUnknown if there's no active (or pending) connection to
  //       the remote endpoint.
  //   Status::kSuccess if none of the above errors occurred. Note that this
  //       indicates that Nearby Connections will attempt to send the Payload,
  //       but not that the send has successfully completed yet. Errors might
  //       still occur during transmission (and at different times for different
  //       endpoints), and will be delivered via
  //       PayloadListener::OnPayloadTransferUpdate().
  SendPayload(string service_id,
              array<string> endpoint_ids,
              Payload payload) => (Status status);

  // Cancels a Payload currently in-flight to or from remote endpoint(s).
  //
  // service_id - Service ID used to bootstrap the connection.
  //
  // payload_id - The identifier for the Payload to be cancelled.
  // Possible return values include:
  //   Status::kSuccess if the payload got cancelled.
  CancelPayload(string service_id, int64 payload_id) => (Status status);

  // Disconnects from, and removes all traces of, all connected and/or
  // discovered endpoints. As a side effect of this call, both
  // StopAdvertising and StopDiscovery are invoked. After calling
  // StopAllEndpoints, no further operations with remote endpoints will
  // be possible until a new call to one of StartAdvertising or
  // StartDiscovery.
  //
  // service_id   - Service ID used to discover endpoints.
  //
  // Possible return values include:
  //   Status::kSuccess disconnected from all endpoints successfully.
  StopAllEndpoints(string service_id) => (Status status);

  // Sends a request to initiate connection bandwidth upgrade.
  //
  // Important note: Bandwidth upgrades may expose stable identifiers,
  // which are only safe to expose after the caller has verified
  // the sender's identity. If the caller is already performing
  // high-visibility advertising (and thus already leaking the device
  // name), then calling this method introduces no further privacy
  // leaks -- in fact, the caller should consider instead requesting
  // to auto-upgrade bandwidth when invoking StartAdvertising().
  //
  // service_id  - Service ID used to discover the endpoint.
  // endpoint_id - The identifier for the remote endpoint which will be
  //               switching to a higher connection data rate and possibly
  //               different wireless protocol. On success, calls
  //               ConnectionLifecycleListener::OnBandwidthChanged.
  // Possible return values include:
  //   Status::kSuccess if upgraded successfully.
  InitiateBandwidthUpgrade(string service_id,
                           string endpoint_id) => (Status status);

  // Register a pair of input and output file for handling incoming file
  // payload associated with |payload_id_|, which is determined by feature
  // specific design. The |input_file| should be opened for read access, and
  // |output_file| should be opened for write access.
  //
  // service_id  - Service ID used to discover the endpoint.
  //
  // Possible return values include:
  //   Status::kSuccess if file is registered successfully.
  //   Status::kError if file is not opened correctly.
  RegisterPayloadFile(string service_id,
                      int64 payload_id,
                      mojo_base.mojom.ReadOnlyFile input_file,
                      mojo_base.mojom.File output_file)
      => (Status status);

  //******************************* V3 *******************************
  // NOTE: Do NOT mix with the V1 APIs above, this might result in undefined
  // behavior!

  // Sends a request to connect to a remote device.
  //
  // service_id         - Service ID used to discover the device.
  // remote_device      - The remote device to which a connection request will
  //                      be sent.
  // connection_options - Connection options for the new connection if both
  //                      sides accept.
  // listener           - An interface notified when the remote device sends
  //                      a response to the connection request.
  // Possible return values include:
  // TODO(b/307319934): Clean up Status values to no longer reference endpoints
  // when the V3 API migration occurs.
  //   Status::kSuccess if the connection request was accepted.
  //   Status::kAlreadyConnectedToEndpoint if the app already has a connection
  //       to the specified device.
  //   Status::kBluetoothError if we failed to connect because of an issue with
  //       Bluetooth.
  //   Status::kWifiLanError if we failed to connect because of an issue with
  //       Wi-Fi.
  //   Status::kError if we failed to connect for any other reason.
  //
  // TODO(b/306188252): This API will initially only be used by Nearby Presence
  // client applications, and therefore uses a PresenceDevice type for its
  // `remote_device` argument. This will eventually be replaced with the
  // NearbyDevice type to allow use by Nearby Connections/non-Presence clients.
  RequestConnectionV3(string service_id,
                      ash.nearby.presence.mojom.PresenceDevice remote_device,
                      ConnectionOptions connection_options,
                      pending_remote<ConnectionListenerV3> listener)
      => (Status status);

  // Accepts a connection to a remote device. This method must be called
  // before Payloads can be exchanged with the remote device.
  //
  // service_id    - Service ID used to discover the device.
  // remote_device - The remote device we are accepting the connection from.
  // listener      - An interface for payloads exchanged with the remote device.
  // Possible status codes include:
  // TODO(b/307319934): Clean up Status values to no longer reference endpoints
  // when the V3 API migration occurs.
  //   Status::kSuccess if the connection request was accepted.
  //   Status::kAlreadyConnectedToEndpoint if the app already has a connection
  //       to the specified device.
  //   Status::kEndpointUnknown if the app doesn't currently have a pending
  //       connection to the remote device.
  AcceptConnectionV3(string service_id,
                     ash.nearby.presence.mojom.PresenceDevice remote_device,
                     pending_remote<PayloadListenerV3> listener)
      => (Status status);

  // Rejects a connection to a remote device.
  //
  // service_id    - Service ID used to discover the device.
  // remote_device - The device for the remote device.
  // Possible status codes include:
  // TODO(b/307319934): Clean up Status values to no longer reference endpoints
  // when the V3 API migration occurs.
  //   Status::kSuccess if the connection request was rejected.
  //   Status::kAlreadyConnectedToEndpoint if the app already has a connection
  //       to the specified device.
  RejectConnectionV3(string service_id,
                     ash.nearby.presence.mojom.PresenceDevice remote_device)
      => (Status status);

  // Disconnects from a remote device. Payloads can no longer be sent to or
  // received from the device after this function is called.
  //
  // service_id    - Service ID used to discover the device.
  // remote_device - The remote device to disconnect from.
  // Possible status codes include:
  //   Status::kSuccess upon successful disconnection.
  //
  // TODO(b/306188252): This API will initially only be used by Nearby Presence
  // client applications, and therefore uses a PresenceDevice type for its
  // `remote_device` argument. This will eventually be replaced with the
  // NearbyDevice type to allow use by Nearby Connections/non-Presence clients.
  DisconnectFromDeviceV3(string service_id,
                         ash.nearby.presence.mojom.PresenceDevice remote_device)
      => (Status status);

  // Registers Nearby Presence's `LocalDeviceProvider` with the Nearby
  // Connections Core associated with the given `service_id`. The registered
  // `PresenceDeviceProvider` is used on future `ConnectV3()` calls made by
  // Nearby Connections. A LocalDeviceProvider provides a representation of
  // the local device (ChromeOS) as a NearbyDevice and is used for
  // authentication during connection attempts.
  RegisterServiceWithPresenceDeviceProvider(string service_id);
};