blob: b879c44923468dd1d7d1a64362be57942f7b9aca [file] [log] [blame] [view]
mark a. foltz6faba39b2019-07-10 20:40:151# Chrome Media Router
2
3## Introduction
4
5*TODO: Update with integration with Remote Playback API*
6
7The media router is a component in Chrome responsible for matching clients that
8wish to render media or URLs (_media sources_) on devices and endpoints capable
9of rendering that content (_media sinks_). When a media source is linked with a
10_media sink_, a _media route_ is created that allows two-way messaging between
11the source and the sink. The media route allows the application to negotiate a
12peer-to-peer media streaming session with the media sink via messaging (e.g.,
13via [WebRTC](http://www.webrtc.org/) or [Cast Streaming](https://cs.chromium.org/chromium/src/components/mirroring/)),
14aka "mirroring." The media route can also be used to request the remote display
15to render a URL without an associated peer-to-peer media streaming session, aka
16"flinging". The media route can be terminated at user or browser request,
17which denies access to the media sink from the application.
18
19The Web [Presentation API](http://w3c.github.io/presentation-api/) allows a Web
20application to request display of Web content on a secondary (wired, or
21wireless) screen. The content may be rendered locally and streamed to the
22display or rendered remotely. The Web application controls the content by
23two-way messaging.
24
25Note that the non-Blink parts of the media router will be implemented only in
26desktop Chrome and ChromeOS. Presentation API functionality will be implemented
27in Chrome for Android using analogous platform components such as the [Android
28Media Route Provider
29framework](https://developer.android.com/guide/topics/media/mediarouteprovider.html).
30
31*TODO: Add material on 1-UA mode, or add a separate document*
32
33Offscreen rendering, capture, and streaming of WebContents (required for full
34Presentation API support) will be covered in a separate design document.
35
36## Objectives
37
38The objectives of this project:
39
40* Allow use of media sinks from a multitude of clients, including: Web
41 applications via the Presentation API;
42 Chrome apps; the browser itself; and the Chrome OS system shell.
43
44* Support mirroring locally rendered content to external screens, including
45 on-screen and off-screen tabs, Chrome apps windows, and the system desktop.
46
47* Support "flinging" HTML5 documents to remote devices capable of rendering
48 them.
49
50* Support the [Cast Chrome Sender
51 SDK](https://developers.google.com/cast/docs/reference/chrome/) on desktop and
52 Android without any user installed extensions.
53
54* Allow new types of media sinks to be added to Chrome by implementing
55 additional Media Route Providers.
56
57The following are non-goals but may be objectives for future work:
58
59* Multicast of local content to multiple sinks at once.
60
61* Support for third party media route providers in Javascript or
62 run-time installation of media route providers.
63
64* Support for sinks that are not primarily intended to render media.
65
66## Overview
67
68The media router consists of four distinct components:
69
701. The Chrome Media Router is a browser service exposed in-process via C++ API
71and is exposed to other processes via a set of two Mojo interfaces: the
72Presentation interface and the Media Router API interface. Its job is to field
73requests from clients for media sink availability, media route
74construction/destruction, and media route control via messaging. It also
75controls the Media Router Dialog and delegates many functions to the Media
76Router component extension.
77
782. *TODO: update* The Media Router extension is an external component extension
79responsible for direct interaction with media sinks. The component extension
80will initially support use of [Cast](http://www.google.com/cast/) and
81[DIAL](http://www.dial-multiscreen.org/) devices with more types of sinks to be
82added over time. The component extension interacts with the Chrome Media Router
83via the Media Router API Mojo service, and uses some chrome.\* platform APIs,
84such as chrome.dial, chrome.cast.channel, and chrome.mdns to implement network
85level interaction with Cast and DIAL devices.
86
873. Users interact with the Chrome Media Router through the Media Router
88Dialog. This dialog allows users to choose the destination media sink
89for new media routes and view and stop active media routes. It may be pulled up
90by the user clicking the Cast icon in the browser toolbar, or at the request of
91a Web application via the Presentation API. It is implemented in Views.
92
934. The PresentationService mojo interface acts as a bridge between the Chrome
94Media Router and the Blink implementations of the Presentation API ([launch
95bug](https://code.google.com/p/chromium/issues/detail?id=412331)).
96
97## Architecture
98
99The following diagram illustrates the architecture of the components described above.
100
101*TODO: update diagram*
102
103[![](https://www.chromium.org/_/rsrc/1423182643815/developers/design-documents/media-router/Chrome%20Media%20Router%20Architecture%20%281%29.png)](https://www.chromium.org/developers/design-documents/media-router/Chrome%20Media%20Router%20Architecture%20%281%29.png?attredirects=0)
104
105### Chrome Media Router
106
107The Chrome Media Router is a browser-resident service that serves as a
108media-protocol-agnostic platform for parties interested in media routing. It
109provides its clients with a set of APIs for media routing related queries and
110operations, including:
111
112* Register for notifications when a sink is available that can render a media
113 source. (Media sources are represented as URIs and can represent local media
114 or remotely hosted content.)
115
116* Request routing of media for that source, which will show the user the media
117 router dialog to select a compatible sink. If the user selects a sink, the
118 media route is returned to the application to allow it to control media
119 playback.
120
121* Accept media control actions from the Media Router Dialog for an active media
122 route and forwarding them to the associated route provider.
123
124* Send and receive arbitrary (string) messages between the application the media
125 sink.
126
127* Terminate media routes, and notify the client and media route provider when
128 that happens.
129
130The Chrome Media Router, itself, does not directly interact with media
131sinks. *TODO: update* Instead it delegates these requests and responses to a
132media route provider in the component extension. The Chrome Media Router will
133contain bookkeeping of established routes, pending route requests, and other
134related resources, so it does not have to request this information from the
135route provider each time.
136
137The following pseudocode describes how a client of the Chrome Media Router
138(through its C++ API) would use it to initiate and control a media sharing
139session.
140
141### Media Router API Example
142
143*TODO: update or remove*
144
145```
146MediaRouter* media_router = MediaRouterImpl::GetInstance();
147
148// Find out what screens are capable of rendering, e.g. www.youtube.com
149MediaSource youtube_src = MediaSource::ForPresentationUrl("http://www.youtube.com");
150
151// MyMediaSinksObserver should override MediaSinksObserver::OnSinksReceived to
152// handle updates to the list of screens compatible with youtube_src
153MediaSinksObserver* my_observer = new MyMediaSinksObserver(youtube_src);
154media_router->RegisterObserver(my_observer);
155
156// Ask the user to pick a screen from the list passed to my_observer and
157// capture the sink_id (code not shown)
158
159// Request routing of media for that source. |callback| is passed a
160// MediaRouteResponse& that contains a MediaRoute result if successful.
161media_router->StartRouteRequest(youtube_src, sink_id, callback);
162
163// The MediaRoute can be used to post messages to the sink.
164media_router->PostMessage(media_route.media_route_id, "some data", "optional_extra_data_json");
165
166// The MediaRoute can be closed which signals the sinkto terminate any remote
167// app or media streaming session.
168media_router->CloseRoute(media_route.media_route_id);`
169```
170
171The Media Router interacts with the component extension via a Mojo service, the
172Media Router API, that exposes functionality whose implementation is delegated
173to the extension.
174
175### Media Router API Mojo Interface
176
177*TODO: Update or replace with link*
178
179```
180// Interface for sending messages from the MediaRouter (MR) to the Media
181// Router Provider Manager (MRPM).
182
183interface MediaRouterApiClient {
184 // Signals the media route manager to route the media located
185 // at |source_urn| to |sink_id|.
186 RequestRoute(int64 request_id, string source, string sink_id);
187
188 // Signals the media route manager to close the route specified by |route_id|.
189 CloseRoute(string route_id);
190
191 // Signals the media route manager to start querying for sinks
192 // capable of displaying |source|.
193 AddMediaSinksQuery(string source);
194
195 // Signals the media route manager to stop querying for sinks
196 // capable of displaying |source|.
197 RemoveMediaSinksQuery(string source);
198
199 // Sends |message| with optional |extra_info_json| via the media route
200 // |media_route_id|.
201 // |extra_info_json| is an empty string if no extra info is provided.
202 PostMessage(string media_route_id, string message, string extra_info_json);
203};
204
205// Interface for sending messages from the MRPM to the MR.
206[Client=MediaRouterApiClient]
207interface MediaRouterApi {
208 // Called when the provider manager is ready.
209 OnProviderManagerReady(string extension_id);
210
211 // Called when the Media Route Manager receives a new list of sinks.
212 OnSinksReceived(string source,
213 array<MediaSink> sinks,
214 array<MediaRoute> routes);
215
216 // Called after a MediaRoute is established.
217 OnRouteResponseReceived(int64 request_id, MediaRoute route);
218
219 // Called when route establishment fails.
220 OnRouteResponseError(int64 request_id, string error_text);
221};
222```
223
224### Media Router Component Extension
225
226*TODO: update to discuss in-browser MRPs and Mirroring Service*
227
228The component extension manages discovery of and network interaction with
229individual media sinks. For the purposes of this discussion a sink is a
230LAN-connected device that speaks the Cast or DIAL protocol, but in theory it
231could be any other type of endpoint that supports media rendering and two-way
232messaging. The extension consists of three types of components:
233
234* Media Route Providers: Each provider is a Javascript bundle that knows how to
235 find and communicate with a specific type of media sink. It communicates
236 with the media sink using HTTP/XHR or via device-specific network protocols
237 (e.g., Cast Channel and Cast Streaming).
238
239* Media Route Provider Manager: This is responsible for dispatching requests
240 from the Chrome Media Router to individual providers. It also registers
241 providers on startup.
242
243* Mirroring Service: If a media source is requested that represents the tab or
244 desktop contents, this service acts on the behalf of the application to
245 initiate the mirroring session. This is handled internally to the component
246 extension and is not exposed to the rest of the browser, it appears to be
247 just another media route.
248
249The component extension is written in JavaScript and includes code for multiple
250media route providers. Initially Media Route Providers will be implemented for
251Cast and DIAL devices with others to follow. Over time media route providers
252that do not rely on proprietary protocols will be implemented in the Chromium
253repository.
254
255As an external component, the extension is installed on the initial run of the
256browser. It is built around an event page so it registers itself with the Media
257Router, registers itself with discovery APIs to be notified of display
258availability, and then suspends. The component extension will only be active
259when there are applications with pending sink availability requests or media
260routes, or when there is active network traffic between the extension and a
261media sink.
262
263There are several modules to the extension that are loaded on-demand. The main
264event page bundles are a few hundred kb. The extension is updated on the Chrome
265release cycle with a branch made a week or two after the Chrome branch point.
266
267## Tab/Desktop Mirroring
268
269*TODO: update with discussion of C++ MirroringService*
270
271Tab and desktop mirroring will request routing of a media source with URN like
272urn:google:tab:3 representing tab contents. When the component extension
273receives a request to route this source, the media route provider manager will
274query route providers to enumerate sinks that can render streamed tab
275contents. Once a sink is selected by the user, the mirroring service will create
276the appropriate MediaStream using the chrome.tabCapture extension API. The
277MediaStream will then be passed to a Cast Streaming or WebRTC session depending
278on the preferred protocol of the selected sink. When the media route is
279terminated, the associated streaming session and media capture are also
280terminated. A similar approach will be used for desktop mirroring but using
281chrome.desktopCapture instead.
282
283# Presentation API
284
285*TODO: Discuss 1-UA mode*
286*TODO: Update for Onion Soup*
287
288Media routing of Web content will primarily be done through the Presentation
289API. Some media sinks (e.g. Cast) can render a subset of Web content natively,
290or render an equivalent app experience (e.g., via DIAL). For generic Web
291documents, we plan on rendering it in an offscreen WebContents and then using
292the Tab Mirroring approach outlined above. The design of the offscreen rendering
293capability will be added later to this document.
294
295The Presentation API implementation in Blink will live in content/ and will
296operate on the frame level. It will delegate the calls to the embedder's Media
297Router implementation (Android Media Router / Chrome Media Router for Android /
298Chrome, respectively) via a common PresentationServiceDelegate interface. A
299draft Mojo interface follows (not yet complete):
300
301## PresentationService mojo interface
302
303*TODO: Update or replace with link*
304
305```
306interface PresentationService {
307 // Returns the last screen availability state if it’s changed since the last
308 // time the method was called. The client has to call this method again when
309 // handling the result (provided via Mojo callback) to get the next update
310 // about the availability status.
311 // May start discovery of the presentation screens. The implementation might
312 // stop discovery once there are no active calls to GetScreenAvailability.
313 // |presentation_url| can be specified to help the implementation to filter
314 // out incompatible screens.
315 GetScreenAvailability(string? presentation_url) => (bool available);
316
317 // Called when the frame no longer listens to the
318 // |availablechange| event.
319 OnScreenAvailabilityListenerRemoved();
320};
321```
322
323*TODO: Update table with current flow, or remove this section*
324
325Here is how the presentation API will roughly map to Chrome Media Router API:
326
327**Presentation API**
328
329**Chrome Media Router**
330
331Adding onavailablechange listener
332
333RegisterObserver(), with result propagated back to the RenderFrame / Presentation API.
334
335startSession
336
337Opens Media Router Dialog (via MediaRouterDialogController) -> User action -> StartRouteRequest()
338
339joinSession
340
341StartRouteRequest()
342
343postMessage
344
345PostMessage()
346
347close
348
349CloseRoute()
350
351Adding onmessage listener
352
353RegisterMessageObserver() (tentative)
354
355Adding onstatechange listener
356
357RegisterRouteStateChangeObserver() (tentative)
358
359## Media Router Dialog
360
361End user control of media routing is done through the Media Router Dialog. The
362media router dialog is implemented in Views.
363
364The Media Router Dialog is activated by clicking on the Cast icon, which is
365always available to the user. The Cast icon appears in the toolbar action menu
366when there is an active media route, or when the user chooses to pin the icon
367there permanently.
368
369-----------------------------------------------
370
371*TODO: Update screenshot*
372
373[![](https://www.chromium.org/_/rsrc/1418943120195/developers/design-documents/media-router/media_router_overflow.jpg)](https://www.chromium.org/developers/design-documents/media-router/media_router_overflow.jpg?attredirects=0)
374
375Clicking on the Cast icon brings up a menu of available media sinks that are
376compatible with the current content. For Web documents not using the
377Presentation API, these will include sinks that can render tab or desktop
378capture. For Web documents, it will include media sinks compatible with the URL
379requested to be presented through the Presentation API.
380
381-----------------------------------------------
382
383*TODO: Update screenshot*
384
385[![](https://www.chromium.org/_/rsrc/1418944081776/developers/design-documents/media-router/media_router_screen_selector.jpg)](https://www.chromium.org/developers/design-documents/media-router/media_router_screen_selector.jpg?attredirects=0)
386
387-----------------------------------------------
388
389## Offscreen Rendering
390
Jordan Bayles98d6d51f2022-03-10 20:53:16391*TODO: Add notes about off-screen rendering.*
mark a. foltz6faba39b2019-07-10 20:40:15392
393# Security
394
395*TODO: Update to discuss sandboxing of in-browser MRPs.*
396
397The entire project should be security reviewed from a holistic and architectural
398perspective. Specific security-related aspects:
399
400* The Chrome Media Router will be designed to have a minimal processing of the
401 URIs and messages passed through it (perhaps only checking for syntactic
402 validity).
403* The Media Router Dialog will allow the MRPs to inject custom
404 content into it, so for example, the inline controls for a game can differ
405 from those for a movie. This content will be rendered out-of-process in an
406 <extensionview> to prevent any escalation of privileges from compromised
407 content.
408* The individual platform APIs used by the component extension MRPs
409 (chrome.dial, chrome.mdns, chrome.cast.channel, chrome.cast.streaming) have
410 been security reviewed previously.
411
412# Contact
413
414* [[email protected]](mailto:[email protected])
415
416# Code location
417
418| Path | Description |
419| ---------------------------------------|--------------------------------------|
420| `chrome/browser/media/router` | Main implementation, in-browser MRPs |
421| `chrome/common/media_router` | Mojo definitions, shared impl |
422| `chrome/browser/ui/media_router/` | Media Router icon, dialog |
423| `chrome/browser/ui/views/media_router/`| |
424| `content/browser/presentation/` | Browser impl of Presentation API|
425| `third_party/blink/renderer/modules/presentation/`| Blink impl of Presentaton API|
426
427# History
428
429| Date | Author | Description |
430|------------|---------------------|--------------------------------------------------|
431| 6-Feb-2015 | [email protected] | Initial publication |
432| 8-Jul-2019 | [email protected] | Converted to markdown, obsolete material removed.|