chromium/components/media_router/common/mojom/media_router.mojom

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

module media_router.mojom;

import "components/media_router/common/mojom/logger.mojom";
import "components/media_router/common/mojom/debugger.mojom";
import "components/media_router/common/mojom/media_controller.mojom";
import "components/media_router/common/mojom/media_route_provider_id.mojom";
import "components/media_router/common/mojom/media_status.mojom";
import "components/media_router/common/mojom/route_request_result_code.mojom";
import "mojo/public/mojom/base/time.mojom";
import "mojo/public/mojom/base/values.mojom";
import "services/network/public/mojom/ip_address.mojom";
import "services/network/public/mojom/ip_endpoint.mojom";
import "third_party/blink/public/mojom/presentation/presentation.mojom";
import "url/mojom/origin.mojom";
import "url/mojom/url.mojom";

// This must stay in sync with media_router::SinkIconType and ash::SinkIconType.
enum SinkIconType {
  CAST = 0,
  CAST_AUDIO_GROUP = 1,
  CAST_AUDIO = 2,
  WIRED_DISPLAY = 6,
  GENERIC = 7
};

// Represents an output sink to which media can be routed.
struct MediaSink {
  // The sink identifier, e.g. "rs71w7mFzYLFlabir_qO4NHl6SUc."
  string sink_id;
  // The human-readable name, e.g. "Janet's Chromecast".
  string name;
  // The type of icon to show in the UI for this media sink.
  SinkIconType icon_type;
  // The ID of the MediaRouteProvider that this sink belongs to.
  MediaRouteProviderId provider_id;
  // This is currently only set by MediaRouter in OnSinksDiscovered().
  MediaSinkExtraData? extra_data;
};

union MediaSinkExtraData {
  DialMediaSink dial_media_sink;
  CastMediaSink cast_media_sink;
};

struct DialMediaSink {
  network.mojom.IPAddress ip_address;

  // Model name of the sink, if it represents a physical device.
  string model_name;

  // Used for DIAL launch
  url.mojom.Url app_url;
};

struct CastMediaSink {
  network.mojom.IPEndPoint ip_endpoint;

  // Model name of the sink, if it represents a physical device.
  string model_name;

  // Bit vector representing capabilities of the sink.  Enum values are defined
  // by CastDeviceCapability in cast_device_capability.h.
  uint64 capabilities;

  // ID of Cast channel opened by Media Router. The ID is defined by the
  // chrome.cast.channel API.
  int32 cast_channel_id;
};

enum RouteControllerType {
  kNone,      // No route controller.
  kGeneric,   // Route controller for sessions with media controls (apps).
  kMirroring  // Route controller for Cast mirroring and remoting sessions.
};

// MediaRoute objects contain the status and metadata of a routing
// operation.
// This struct should be kept in sync with media_route.h.
struct MediaRoute {
  // The ID of this media route, e.g. "r_PR1O_blkC9dsKp-tb1ti8qurOo".
  string media_route_id;
  // The ID of the presentation that this route is associated with.
  string presentation_id;
  // The ID of the media source being sent through this media route.
  // May be missing if route is not local.
  string? media_source;
  // The ID of sink that is rendering the media content.
  string media_sink_id;
  // Human readable name of the sink.
  string media_sink_name;
  // Human readable description of the casting activity.  Examples:
  // "Mirroring tab (www.example.com)", "Casting media", "Casting YouTube"
  string description;
  // Specifies that the route is requested locally.
  bool is_local;
  // The type of route controller that can be created for this route. See
  // media_controller.mojom for details.
  RouteControllerType controller_type;
  // Set to true if this route corresponds to a local presentation.
  bool is_local_presentation;
  // Set to true if this route has been created by the MRP but is waiting for
  // the receiver's response.
  bool is_connecting;
};

struct Issue {
  enum Severity {
    WARNING,
    NOTIFICATION
  };

  // If set, the ID of the route to which this issue pertains.
  // If this is an empty string (default), then this is a global issue.
  string route_id;

  // The ID of the sink associated with this issue.
  // If this is an empty string (default), then this is a global issue.
  string sink_id;

  Severity severity;

  // Short description about the issue.
  string title;

  // Message about issue detail or how to handle issue.
  // Messages should be suitable for end users to decide which actions to take.
  string? message;
};

struct RouteMessage {
  enum Type {
    TEXT,
    BINARY
  };
  // The type of this message.
  Type type;
  // Used when the |type| is TEXT.
  string? message;
  // Used when the |type| is BINARY.
  array<uint8>? data;
};

