tree: c13863c027d2d402d80f69ce1bd727ef2831a456 [path history] [tgz]
  1. browser/
  2. common/
  3. renderer/
  4. BUILD.gn
  5. DEPS
  6. DIR_METADATA
  7. OWNERS
  8. README.md
components/cast_receiver/README.md

Introduction

This component provides the shared Cast receiver implementation that is used by various embedders throughout Chromium. It is planned to be used for WebEngine, Chromecast hardware, and others.

Usage

The specifics of integrating this component with an existing Chromium embedder are described below. The canonical implementation of this component can be found at //chromecast/cast_core. For specific usages of the below described APIs, see its RuntimeServiceImpl and RuntimeApplicationServiceImpl classes, which use this component to implement a gRPC-defined service.

Integration With Existing Code

Integration with an existing Chromium embedder is relateively easy, with only a small number of integration points required:

Browser-Side Integration

Browser-side integration has two parts:

Permissions Management

The Permissions Manager is used to define the permissions that can be used by a given application. It is integrated into an existing Chromium embedder by calling into the PermissionsManager::GetPermissionsStatus() function from the embedder's implementation of content::PermissionControllerDelegate::GetPermissionStatus().

Runtime Hooks

The remaining integration is done by creating an instance of the ContentBrowserClientMixins class in the ContentBrowserClient implementation for this embedder. For instance, this is currently done in the Cast Core implementation. From there, the OnWebContentsCreated() and CreateURLLoaderThrottles() functions must be called from the ContentBrowserClient functions of the same name.

The embedder may additionally call AddApplicationStateObserver() or AddStreamingResolutionObserver() to subscribe to state change events for the runtime.

Renderer-Side Integration

Renderer side integration is done very similarly to the runtime hooks for the browser-side integration as described above. Specifically, from the embedder‘s ContentRendererClient implementation, an instance of ContentRendererClientMixins must be created as is currently done in the Cast Core implementation. Then, the functions of this calls must all be called from the appropriate ContentRendererClient functions as outlined in the class’s documentation.

Running Applications

Lifetime of an Application

Once the above integration is done, applications can be created by first creating an instance of RuntimeApplicationDispatcher using the ContentBrowserClientMixins::CreateApplicationDispatcher() function, then calling CreateApplication() and providing basic information about the application (such as application id, requested permissions, etc). Note that this requires a template parameter of a type implementing the EmbedderApplication interface.

After creation, an application will always exist in one of the following lifetime states, transitioning between them using functions defined in the RuntimeApplication interface:

  1. Created: In this state, the RuntimeApplication object has been created, but nothing else has been done.
  2. Loaded: In this state, information pertaining to the application has been provided (e.g. any platform-specific application info), and is considered to have started “running”, but no content should be displayed on the screen.
  3. Launched: The application has been displayed on the screen, and the user may interact with it.
  4. Stopped: The application is no longer running and should not be displayed.

It is expected that the application will be loaded immediately after being created, and then launched shortly after.

When the application is to be destroyed, this can be done through calling RuntimeApplicationDispatcher::DestroyApplication().

Embedder-Specific Application Details

Implementing EmbedderApplication is where the majority of the embedder's work is located. Doing so requires the following:

  • Callbacks to inform the embedder's infrastructure of application state changes (NotifyApplicationStarted(), NotifyApplicationStopped(), and NotifyMediaPlaybackChanged()).
  • Accessors to the application-specific data for displaying its contents (GetWebContents() and GetAllBindings()).
  • Embedder-specific controls for the underlying application (GetMessagePortService() and GetContentWindowControls()).
  • Other optional overloads that may be needed depending on the embedder's infrastructure.

Implementing this type therefore requires at minimum implementations of the following two embedder-specific classes:

  • ContentWindowControls: Used for controlling the UX Window associated with this application.
  • MessagePortService: A wrapper around message port functionality, used to handle communication with services outside of this component.

Connecting Runtime Applications and Embedder Applications

When creating an instance of EmbedderApplication through RuntimeApplicationDispatcher, an instance of RuntimeApplication is provided, which can be used for control of this application. Specifically:

  • Application Lifetime can be controlled through the Load(), Launch(), and Stop() functions.
  • Application State can be controlled with the SetMediaBlocking(), SetVisibility(), SetTouchInputEnabled(), and SetUrlRewriteRules() functions.

