| // Copyright 2015 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| 'use strict'; |
| |
| if ((typeof mojo === 'undefined') || !mojo.bindingsLibraryInitialized) { |
| loadScript('mojo_bindings'); |
| } |
| mojo.config.autoLoadMojomDeps = false; |
| |
| loadScript('chrome/common/media_router/mojo/media_controller.mojom'); |
| loadScript('chrome/common/media_router/mojo/media_router.mojom'); |
| loadScript('chrome/common/media_router/mojo/media_status.mojom'); |
| loadScript('extensions/common/mojo/keep_alive.mojom'); |
| loadScript('media/mojo/interfaces/mirror_service_remoting.mojom'); |
| loadScript('media/mojo/interfaces/remoting_common.mojom'); |
| loadScript('mojo/common/time.mojom'); |
| loadScript('net/interfaces/ip_address.mojom'); |
| loadScript('net/interfaces/ip_endpoint.mojom'); |
| loadScript('url/mojo/origin.mojom'); |
| loadScript('url/mojo/url.mojom'); |
| |
| // The following adapter classes preserve backward compatibility for the media |
| // router component extension. |
| // TODO(crbug.com/787128): Remove these adapters. |
| |
| function assignFields(object, fields) { |
| for(var field in fields) { |
| if (object.hasOwnProperty(field)) |
| object[field] = fields[field]; |
| } |
| } |
| |
| /** |
| * Adapter for mediaRouter.mojom.DialMediaSink. |
| * @constructor |
| */ |
| function DialMediaSinkAdapter(fields) { |
| this.ip_address = null; |
| this.model_name = null; |
| this.app_url = null; |
| |
| assignFields(this, fields); |
| } |
| |
| DialMediaSinkAdapter.fromNewVersion = function(other) { |
| return new DialMediaSinkAdapter({ |
| 'ip_address': IPAddressAdapter.fromNewVersion(other.ipAddress), |
| 'model_name': other.modelName, |
| 'app_url': other.appUrl, |
| }); |
| }; |
| |
| DialMediaSinkAdapter.prototype.toNewVersion = function() { |
| return new mediaRouter.mojom.DialMediaSink({ |
| 'ipAddress' : this.ip_address.toNewVersion(), |
| 'modelName' : this.model_name, |
| 'appUrl' : this.app_url, |
| }); |
| }; |
| |
| /** |
| * Adapter for mediaRouter.mojom.CastMediaSink. |
| * @constructor |
| */ |
| function CastMediaSinkAdapter(fields) { |
| this.ip_endpoint = null; |
| this.model_name = null; |
| this.capabilities = 0; |
| this.cast_channel_id = 0; |
| |
| assignFields(this, fields); |
| } |
| |
| CastMediaSinkAdapter.fromNewVersion = function(other) { |
| return new CastMediaSinkAdapter({ |
| 'ip_endpoint': IPEndpointAdapter.fromNewVersion(other.ipEndpoint), |
| 'model_name': other.modelName, |
| 'capabilities': other.capabilities, |
| 'cast_channel_id': other.castChannelId, |
| }); |
| }; |
| |
| CastMediaSinkAdapter.prototype.toNewVersion = function() { |
| return new mediaRouter.mojom.CastMediaSink({ |
| 'ipEndpoint': this.ip_endpoint.toNewVersion(), |
| 'modelName': this.model_name, |
| 'capabilities': this.capabilities, |
| 'castChannelId': this.cast_channel_id, |
| }); |
| }; |
| |
| /** |
| * Adapter for mediaRouter.mojom.HangoutsMediaStatusExtraData. |
| * @constructor |
| */ |
| function HangoutsMediaStatusExtraDataAdapter(fields) { |
| this.local_present = false; |
| |
| assignFields(this, fields); |
| } |
| |
| HangoutsMediaStatusExtraDataAdapter.prototype.toNewVersion = function() { |
| return new mediaRouter.mojom.HangoutsMediaStatusExtraData({ |
| 'localPresent': this.local_present, |
| }); |
| }; |
| |
| /** |
| * Adapter for net.interfaces.IPAddress. |
| * @constructor |
| */ |
| function IPAddressAdapter(fields) { |
| this.address_bytes = null; |
| |
| assignFields(this, fields); |
| } |
| |
| IPAddressAdapter.fromNewVersion = function(other) { |
| return new IPAddressAdapter({ |
| 'address_bytes': other.addressBytes, |
| }); |
| }; |
| |
| IPAddressAdapter.prototype.toNewVersion = function() { |
| return new net.interfaces.IPAddress({ |
| 'addressBytes': this.address_bytes, |
| }); |
| }; |
| |
| /** |
| * Adapter for net.interfaces.IPEndpoint. |
| * @constructor |
| */ |
| function IPEndpointAdapter(fields) { |
| this.address = null; |
| this.port = 0; |
| |
| assignFields(this, fields); |
| } |
| |
| IPEndpointAdapter.fromNewVersion = function(other) { |
| return new IPEndpointAdapter({ |
| 'address': IPAddressAdapter.fromNewVersion(other.address), |
| 'port': other.port, |
| }); |
| }; |
| |
| IPEndpointAdapter.prototype.toNewVersion = function() { |
| return new net.interfaces.IPEndpoint({ |
| 'address': this.address.toNewVersion(), |
| 'port': this.port, |
| }); |
| }; |
| |
| /** |
| * Adapter for mediaRouter.mojom.MediaStatus. |
| * @constructor |
| */ |
| function MediaStatusAdapter(fields) { |
| this.title = null; |
| this.description = null; |
| this.can_play_pause = false; |
| this.can_mute = false; |
| this.can_set_volume = false; |
| this.can_seek = false; |
| this.is_muted = false; |
| this.play_state = 0; |
| this.volume = 0; |
| this.duration = null; |
| this.current_time = null; |
| this.hangouts_extra_data = null; |
| |
| assignFields(this, fields); |
| } |
| |
| MediaStatusAdapter.PlayState = mediaRouter.mojom.MediaStatus.PlayState; |
| |
| MediaStatusAdapter.prototype.toNewVersion = function() { |
| return new mediaRouter.mojom.MediaStatus({ |
| 'title': this.title, |
| 'description': this.description, |
| 'canPlayPause': this.can_play_pause, |
| 'canMute': this.can_mute, |
| 'canSetVolume': this.can_set_volume, |
| 'canSeek': this.can_seek, |
| 'isMuted': this.is_muted, |
| 'playState': this.play_state, |
| 'volume': this.volume, |
| 'duration': this.duration, |
| 'currentTime': this.current_time, |
| 'hangoutsExtraData': |
| this.hangouts_extra_data && this.hangouts_extra_data.toNewVersion(), |
| }); |
| }; |
| |
| /** |
| * Adapter for media.mojom.RemotingSinkMetadata. |
| * @constructor |
| */ |
| function RemotingSinkMetadataAdapter(fields) { |
| this.features = null; |
| this.audio_capabilities = null; |
| this.video_capabilities = null; |
| this.friendly_name = null; |
| |
| assignFields(this, fields); |
| } |
| |
| RemotingSinkMetadataAdapter.fromNewVersion = function(other) { |
| return new RemotingSinkMetadataAdapter({ |
| 'features': other.features, |
| 'audio_capabilities': other.audioCapabilities, |
| 'video_capabilities': other.videoCapabilities, |
| 'friendly_name': other.friendlyName, |
| }); |
| }; |
| |
| RemotingSinkMetadataAdapter.prototype.toNewVersion = function() { |
| return new media.mojom.RemotingSinkMetadata({ |
| 'features': this.features, |
| 'audioCapabilities': this.audio_capabilities, |
| 'videoCapabilities': this.video_capabilities, |
| 'friendlyName': this.friendly_name, |
| }); |
| }; |
| |
| /** |
| * Adapter for mediaRouter.mojom.MediaSink. |
| * @constructor |
| */ |
| function MediaSinkAdapter(fields) { |
| this.sink_id = null; |
| this.name = null; |
| this.description = null; |
| this.domain = null; |
| this.icon_type = 0; |
| this.extra_data = null; |
| |
| assignFields(this, fields); |
| } |
| |
| MediaSinkAdapter.fromNewVersion = function(other) { |
| return new MediaSinkAdapter({ |
| 'sink_id': other.sinkId, |
| 'name': other.name, |
| 'description': other.description, |
| 'domain': other.domain, |
| 'icon_type': other.iconType, |
| 'extra_data': other.extraData && |
| MediaSinkExtraDataAdapter.fromNewVersion(other.extraData), |
| }); |
| }; |
| |
| MediaSinkAdapter.prototype.toNewVersion = function() { |
| return new mediaRouter.mojom.MediaSink({ |
| 'sinkId': this.sink_id, |
| 'name': this.name, |
| 'description': this.description, |
| 'domain': this.domain, |
| 'iconType': this.icon_type, |
| 'extraData': this.extra_data && this.extra_data.toNewVersion(), |
| }); |
| }; |
| |
| /** |
| * Adapter for mediaRouter.mojom.MediaSinkExtraData. |
| * @constructor |
| */ |
| function MediaSinkExtraDataAdapter(value) { |
| this.$data = null; |
| this.$tag = undefined; |
| |
| if (value == undefined) { |
| return; |
| } |
| |
| var keys = Object.keys(value); |
| if (keys.length == 0) { |
| return; |
| } |
| |
| if (keys.length > 1) { |
| throw new TypeError('You may set only one member on a union.'); |
| } |
| |
| var fields = [ |
| 'dial_media_sink', |
| 'cast_media_sink', |
| ]; |
| |
| if (fields.indexOf(keys[0]) < 0) { |
| throw new ReferenceError(keys[0] + |
| ' is not a MediaSinkExtraDataAdapter member.'); |
| } |
| |
| this[keys[0]] = value[keys[0]]; |
| } |
| |
| MediaSinkExtraDataAdapter.Tags = { |
| dial_media_sink: 0, |
| cast_media_sink: 1, |
| }; |
| |
| Object.defineProperty(MediaSinkExtraDataAdapter.prototype, 'dial_media_sink', { |
| get: function() { |
| if (this.$tag != MediaSinkExtraDataAdapter.Tags.dial_media_sink) { |
| throw new ReferenceError( |
| 'MediaSinkExtraDataAdapter.dial_media_sink is not currently set.'); |
| } |
| return this.$data; |
| }, |
| |
| set: function(value) { |
| this.$tag = MediaSinkExtraDataAdapter.Tags.dial_media_sink; |
| this.$data = value; |
| } |
| }); |
| |
| Object.defineProperty(MediaSinkExtraDataAdapter.prototype, 'cast_media_sink', { |
| get: function() { |
| if (this.$tag != MediaSinkExtraDataAdapter.Tags.cast_media_sink) { |
| throw new ReferenceError( |
| 'MediaSinkExtraDataAdapter.cast_media_sink is not currently set.'); |
| } |
| return this.$data; |
| }, |
| |
| set: function(value) { |
| this.$tag = MediaSinkExtraDataAdapter.Tags.cast_media_sink; |
| this.$data = value; |
| } |
| }); |
| |
| MediaSinkExtraDataAdapter.fromNewVersion = function(other) { |
| if (other.$tag == mediaRouter.mojom.MediaSinkExtraData.Tags.dialMediaSink) { |
| return new MediaSinkExtraDataAdapter({ |
| 'dial_media_sink': |
| DialMediaSinkAdapter.fromNewVersion(other.dialMediaSink), |
| }); |
| } else { |
| return new MediaSinkExtraDataAdapter({ |
| 'cast_media_sink': |
| CastMediaSinkAdapter.fromNewVersion(other.castMediaSink), |
| }); |
| } |
| }; |
| |
| MediaSinkExtraDataAdapter.prototype.toNewVersion = function() { |
| if (this.$tag == MediaSinkExtraDataAdapter.Tags.dial_media_sink) { |
| return new mediaRouter.mojom.MediaSinkExtraData({ |
| 'dialMediaSink': this.dial_media_sink.toNewVersion(), |
| }); |
| } else { |
| return new mediaRouter.mojom.MediaSinkExtraData({ |
| 'castMediaSink': this.cast_media_sink.toNewVersion(), |
| }); |
| } |
| }; |
| |
| /** |
| * Adapter for media.mojom.MirrorServiceRemoterPtr. |
| * @constructor |
| */ |
| function MirrorServiceRemoterPtrAdapter(handleOrPtrInfo) { |
| this.ptr = new mojo.InterfacePtrController(MirrorServiceRemoterAdapter, |
| handleOrPtrInfo); |
| } |
| |
| MirrorServiceRemoterPtrAdapter.prototype = |
| Object.create(media.mojom.MirrorServiceRemoterPtr.prototype); |
| MirrorServiceRemoterPtrAdapter.prototype.constructor = |
| MirrorServiceRemoterPtrAdapter; |
| |
| MirrorServiceRemoterPtrAdapter.prototype.startDataStreams = function() { |
| return MirrorServiceRemoterProxy.prototype.startDataStreams |
| .apply(this.ptr.getProxy(), arguments).then(function(response) { |
| return Promise.resolve({ |
| 'audio_stream_id': response.audioStreamId, |
| 'video_stream_id': response.videoStreamId, |
| }); |
| }); |
| }; |
| |
| /** |
| * Adapter for media.mojom.MirrorServiceRemoter.stubclass. |
| * @constructor |
| */ |
| function MirrorServiceRemoterStubAdapter(delegate) { |
| this.delegate_ = delegate; |
| } |
| |
| MirrorServiceRemoterStubAdapter.prototype = Object.create( |
| media.mojom.MirrorServiceRemoter.stubClass.prototype); |
| MirrorServiceRemoterStubAdapter.prototype.constructor = |
| MirrorServiceRemoterStubAdapter; |
| |
| MirrorServiceRemoterStubAdapter.prototype.startDataStreams = |
| function(hasAudio, hasVideo) { |
| return this.delegate_ && this.delegate_.startDataStreams && |
| this.delegate_.startDataStreams(hasAudio, hasVideo).then( |
| function(response) { |
| return { |
| 'audioStreamId': response.audio_stream_id, |
| 'videoStreamId': response.video_stream_id, |
| }; |
| }); |
| }; |
| |
| /** |
| * Adapter for media.mojom.MirrorServiceRemoter. |
| */ |
| var MirrorServiceRemoterAdapter = { |
| name: 'media::mojom::MirrorServiceRemoter', |
| kVersion: 0, |
| ptrClass: MirrorServiceRemoterPtrAdapter, |
| proxyClass: media.mojom.MirrorServiceRemoter.proxyClass, |
| stubClass: MirrorServiceRemoterStubAdapter, |
| validateRequest: media.mojom.MirrorServiceRemoter.validateRequest, |
| validateResponse: media.mojom.MirrorServiceRemoter.validateResponse, |
| }; |
| |
| /** |
| * Adapter for media.mojom.MirrorServiceRemotingSourcePtr. |
| * @constructor |
| */ |
| function MirrorServiceRemotingSourcePtrAdapter(handleOrPtrInfo) { |
| this.ptr = new mojo.InterfacePtrController(MirrorServiceRemotingSourceAdapter, |
| handleOrPtrInfo); |
| } |
| |
| MirrorServiceRemotingSourcePtrAdapter.prototype = |
| Object.create(media.mojom.MirrorServiceRemotingSourcePtr.prototype); |
| MirrorServiceRemotingSourcePtrAdapter.prototype.constructor = |
| MirrorServiceRemotingSourcePtrAdapter; |
| |
| MirrorServiceRemotingSourcePtrAdapter.prototype.onSinkAvailable = |
| function(metadata) { |
| return this.ptr.getProxy().onSinkAvailable(metadata.toNewVersion()); |
| }; |
| |
| /** |
| * Adapter for media.mojom.MirrorServiceRemotingSource. |
| */ |
| var MirrorServiceRemotingSourceAdapter = { |
| name: 'media::mojom::MirrorServiceRemotingSource', |
| kVersion: 0, |
| ptrClass: MirrorServiceRemotingSourcePtrAdapter, |
| proxyClass: media.mojom.MirrorServiceRemotingSource.proxyClass, |
| stubClass: null, |
| validateRequest: media.mojom.MirrorServiceRemotingSource.validateRequest, |
| validateResponse: null, |
| }; |
| |
| /** |
| * Adapter for mediaRouter.mojom.MediaStatusObserver. |
| * @constructor |
| */ |
| function MediaStatusObserverPtrAdapter(handleOrPtrInfo) { |
| this.ptr = new mojo.InterfacePtrController(MediaStatusObserverAdapter, |
| handleOrPtrInfo); |
| } |
| |
| MediaStatusObserverPtrAdapter.prototype = |
| Object.create(mediaRouter.mojom.MediaStatusObserverPtr.prototype); |
| MediaStatusObserverPtrAdapter.prototype.constructor = |
| MediaStatusObserverPtrAdapter; |
| |
| MediaStatusObserverPtrAdapter.prototype.onMediaStatusUpdated = |
| function(status) { |
| return this.ptr.getProxy().onMediaStatusUpdated(status.toNewVersion()); |
| }; |
| |
| /** |
| * Adapter for mediaRouter.mojom.MediaStatusObserver. |
| */ |
| var MediaStatusObserverAdapter = { |
| name: 'mediaRouter::mojom::MediaStatusObserver', |
| kVersion: 0, |
| ptrClass: MediaStatusObserverPtrAdapter, |
| proxyClass: mediaRouter.mojom.MediaStatusObserver.proxyClass, |
| stubClass: null, |
| validateRequest: mediaRouter.mojom.MediaStatusObserver.validateRequest, |
| validateResponse: null, |
| }; |
| |
| /** |
| * Converts a media sink to a MediaSink Mojo object. |
| * @param {!MediaSink} sink A media sink. |
| * @return {!mediaRouter.mojom.MediaSink} A Mojo MediaSink object. |
| */ |
| function sinkToMojo_(sink) { |
| return new mediaRouter.mojom.MediaSink({ |
| 'name': sink.friendlyName, |
| 'description': sink.description, |
| 'domain': sink.domain, |
| 'sinkId': sink.id, |
| 'iconType': sinkIconTypeToMojo(sink.iconType), |
| 'provider_id': mediaRouter.mojom.MediaRouteProvider.Id.EXTENSION, |
| }); |
| } |
| |
| /** |
| * Converts a media sink's icon type to a MediaSink.IconType Mojo object. |
| * @param {!MediaSink.IconType} type A media sink's icon type. |
| * @return {!mediaRouter.mojom.MediaSink.IconType} A Mojo MediaSink.IconType |
| * object. |
| */ |
| function sinkIconTypeToMojo(type) { |
| switch (type) { |
| case 'cast': |
| return mediaRouter.mojom.SinkIconType.CAST; |
| case 'cast_audio_group': |
| return mediaRouter.mojom.SinkIconType.CAST_AUDIO_GROUP; |
| case 'cast_audio': |
| return mediaRouter.mojom.SinkIconType.CAST_AUDIO; |
| case 'meeting': |
| return mediaRouter.mojom.SinkIconType.MEETING; |
| case 'hangout': |
| return mediaRouter.mojom.SinkIconType.HANGOUT; |
| case 'education': |
| return mediaRouter.mojom.SinkIconType.EDUCATION; |
| case 'generic': |
| return mediaRouter.mojom.SinkIconType.GENERIC; |
| default: |
| console.error('Unknown sink icon type : ' + type); |
| return mediaRouter.mojom.SinkIconType.GENERIC; |
| } |
| } |
| |
| /** |
| * Returns a Mojo MediaRoute object given a MediaRoute and a |
| * media sink name. |
| * @param {!MediaRoute} route |
| * @return {!mediaRouter.mojom.MediaRoute} |
| */ |
| function routeToMojo_(route) { |
| return new mediaRouter.mojom.MediaRoute({ |
| 'mediaRouteId': route.id, |
| 'mediaSource': route.mediaSource, |
| 'mediaSinkId': route.sinkId, |
| 'description': route.description, |
| 'iconUrl': route.iconUrl, |
| 'isLocal': route.isLocal, |
| 'customControllerPath': route.customControllerPath || '', |
| 'forDisplay': route.forDisplay, |
| 'isIncognito': route.offTheRecord, |
| 'isLocalPresentation': route.isOffscreenPresentation, |
| 'supportsMediaRouteController': route.supportsMediaRouteController, |
| 'controllerType': route.controllerType, |
| // Begin newly added properties, followed by the milestone they were |
| // added. The guard should be safe to remove N+2 milestones later. |
| 'presentationId': route.presentationId || '' // M64 |
| }); |
| } |
| |
| /** |
| * Converts a route message to a RouteMessage Mojo object. |
| * @param {!RouteMessage} message |
| * @return {!mediaRouter.mojom.RouteMessage} A Mojo RouteMessage object. |
| */ |
| function messageToMojo_(message) { |
| if ("string" == typeof message.message) { |
| return new mediaRouter.mojom.RouteMessage({ |
| 'type': mediaRouter.mojom.RouteMessage.Type.TEXT, |
| 'message': message.message, |
| }); |
| } else { |
| return new mediaRouter.mojom.RouteMessage({ |
| 'type': mediaRouter.mojom.RouteMessage.Type.BINARY, |
| 'data': message.message, |
| }); |
| } |
| } |
| |
| /** |
| * Converts presentation connection state to Mojo enum value. |
| * @param {!string} state |
| * @return {!mediaRouter.mojom.MediaRouter.PresentationConnectionState} |
| */ |
| function presentationConnectionStateToMojo_(state) { |
| var PresentationConnectionState = |
| mediaRouter.mojom.MediaRouter.PresentationConnectionState; |
| switch (state) { |
| case 'connecting': |
| return PresentationConnectionState.CONNECTING; |
| case 'connected': |
| return PresentationConnectionState.CONNECTED; |
| case 'closed': |
| return PresentationConnectionState.CLOSED; |
| case 'terminated': |
| return PresentationConnectionState.TERMINATED; |
| default: |
| console.error('Unknown presentation connection state: ' + state); |
| return PresentationConnectionState.TERMINATED; |
| } |
| } |
| |
| /** |
| * Converts presentation connection close reason to Mojo enum value. |
| * @param {!string} reason |
| * @return {!mediaRouter.mojom.MediaRouter.PresentationConnectionCloseReason} |
| */ |
| function presentationConnectionCloseReasonToMojo_(reason) { |
| var PresentationConnectionCloseReason = |
| mediaRouter.mojom.MediaRouter.PresentationConnectionCloseReason; |
| switch (reason) { |
| case 'error': |
| return PresentationConnectionCloseReason.CONNECTION_ERROR; |
| case 'closed': |
| return PresentationConnectionCloseReason.CLOSED; |
| case 'went_away': |
| return PresentationConnectionCloseReason.WENT_AWAY; |
| default: |
| console.error('Unknown presentation connection close reason : ' + |
| reason); |
| return PresentationConnectionCloseReason.CONNECTION_ERROR; |
| } |
| } |
| |
| /** |
| * Parses the given route request Error object and converts it to the |
| * corresponding result code. |
| * @param {!Error} error |
| * @return {!mediaRouter.mojom.RouteRequestResultCode} |
| */ |
| function getRouteRequestResultCode_(error) { |
| return error.errorCode ? error.errorCode : |
| mediaRouter.mojom.RouteRequestResultCode.UNKNOWN_ERROR; |
| } |
| |
| /** |
| * Creates and returns a successful route response from given route. |
| * @param {!MediaRoute} route |
| * @return {!Object} |
| */ |
| function toSuccessRouteResponse_(route) { |
| return { |
| route: routeToMojo_(route), |
| resultCode: mediaRouter.mojom.RouteRequestResultCode.OK |
| }; |
| } |
| |
| /** |
| * Creates and returns a error route response from given Error object. |
| * @param {!Error} error |
| * @return {!Object} |
| */ |
| function toErrorRouteResponse_(error) { |
| return { |
| errorText: error.message, |
| resultCode: getRouteRequestResultCode_(error) |
| }; |
| } |
| |
| /** |
| * Creates a new MediaRouter. |
| * Converts a route struct to its Mojo form. |
| * @param {!mediaRouter.mojom.MediaRouterPtr} service |
| * @constructor |
| */ |
| function MediaRouter(service) { |
| /** |
| * The Mojo service proxy. Allows extension code to call methods that reside |
| * in the browser. |
| * @type {!mediaRouter.mojom.MediaRouterPtr} |
| */ |
| this.service_ = service; |
| |
| /** |
| * The provider manager service delegate. Its methods are called by the |
| * browser-resident Mojo service. |
| * @type {!MediaRouter} |
| */ |
| this.mrpm_ = new MediaRouteProvider(this); |
| |
| /** |
| * Handle to a KeepAlive service object, which prevents the extension from |
| * being suspended as long as it remains in scope. |
| * @type {boolean} |
| */ |
| this.keepAlive_ = null; |
| |
| /** |
| * The bindings to bind the service delegate to the Mojo interface. |
| * Object must remain in scope for the lifetime of the connection to |
| * prevent the connection from closing automatically. |
| * @type {!mojo.Binding} |
| */ |
| this.mediaRouteProviderBinding_ = new mojo.Binding( |
| mediaRouter.mojom.MediaRouteProvider, this.mrpm_); |
| } |
| |
| /** |
| * Returns definitions of Mojo core and generated Mojom classes that can be |
| * used directly by the component. |
| * @return {!Object} |
| * TODO(imcheng): We should export these along with MediaRouter. This requires |
| * us to modify the component to handle multiple exports. When that logic is |
| * baked in for a couple of milestones, we should be able to remove this |
| * method. |
| * TODO(imcheng): We should stop exporting mojo bindings classes that the |
| * Media Router extension doesn't directly use, such as |
| * mojo.AssociatedInterfacePtrInfo, mojo.InterfacePtrController and |
| * mojo.interfaceControl. |
| */ |
| MediaRouter.prototype.getMojoExports = function() { |
| return { |
| AssociatedInterfacePtrInfo: mojo.AssociatedInterfacePtrInfo, |
| Binding: mojo.Binding, |
| DialMediaSink: DialMediaSinkAdapter, |
| CastMediaSink: CastMediaSinkAdapter, |
| HangoutsMediaRouteController: |
| mediaRouter.mojom.HangoutsMediaRouteController, |
| HangoutsMediaStatusExtraData: HangoutsMediaStatusExtraDataAdapter, |
| IPAddress: IPAddressAdapter, |
| IPEndpoint: IPEndpointAdapter, |
| InterfacePtrController: mojo.InterfacePtrController, |
| InterfacePtrInfo: mojo.InterfacePtrInfo, |
| InterfaceRequest: mojo.InterfaceRequest, |
| MediaController: mediaRouter.mojom.MediaController, |
| MediaStatus: MediaStatusAdapter, |
| MediaStatusObserverPtr: mediaRouter.mojom.MediaStatusObserverPtr, |
| MirrorServiceRemoter: MirrorServiceRemoterAdapter, |
| MirrorServiceRemoterPtr: MirrorServiceRemoterPtrAdapter, |
| MirrorServiceRemotingSourcePtr: MirrorServiceRemotingSourcePtrAdapter, |
| RemotingStopReason: media.mojom.RemotingStopReason, |
| RemotingStartFailReason: media.mojom.RemotingStartFailReason, |
| RemotingSinkFeature: media.mojom.RemotingSinkFeature, |
| RemotingSinkAudioCapability: |
| media.mojom.RemotingSinkAudioCapability, |
| RemotingSinkVideoCapability: |
| media.mojom.RemotingSinkVideoCapability, |
| RemotingSinkMetadata: RemotingSinkMetadataAdapter, |
| RouteControllerType: mediaRouter.mojom.RouteControllerType, |
| Origin: url.mojom.Origin, |
| Sink: MediaSinkAdapter, |
| SinkExtraData: MediaSinkExtraDataAdapter, |
| TimeDelta: mojo.common.mojom.TimeDelta, |
| Url: url.mojom.Url, |
| interfaceControl: mojo.interfaceControl, |
| makeRequest: mojo.makeRequest, |
| }; |
| }; |
| |
| /** |
| * Registers the Media Router Provider Manager with the Media Router. |
| * @return {!Promise<Object>} Instance ID and config for the Media Router. |
| */ |
| MediaRouter.prototype.start = function() { |
| return this.service_.registerMediaRouteProvider( |
| mediaRouter.mojom.MediaRouteProvider.Id.EXTENSION, |
| this.mediaRouteProviderBinding_.createInterfacePtrAndBind()).then( |
| function(response) { |
| return { |
| 'enable_dial_discovery': response.enableDialDiscovery, |
| 'enable_cast_discovery': response.enableCastDiscovery, |
| }; |
| }); |
| } |
| |
| /** |
| * Sets the service delegate methods. |
| * @param {Object} handlers |
| */ |
| MediaRouter.prototype.setHandlers = function(handlers) { |
| this.mrpm_.setHandlers(handlers); |
| } |
| |
| /** |
| * The keep alive status. |
| * @return {boolean} |
| */ |
| MediaRouter.prototype.getKeepAlive = function() { |
| return this.keepAlive_ != null; |
| }; |
| |
| /** |
| * Called by the provider manager when a sink list for a given source is |
| * updated. |
| * @param {!string} sourceUrn |
| * @param {!Array<!MediaSink>} sinks |
| * @param {!Array<!url.mojom.Origin>} origins |
| */ |
| MediaRouter.prototype.onSinksReceived = function(sourceUrn, sinks, origins) { |
| this.service_.onSinksReceived( |
| mediaRouter.mojom.MediaRouteProvider.Id.EXTENSION, sourceUrn, |
| sinks.map(sinkToMojo_), origins); |
| }; |
| |
| /** |
| * Called by the provider manager when a sink is found to notify the MR of the |
| * sink's ID. The actual sink will be returned through the normal sink list |
| * update process, so this helps the MR identify the search result in the |
| * list. |
| * @param {string} pseudoSinkId ID of the pseudo sink that started the |
| * search. |
| * @param {string} sinkId ID of the newly-found sink. |
| */ |
| MediaRouter.prototype.onSearchSinkIdReceived = function( |
| pseudoSinkId, sinkId) { |
| this.service_.onSearchSinkIdReceived(pseudoSinkId, sinkId); |
| }; |
| |
| /** |
| * Called by the provider manager to keep the extension from suspending |
| * if it enters a state where suspension is undesirable (e.g. there is an |
| * active MediaRoute.) |
| * If keepAlive is true, the extension is kept alive. |
| * If keepAlive is false, the extension is allowed to suspend. |
| * @param {boolean} keepAlive |
| */ |
| MediaRouter.prototype.setKeepAlive = function(keepAlive) { |
| if (keepAlive === false && this.keepAlive_) { |
| this.keepAlive_.ptr.reset(); |
| this.keepAlive_ = null; |
| } else if (keepAlive === true && !this.keepAlive_) { |
| this.keepAlive_ = new extensions.KeepAlivePtr; |
| Mojo.bindInterface(extensions.KeepAlive.name, |
| mojo.makeRequest(this.keepAlive_).handle); |
| } |
| }; |
| |
| /** |
| * Called by the provider manager to send an issue from a media route |
| * provider to the Media Router, to show the user. |
| * @param {!Object} issue The issue object. |
| */ |
| MediaRouter.prototype.onIssue = function(issue) { |
| function issueSeverityToMojo_(severity) { |
| switch (severity) { |
| case 'fatal': |
| return mediaRouter.mojom.Issue.Severity.FATAL; |
| case 'warning': |
| return mediaRouter.mojom.Issue.Severity.WARNING; |
| case 'notification': |
| return mediaRouter.mojom.Issue.Severity.NOTIFICATION; |
| default: |
| console.error('Unknown issue severity: ' + severity); |
| return mediaRouter.mojom.Issue.Severity.NOTIFICATION; |
| } |
| } |
| |
| function issueActionToMojo_(action) { |
| switch (action) { |
| case 'dismiss': |
| return mediaRouter.mojom.Issue.ActionType.DISMISS; |
| case 'learn_more': |
| return mediaRouter.mojom.Issue.ActionType.LEARN_MORE; |
| default: |
| console.error('Unknown issue action type : ' + action); |
| return mediaRouter.mojom.Issue.ActionType.OK; |
| } |
| } |
| |
| var secondaryActions = (issue.secondaryActions || []).map(issueActionToMojo_); |
| this.service_.onIssue(new mediaRouter.mojom.Issue({ |
| 'routeId': issue.routeId || '', |
| 'severity': issueSeverityToMojo_(issue.severity), |
| 'title': issue.title, |
| 'message': issue.message || '', |
| 'defaultAction': issueActionToMojo_(issue.defaultAction), |
| 'secondaryActions': secondaryActions, |
| 'helpPageId': issue.helpPageId, |
| 'isBlocking': issue.isBlocking |
| })); |
| }; |
| |
| /** |
| * Called by the provider manager when the set of active routes |
| * has been updated. |
| * @param {!Array<MediaRoute>} routes The active set of media routes. |
| * @param {string=} sourceUrn The sourceUrn associated with this route |
| * query. |
| * @param {Array<string>=} joinableRouteIds The active set of joinable |
| * media routes. |
| */ |
| MediaRouter.prototype.onRoutesUpdated = function( |
| routes, sourceUrn = '', joinableRouteIds = []) { |
| this.service_.onRoutesUpdated( |
| mediaRouter.mojom.MediaRouteProvider.Id.EXTENSION, |
| routes.map(routeToMojo_), sourceUrn, joinableRouteIds); |
| }; |
| |
| /** |
| * Called by the provider manager when sink availability has been updated. |
| * @param {!mediaRouter.mojom.MediaRouter.SinkAvailability} availability |
| * The new sink availability. |
| */ |
| MediaRouter.prototype.onSinkAvailabilityUpdated = function(availability) { |
| this.service_.onSinkAvailabilityUpdated( |
| mediaRouter.mojom.MediaRouteProvider.Id.EXTENSION, availability); |
| }; |
| |
| /** |
| * Called by the provider manager when the state of a presentation connected |
| * to a route has changed. |
| * @param {string} routeId |
| * @param {string} state |
| */ |
| MediaRouter.prototype.onPresentationConnectionStateChanged = |
| function(routeId, state) { |
| this.service_.onPresentationConnectionStateChanged( |
| routeId, presentationConnectionStateToMojo_(state)); |
| }; |
| |
| /** |
| * Called by the provider manager when the state of a presentation connected |
| * to a route has closed. |
| * @param {string} routeId |
| * @param {string} reason |
| * @param {string} message |
| */ |
| MediaRouter.prototype.onPresentationConnectionClosed = |
| function(routeId, reason, message) { |
| this.service_.onPresentationConnectionClosed( |
| routeId, presentationConnectionCloseReasonToMojo_(reason), message); |
| }; |
| |
| /** |
| * @param {string} routeId |
| * @param {!Array<!RouteMessage>} mesages |
| */ |
| MediaRouter.prototype.onRouteMessagesReceived = function(routeId, messages) { |
| this.service_.onRouteMessagesReceived( |
| routeId, messages.map(messageToMojo_)); |
| }; |
| |
| /** |
| * @param {number} tabId |
| * @param {!media.mojom.MirrorServiceRemoterPtr} remoter |
| * @param {!mojo.InterfaceRequest} remotingSource |
| */ |
| MediaRouter.prototype.onMediaRemoterCreated = function(tabId, remoter, |
| remotingSource) { |
| this.service_.onMediaRemoterCreated( |
| tabId, |
| new media.mojom.MirrorServiceRemoterPtr(remoter.ptr.passInterface()), |
| remotingSource); |
| } |
| |
| /** |
| * Object containing callbacks set by the provider manager. |
| * |
| * @constructor |
| * @struct |
| */ |
| function MediaRouterHandlers() { |
| /** |
| * @type {function(!string, !string, !string, !string, !number)} |
| */ |
| this.createRoute = null; |
| |
| /** |
| * @type {function(!string, !string, !string, !number)} |
| */ |
| this.joinRoute = null; |
| |
| /** |
| * @type {function(string): Promise} |
| */ |
| this.terminateRoute = null; |
| |
| /** |
| * @type {function(string)} |
| */ |
| this.startObservingMediaSinks = null; |
| |
| /** |
| * @type {function(string)} |
| */ |
| this.stopObservingMediaSinks = null; |
| |
| /** |
| * @type {function(string, string): Promise} |
| */ |
| this.sendRouteMessage = null; |
| |
| /** |
| * @type {function(string, Uint8Array): Promise} |
| */ |
| this.sendRouteBinaryMessage = null; |
| |
| /** |
| * @type {function(string)} |
| */ |
| this.startListeningForRouteMessages = null; |
| |
| /** |
| * @type {function(string)} |
| */ |
| this.stopListeningForRouteMessages = null; |
| |
| /** |
| * @type {function(string)} |
| */ |
| this.detachRoute = null; |
| |
| /** |
| * @type {function()} |
| */ |
| this.startObservingMediaRoutes = null; |
| |
| /** |
| * @type {function()} |
| */ |
| this.stopObservingMediaRoutes = null; |
| |
| /** |
| * @type {function()} |
| */ |
| this.connectRouteByRouteId = null; |
| |
| /** |
| * @type {function()} |
| */ |
| this.enableMdnsDiscovery = null; |
| |
| /** |
| * @type {function()} |
| */ |
| this.updateMediaSinks = null; |
| |
| /** |
| * @type {function(string, string, !SinkSearchCriteria): string} |
| */ |
| this.searchSinks = null; |
| |
| /** |
| * @type {function()} |
| */ |
| this.provideSinks = null; |
| |
| /** |
| * @type {function(string, !mojo.InterfaceRequest, |
| * !mediaRouter.mojom.MediaStatusObserverPtr): !Promise<void>} |
| */ |
| this.createMediaRouteController = null; |
| }; |
| |
| /** |
| * Routes calls from Media Router to the provider manager extension. |
| * Registered with the MediaRouter stub. |
| * @param {!MediaRouter} MediaRouter proxy to call into the |
| * Media Router mojo interface. |
| * @constructor |
| */ |
| function MediaRouteProvider(mediaRouter) { |
| /** |
| * Object containing JS callbacks into Provider Manager code. |
| * @type {!MediaRouterHandlers} |
| */ |
| this.handlers_ = new MediaRouterHandlers(); |
| |
| /** |
| * Proxy class to the browser's Media Router Mojo service. |
| * @type {!MediaRouter} |
| */ |
| this.mediaRouter_ = mediaRouter; |
| } |
| |
| /* |
| * Sets the callback handler used to invoke methods in the provider manager. |
| * |
| * @param {!MediaRouterHandlers} handlers |
| */ |
| MediaRouteProvider.prototype.setHandlers = function(handlers) { |
| this.handlers_ = handlers; |
| var requiredHandlers = [ |
| 'stopObservingMediaRoutes', |
| 'startObservingMediaRoutes', |
| 'sendRouteMessage', |
| 'sendRouteBinaryMessage', |
| 'startListeningForRouteMessages', |
| 'stopListeningForRouteMessages', |
| 'detachRoute', |
| 'terminateRoute', |
| 'joinRoute', |
| 'createRoute', |
| 'stopObservingMediaSinks', |
| 'startObservingMediaRoutes', |
| 'connectRouteByRouteId', |
| 'enableMdnsDiscovery', |
| 'updateMediaSinks', |
| 'searchSinks', |
| 'provideSinks', |
| 'createMediaRouteController', |
| 'onBeforeInvokeHandler' |
| ]; |
| requiredHandlers.forEach(function(nextHandler) { |
| if (handlers[nextHandler] === undefined) { |
| console.error(nextHandler + ' handler not registered.'); |
| } |
| }); |
| } |
| |
| /** |
| * Starts querying for sinks capable of displaying the media source |
| * designated by |sourceUrn|. Results are returned by calling |
| * OnSinksReceived. |
| * @param {!string} sourceUrn |
| */ |
| MediaRouteProvider.prototype.startObservingMediaSinks = |
| function(sourceUrn) { |
| this.handlers_.onBeforeInvokeHandler(); |
| this.handlers_.startObservingMediaSinks(sourceUrn); |
| }; |
| |
| /** |
| * Stops querying for sinks capable of displaying |sourceUrn|. |
| * @param {!string} sourceUrn |
| */ |
| MediaRouteProvider.prototype.stopObservingMediaSinks = |
| function(sourceUrn) { |
| this.handlers_.onBeforeInvokeHandler(); |
| this.handlers_.stopObservingMediaSinks(sourceUrn); |
| }; |
| |
| /** |
| * Requests that |sinkId| render the media referenced by |sourceUrn|. If the |
| * request is from the Presentation API, then origin and tabId will |
| * be populated. |
| * @param {!string} sourceUrn Media source to render. |
| * @param {!string} sinkId Media sink ID. |
| * @param {!string} presentationId Presentation ID from the site |
| * requesting presentation. TODO(mfoltz): Remove. |
| * @param {!url.mojom.Origin} origin Origin of site requesting presentation. |
| * @param {!number} tabId ID of tab requesting presentation. |
| * @param {!mojo.common.mojom.TimeDelta} timeout If positive, the timeout |
| * duration for the request. Otherwise, the default duration will be used. |
| * @param {!boolean} incognito If true, the route is being requested by |
| * an incognito profile. |
| * @return {!Promise.<!Object>} A Promise resolving to an object describing |
| * the newly created media route, or rejecting with an error message on |
| * failure. |
| */ |
| MediaRouteProvider.prototype.createRoute = |
| function(sourceUrn, sinkId, presentationId, origin, tabId, |
| timeout, incognito) { |
| this.handlers_.onBeforeInvokeHandler(); |
| return this.handlers_.createRoute( |
| sourceUrn, sinkId, presentationId, origin, tabId, |
| Math.floor(timeout.microseconds / 1000), incognito) |
| .then(function(route) { |
| return toSuccessRouteResponse_(route); |
| }, |
| function(err) { |
| return toErrorRouteResponse_(err); |
| }); |
| }; |
| |
| /** |
| * Handles a request via the Presentation API to join an existing route given |
| * by |sourceUrn| and |presentationId|. |origin| and |tabId| are used for |
| * validating same-origin/tab scope. |
| * @param {!string} sourceUrn Media source to render. |
| * @param {!string} presentationId Presentation ID to join. |
| * @param {!url.mojom.Origin} origin Origin of site requesting join. |
| * @param {!number} tabId ID of tab requesting join. |
| * @param {!mojo.common.mojom.TimeDelta} timeout If positive, the timeout |
| * duration for the request. Otherwise, the default duration will be used. |
| * @param {!boolean} incognito If true, the route is being requested by |
| * an incognito profile. |
| * @return {!Promise.<!Object>} A Promise resolving to an object describing |
| * the newly created media route, or rejecting with an error message on |
| * failure. |
| */ |
| MediaRouteProvider.prototype.joinRoute = |
| function(sourceUrn, presentationId, origin, tabId, timeout, |
| incognito) { |
| this.handlers_.onBeforeInvokeHandler(); |
| return this.handlers_.joinRoute( |
| sourceUrn, presentationId, origin, tabId, |
| Math.floor(timeout.microseconds / 1000), incognito) |
| .then(function(route) { |
| return toSuccessRouteResponse_(route); |
| }, |
| function(err) { |
| return toErrorRouteResponse_(err); |
| }); |
| }; |
| |
| /** |
| * Handles a request via the Presentation API to join an existing route given |
| * by |sourceUrn| and |routeId|. |origin| and |tabId| are used for |
| * validating same-origin/tab scope. |
| * @param {!string} sourceUrn Media source to render. |
| * @param {!string} routeId Route ID to join. |
| * @param {!string} presentationId Presentation ID to join. |
| * @param {!url.mojom.Origin} origin Origin of site requesting join. |
| * @param {!number} tabId ID of tab requesting join. |
| * @param {!mojo.common.mojom.TimeDelta} timeout If positive, the timeout |
| * duration for the request. Otherwise, the default duration will be used. |
| * @param {!boolean} incognito If true, the route is being requested by |
| * an incognito profile. |
| * @return {!Promise.<!Object>} A Promise resolving to an object describing |
| * the newly created media route, or rejecting with an error message on |
| * failure. |
| */ |
| MediaRouteProvider.prototype.connectRouteByRouteId = |
| function(sourceUrn, routeId, presentationId, origin, tabId, |
| timeout, incognito) { |
| this.handlers_.onBeforeInvokeHandler(); |
| return this.handlers_.connectRouteByRouteId( |
| sourceUrn, routeId, presentationId, origin, tabId, |
| Math.floor(timeout.microseconds / 1000), incognito) |
| .then(function(route) { |
| return toSuccessRouteResponse_(route); |
| }, |
| function(err) { |
| return toErrorRouteResponse_(err); |
| }); |
| }; |
| |
| /** |
| * Terminates the route specified by |routeId|. |
| * @param {!string} routeId |
| * @return {!Promise<!Object>} A Promise resolving to an object describing |
| * the result of the terminate operation, or rejecting with an error |
| * message and code if the operation failed. |
| */ |
| MediaRouteProvider.prototype.terminateRoute = function(routeId) { |
| this.handlers_.onBeforeInvokeHandler(); |
| return this.handlers_.terminateRoute(routeId).then( |
| () => ({resultCode: mediaRouter.mojom.RouteRequestResultCode.OK}), |
| (err) => toErrorRouteResponse_(err)); |
| }; |
| |
| /** |
| * Posts a message to the route designated by |routeId|. |
| * @param {!string} routeId |
| * @param {!string} message |
| * @return {!Promise.<boolean>} Resolved with true if the message was sent, |
| * or false on failure. |
| */ |
| MediaRouteProvider.prototype.sendRouteMessage = function( |
| routeId, message) { |
| this.handlers_.onBeforeInvokeHandler(); |
| return this.handlers_.sendRouteMessage(routeId, message) |
| .then(function() { |
| return {'sent': true}; |
| }, function() { |
| return {'sent': false}; |
| }); |
| }; |
| |
| /** |
| * Sends a binary message to the route designated by |routeId|. |
| * @param {!string} routeId |
| * @param {!Array<number>} data |
| * @return {!Promise.<boolean>} Resolved with true if the data was sent, |
| * or false on failure. |
| */ |
| MediaRouteProvider.prototype.sendRouteBinaryMessage = function( |
| routeId, data) { |
| this.handlers_.onBeforeInvokeHandler(); |
| return this.handlers_.sendRouteBinaryMessage(routeId, new Uint8Array(data)) |
| .then(function() { |
| return {'sent': true}; |
| }, function() { |
| return {'sent': false}; |
| }); |
| }; |
| |
| /** |
| * Listen for messages from a route. |
| * @param {!string} routeId |
| */ |
| MediaRouteProvider.prototype.startListeningForRouteMessages = function( |
| routeId) { |
| this.handlers_.onBeforeInvokeHandler(); |
| this.handlers_.startListeningForRouteMessages(routeId); |
| }; |
| |
| /** |
| * @param {!string} routeId |
| */ |
| MediaRouteProvider.prototype.stopListeningForRouteMessages = function( |
| routeId) { |
| this.handlers_.onBeforeInvokeHandler(); |
| this.handlers_.stopListeningForRouteMessages(routeId); |
| }; |
| |
| /** |
| * Indicates that the presentation connection that was connected to |routeId| |
| * is no longer connected to it. |
| * @param {!string} routeId |
| */ |
| MediaRouteProvider.prototype.detachRoute = function( |
| routeId) { |
| this.handlers_.detachRoute(routeId); |
| }; |
| |
| /** |
| * Requests that the provider manager start sending information about active |
| * media routes to the Media Router. |
| * @param {!string} sourceUrn |
| */ |
| MediaRouteProvider.prototype.startObservingMediaRoutes = function(sourceUrn) { |
| this.handlers_.onBeforeInvokeHandler(); |
| this.handlers_.startObservingMediaRoutes(sourceUrn); |
| }; |
| |
| /** |
| * Requests that the provider manager stop sending information about active |
| * media routes to the Media Router. |
| * @param {!string} sourceUrn |
| */ |
| MediaRouteProvider.prototype.stopObservingMediaRoutes = function(sourceUrn) { |
| this.handlers_.onBeforeInvokeHandler(); |
| this.handlers_.stopObservingMediaRoutes(sourceUrn); |
| }; |
| |
| /** |
| * Enables mDNS device discovery. |
| */ |
| MediaRouteProvider.prototype.enableMdnsDiscovery = function() { |
| this.handlers_.onBeforeInvokeHandler(); |
| this.handlers_.enableMdnsDiscovery(); |
| }; |
| |
| /** |
| * Requests that the provider manager update media sinks. |
| * @param {!string} sourceUrn |
| */ |
| MediaRouteProvider.prototype.updateMediaSinks = function(sourceUrn) { |
| this.handlers_.onBeforeInvokeHandler(); |
| this.handlers_.updateMediaSinks(sourceUrn); |
| }; |
| |
| /** |
| * Requests that the provider manager search its providers for a sink matching |
| * |searchCriteria| that is compatible with |sourceUrn|. If a sink is found |
| * that can be used immediately for route creation, its ID is returned. |
| * Otherwise the empty string is returned. |
| * |
| * @param {string} sinkId Sink ID of the pseudo sink generating the request. |
| * @param {string} sourceUrn Media source to be used with the sink. |
| * @param {!SinkSearchCriteria} searchCriteria Search criteria for the route |
| * providers. |
| * @return {!Promise.<!{sink_id: !string}>} A Promise resolving to either the |
| * sink ID of the sink found by the search that can be used for route |
| * creation, or the empty string if no route can be immediately created. |
| */ |
| MediaRouteProvider.prototype.searchSinks = function( |
| sinkId, sourceUrn, searchCriteria) { |
| this.handlers_.onBeforeInvokeHandler(); |
| return this.handlers_.searchSinks(sinkId, sourceUrn, searchCriteria).then( |
| sinkId => { |
| return { 'sinkId': sinkId }; |
| }, |
| () => { |
| return { 'sinkId': '' }; |
| }); |
| }; |
| |
| /** |
| * Notifies the provider manager that MediaRouter has discovered a list of |
| * sinks. |
| * @param {string} providerName |
| * @param {!Array<!mediaRouter.mojom.MediaSink>} sinks |
| */ |
| MediaRouteProvider.prototype.provideSinks = function(providerName, sinks) { |
| this.handlers_.onBeforeInvokeHandler(); |
| this.handlers_.provideSinks(providerName, |
| sinks.map(MediaSinkAdapter.fromNewVersion)); |
| }; |
| |
| /** |
| * Creates a controller for the given route and binds the given |
| * InterfaceRequest to it, and registers an observer for media status updates |
| * for the route. |
| * @param {string} routeId |
| * @param {!mojo.InterfaceRequest} controllerRequest |
| * @param {!mediaRouter.mojom.MediaStatusObserverPtr} observer |
| * @return {!Promise<!{success: boolean}>} Resolves to true if a controller |
| * is created. Resolves to false if a controller cannot be created, or if |
| * the controller is already bound. |
| */ |
| MediaRouteProvider.prototype.createMediaRouteController = function( |
| routeId, controllerRequest, observer) { |
| this.handlers_.onBeforeInvokeHandler(); |
| return this.handlers_.createMediaRouteController( |
| routeId, controllerRequest, |
| new MediaStatusObserverPtrAdapter(observer.ptr.passInterface())).then( |
| () => ({success: true}), e => ({success: false})); |
| }; |
| |
| var ptr = new mediaRouter.mojom.MediaRouterPtr; |
| Mojo.bindInterface(mediaRouter.mojom.MediaRouter.name, |
| mojo.makeRequest(ptr).handle); |
| exports.$set('returnValue', new MediaRouter(ptr)); |