// Used to pass a pair of PresentationConnection pipes as part of a route
// result.  An MRP may return this as part of any route creation callback to
// allow direct communication with the controlling page.
struct RoutePresentationConnection {
  // Remote to send messages to the MRP.
  pending_remote<blink.mojom.PresentationConnection> connection_remote;

  // Receiver which the controlling page should bind to receive messages from
  // the MRP.
  pending_receiver<blink.mojom.PresentationConnection> connection_receiver;
};

// State of one active Cast session.
struct CastSessionState {
  // The Media Sink ID for the session.
  string sink_id;
  // The Cast App ID that the session is currently running.
  string app_id;
  // The session ID assigned by the Cast Receiver.
  string session_id;
  // Human readable description of the app or session, e.g. "Netflix."
  string route_description;
};

// The state of the Cast Media Route Provider.
struct CastProviderState {
  // Includes all sessions running on known (local network) Cast receivers.
  array<CastSessionState> session_state;
};

// Returned to the Media Router to reflect the state of a single route
// provider for chrome://media-router-internals.
union ProviderState {
  // The state of the Cast MRP.
  CastProviderState cast_provider_state;
};

// Modeled after the MediaRouter interface defined in
// chrome/browser/media/router/media_router.h
//
// MediaRouteProvider is responsible for discovering MediaSinks, and managing
// MediaRoutes associated with them.
// A MediaRouteProvider is associated with a MediaRouter. MediaRouter issues
// commands to the MediaRouteProvider, such as observing MediaSinks or creating
// a MediaRoute. In return, the MediaRouteProvider notifies the MediaRouter when
// there are changes related to sinks or routes.
// Each MRP is used to manage one type of media sinks (e.g. the Cast MRP is used
// for CAST sinks)
// WIRED_DISPLAY, CAST and DIAL MRPs live in the browser. ANDROID_CAF is the
// Cast Application Framework based MRPs used on Android only.
interface MediaRouteProvider {
  // Creates a media route from |media_source| to the sink given by |sink_id|.
  //
  // The presentation ID of the route created will be |presentation_id|, but it
  // may be overridden by a provider implementation. The presentation ID will
  // be used by the presentation API to refer to the created route.
  //
  // |origin| and |frame_tree_node_id| may be passed in for enforcing
  // same-origin and/or same-tab scopes. Use -1 as |frame_tree_node_id| in
  // cases where the request is not made on behalf of a tab.
  //
  // If |timeout| is positive, it will be used in place of the default timeout
  // defined by Media Route Provider Manager.
  //
  // If the operation was successful, |route| will be defined and |error_text|
  // will be null.  If the operation failed, |route| will be null and
  // |error_text| will be set.  If |connection| is set, it should be returned to
  // the presentation controller for communication with the MRP/receiver.
  //
  // |result_code| will be set to OK if successful, or an error code if an error
  // occurred.
  // TODO(crbug.com/1346066): Consolidate parameters into a struct.
  // TODO(crbug.com/1351184): Make |frame_tree_node_id| optional.
  CreateRoute(string media_source,
              string sink_id,
              string original_presentation_id,
              url.mojom.Origin origin,
              int32 frame_tree_node_id,
              mojo_base.mojom.TimeDelta timeout) =>
                  (MediaRoute? route,
                   RoutePresentationConnection? connection,
                   string? error_text,
                   RouteRequestResultCode result_code);

  // Requests a connection to an established route for |media_source| given
  // by |presentation_id|.
  //
  // |origin| and |frame_tree_node_id| are used for validating same-origin/tab
  // scopes; see CreateRoute for additional documentation.
  //
  // If |timeout| is positive, it will be used in place of the default timeout
  // defined by Media Route Provider Manager.
  //
  // If the operation was successful, |route| will be defined and |error_text|
  // will be null.  If the operation failed, |route| will be null and
  // |error_text| will be set.  If |connection| is set, it should be returned to
  // the presentation controller for communication with the MRP/receiver.
  //
  // |result_code| will be set to OK if successful, or an error code if an error
  // occurred.
  // TODO(crbug.com/1346066): Consolidate parameters into a struct.
  // TODO(crbug.com/1351184): Make |frame_tree_node_id| optional.
  JoinRoute(string media_source,
            string presentation_id,
            url.mojom.Origin origin,
            int32 frame_tree_node_id,
            mojo_base.mojom.TimeDelta timeout) =>
                (MediaRoute? route,
                 RoutePresentationConnection? connection,
                 string? error_text,
                 RouteRequestResultCode result_code);

  // Terminates the route specified by |route_id|.  If the route was terminated
  // successfully, |result_code| is set to OK and |error_text| is null.
  // Otherwise, |result_code| is an error code and |error_text| describes the
  // error.
  TerminateRoute(string route_id) =>
      (string? error_text, RouteRequestResultCode result_code);