A pointer to this instance of EmbedderApplication will also be provided to the RuntimeApplicaiton, which will use the callbacks and controls as described previously throughout the application's lifetime.

Architecture

Code Structure

The top-level object with which the embedder will interact is the ContentBrowserClientMixins class which will be used to create a RuntimeApplicationDispatcher instance. That instance will create RuntimeApplications instances, either StreamingRuntimeApplication or WebRuntimeApplication instances, and then wrap them in an EmbedderApplication instance using a factory provided by the embedder. The EmbedderApplication instance will control the RuntimeApplication with the following commands:

  • Load()
  • Launch()
  • Stop()

Additionally, the RuntimeApplication exposes a number of accessors and ways to set properties of the application, such as enabling or disabling touch input. The EmbedderApplication exposes functions to supply embedder-specific types or commands, such as:

  • GetAllBindings()
  • GetMessagePortService()
  • GetContentWindowControls()
  • GetStreamingConfigManager()

Additionally, it exposes functions by which it may be informed of state changes in the RuntimeApplication instance it owns.

cast_receiver code structure

Common Scenarios

In each of the following diagrams, blue boxes are used to represent embedder-specific infrastructure, while white boxes are part of the component.

This component supports two types of applications: Web Applications and Streaming Applications. Much of the infrastructure for these two application types is shared, but the differences are substantial enough that each will be discussed independently.

Web Applications

Web Applications are used for hosting the majority of applications for a Cast receiver. At a high level, the flow for using a Web Application is:

  1. Create a new ContentBrowserClientMixins instance in the embedder-specific ContentBrowserClient implementation, and then use that instance to create a RuntimeApplicationDispatcher.
  2. Use the RuntimeApplicationDispatcher to create a WebRuntimeApplication instance, which will then be used to create an instance of the embedder-specific EmbedderApplication type.
  3. Call Load() on the RuntimeApplication instance, and wait for its callback.
  4. Call SetUrlRewriteRules() on the RuntimeApplication. This may be called at any time, but is expected to be called at least once before the Launch() command if such rules are required for the application’s functionality.
  5. Call Launch() on the RuntimeApplication instance, and wait for its callback. Various EmbedderApplication functions will be called to create the necessary resources.
  6. Once the application is no longer needed, close it with StopApplication() and then destroy the application with the RuntimeApplicationDispatcher after the StopApplication()’s callback returns.

Web Application code flow

Streaming

Streaming Applications are used to support the Cast streaming and remoting scenarios by making use of the cast_streaming component

  1. Create a new ContentBrowserClientMixins instance in the embedder-specific ContentBrowserClient implementation, and then use that instance to create a RuntimeApplicationDispatcher.
  2. Use the RuntimeApplicationDispatcher to create a StreamingRuntimeApplication instance, which will then be used to create an instance of the embedder-specific EmbedderApplication type.
  3. Call Load() on the RuntimeApplication instance, and wait for its callback.
  4. Call Launch() on the RuntimeApplication instance, and wait for its callback. Various EmbedderApplication functions will be called to create the necessary resources, which will be used to start the cast_streaming component. Each of the following is expected to occur for the streaming session to successfully begin, but the order may vary:
    1. Calling of StartPlaybackAsync(), which will be called as part of the Launch() command before its callback is called.
    2. The WebContents instance associated with this application, as returned by EmbedderApplication::GetWebContents(), loads the page used for displaying the streaming session.
    3. The configuration to use for streaming is returned by the embedder-specific ConfigurationManager as provided by EmbedderApplication::GetStreamingConfigManager().
  5. Once streaming has started and a connection has been formed with the Cast sender device, a OnStreamingResolutionChanged() event will be fired.
  6. Streaming may be stopped by the embedder as with Web applications. Alternatively, if the session is ended by the remote device, a NotifyApplicationStopped() event will be fired to the EmbedderApplication, at which point the application should be destroyed by the RuntimeApplicationDispatcher.

Streaming Application code flow

Known Issues and Limitations

  • TODO(crbug.com/1405480): DRM is not supported.