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.
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 an existing Chromium embedder is relateively easy, with only a small number of integration points required:
Browser-side integration has two parts:
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()
.
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 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.
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:
- Created: In this state, the
RuntimeApplication
object has been created, but nothing else has been done. - 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.
- Launched: The application has been displayed on the screen, and the user may interact with it.
- 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()
.
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()
, andNotifyMediaPlaybackChanged()
). - Accessors to the application-specific data for displaying its contents
(
GetWebContents()
andGetAllBindings()
). - Embedder-specific controls for the underlying application
(
GetMessagePortService()
andGetContentWindowControls()
). - 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.
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()
, andStop()
functions. - Application State can be controlled with the
SetMediaBlocking()
,SetVisibility()
,SetTouchInputEnabled()
, andSetUrlRewriteRules()
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.
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.
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 are used for hosting the majority of applications for a Cast receiver. At a high level, the flow for using a Web Application is:
- Create
a new
ContentBrowserClientMixins
instance in the embedder-specificContentBrowserClient
implementation, and then use that instance to create aRuntimeApplicationDispatcher
. - Use the
RuntimeApplicationDispatcher
to create aWebRuntimeApplication
instance, which will then be used to create an instance of the embedder-specificEmbedderApplication
type. - Call
Load()
on theRuntimeApplication
instance, and wait for its callback. - Call
SetUrlRewriteRules()
on theRuntimeApplication
. This may be called at any time, but is expected to be called at least once before theLaunch()
command if such rules are required for the application’s functionality. - Call
Launch()
on theRuntimeApplication
instance, and wait for its callback. VariousEmbedderApplication
functions will be called to create the necessary resources. - Once the application is no longer needed, close it with
StopApplication()
and then destroy the application with theRuntimeApplicationDispatcher
after theStopApplication()
’s callback returns.
Streaming Applications are used to support the Cast streaming and remoting
scenarios by making use of the cast_streaming
component
- Create
a new
ContentBrowserClientMixins
instance in the embedder-specificContentBrowserClient
implementation, and then use that instance to create aRuntimeApplicationDispatcher
. - Use the
RuntimeApplicationDispatcher
to create aStreamingRuntimeApplication
instance, which will then be used to create an instance of the embedder-specificEmbedderApplication
type. - Call
Load()
on theRuntimeApplication
instance, and wait for its callback. - Call
Launch()
on theRuntimeApplication
instance, and wait for its callback. VariousEmbedderApplication
functions will be called to create the necessary resources, which will be used to start thecast_streaming
component. Each of the following is expected to occur for the streaming session to successfully begin, but the order may vary:- Calling of
StartPlaybackAsync()
, which will be called as part of theLaunch()
command before its callback is called. - The
WebContents
instance associated with this application, as returned byEmbedderApplication::GetWebContents()
, loads the page used for displaying the streaming session. - The configuration to use for streaming is returned by the
embedder-specific
ConfigurationManager
as provided byEmbedderApplication::GetStreamingConfigManager()
.
- Calling of
- Once streaming has started and a connection has been formed with the Cast
sender device, a
OnStreamingResolutionChanged()
event will be fired. - 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 theEmbedderApplication
, at which point the application should be destroyed by theRuntimeApplicationDispatcher
.
- TODO(crbug.com/1405480): DRM is not supported.