  // Sends |message| via the media route |media_route_id|.
  // If the operation was successful, |sent| is true; otherwise it is false.
  SendRouteMessage(string media_route_id, string message);

  // Sends |data| via the media route |media_route_id|.
  // If the operation was successful, |sent| is true; otherwise it is false.
  SendRouteBinaryMessage(string media_route_id, array<uint8> data);

  // Starts querying for sinks capable of displaying |media_source|. If
  // |media_source| is empty, queries for all available sinks.
  StartObservingMediaSinks(string media_source);

  // Stops querying sinks for |media_source|.
  StopObservingMediaSinks(string media_source);

  // Starts reporting the state of active media routes.
  StartObservingMediaRoutes();

  // Indicates that a PresentationConnection that was connected to route
  // |route_id| has been closed (via .close(), garbage collection or
  // navigation).
  DetachRoute(string route_id);

  // Enables mDNS discovery. No-op if mDNS discovery is already enabled.
  // Calling this will trigger a firewall prompt on Windows if there is not
  // already a firewall rule for mDNS.
  EnableMdnsDiscovery();

  // Requests the MediaRouteProvider to update its list of media sinks.
  // This is called when a user gesture occurs, and the MRP is expected to
  // initiate discovery of media sinks in response.
  DiscoverSinksNow();

  // Binds the |media_controller| for the media route with given |route_id| to
  // receive media commands, and binds the |observer| to be notified whenever
  // there is a change in the status of the media route. This method can be
  // called multiple times with the same |route_id| to bind multiple
  // |media_controller|s and |observer|s. This method returns false if the media
  // route for |route_id| does not exist or there was an error while binding the
  // |media_controller|. This method must close |media_controller| in case
  // of such a failure. |media_controller| becomes invalid when the media route
  // is terminated by calling |TerminateRoute|.
  BindMediaController(
      string route_id,
      pending_receiver<MediaController> media_controller,
      pending_remote<MediaStatusObserver> observer) => (bool success);

  // Returns the state of this Media Route Provider for debugging; returns null
  // if this MRP does not report any state.
  //
  // Currently, only the Cast MRP returns a state value.
  GetState() => (ProviderState? state);
};

// Interface for a service which observes MediaRouteProviders for state changes
// across media sources, sinks, and issues. The MediaRouter lives in the browser
// process.
interface MediaRouter {
  // Registers a MediaRouteProvider with the MediaRouter.
  RegisterMediaRouteProvider(MediaRouteProviderId provider_id,
      pending_remote<MediaRouteProvider> media_router_provider);

  // Called when a MediaRouteProvider receives a new list of |sinks|
  // compatible with |media_source|. The result is only valid for |origins|. If
  // |origins| is empty, the result is valid for any origin.
  OnSinksReceived(MediaRouteProviderId provider_id,
                  string media_source,
                  array<MediaSink> sinks,
                  array<url.mojom.Origin> origins);

  // Called when issues are reported for media routes.
  OnIssue(Issue issue);

  // Clears the top Issue if it belongs to the given sink_id.
  ClearTopIssueForSink(string sink_id);

  // Called when list of routes for a MediaRouteProvider has been updated.
  OnRoutesUpdated(MediaRouteProviderId provider_id,
                  array<MediaRoute> routes);

  // Called when the state of presentation connected to route |route_id| has
  // changed to |state|.
  OnPresentationConnectionStateChanged(
      string route_id, blink.mojom.PresentationConnectionState state);

  // Called when the presentation connected to route |route_id| has closed.
  OnPresentationConnectionClosed(
      string route_id, blink.mojom.PresentationConnectionCloseReason reason,
      string message);

  // Called when the a batch of messages arrives from the media sink for the
  // route given by |route_id|.
  // |StartListeningForRouteMessages| must be called first in order to receive
  // messages.
  // |route_id|: ID of route of the messages.
  // |messages|: A non-empty list of messages received.
  OnRouteMessagesReceived(string route_id,
                          array<RouteMessage> messages);

  // Returns current status of media sink service in JSON format.
  GetMediaSinkServiceStatus() => (string status);

  // The logger can be used to add entries to logs returned by GetLogs().
  GetLogger(pending_receiver<Logger> receiver);

  // The debugger can be used to fetch debugging states and add debugging info
  // such as mirroring stats for the current session.
  GetDebugger(pending_receiver<Debugger> receiver);

  // Returns a JSON array of logs collected by Media Router components.
  // Serializing the logs requires allocating extra memory, so it should only be
  // called under limited circumstances, such as when the user is submitting a
  // feedback report.
  GetLogsAsString() => (string logs);
};