summaryrefslogtreecommitdiffstats
path: root/dom/presentation/provider/AndroidCastDeviceProvider.js
diff options
context:
space:
mode:
Diffstat (limited to 'dom/presentation/provider/AndroidCastDeviceProvider.js')
-rw-r--r--dom/presentation/provider/AndroidCastDeviceProvider.js461
1 files changed, 0 insertions, 461 deletions
diff --git a/dom/presentation/provider/AndroidCastDeviceProvider.js b/dom/presentation/provider/AndroidCastDeviceProvider.js
deleted file mode 100644
index cf555f77b..000000000
--- a/dom/presentation/provider/AndroidCastDeviceProvider.js
+++ /dev/null
@@ -1,461 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-/* jshint esnext:true, globalstrict:true, moz:true, undef:true, unused:true */
-/* globals Components, dump */
-"use strict";
-
-const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
-
-// globals XPCOMUtils
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-// globals Services
-Cu.import("resource://gre/modules/Services.jsm");
-// globals Messaging
-Cu.import("resource://gre/modules/Messaging.jsm");
-
-function log(str) {
- // dump("-*- AndroidCastDeviceProvider -*-: " + str + "\n");
-}
-
-// Helper function: transfer nsIPresentationChannelDescription to json
-function descriptionToString(aDescription) {
- let json = {};
- json.type = aDescription.type;
- switch(aDescription.type) {
- case Ci.nsIPresentationChannelDescription.TYPE_TCP:
- let addresses = aDescription.tcpAddress.QueryInterface(Ci.nsIArray);
- json.tcpAddress = [];
- for (let idx = 0; idx < addresses.length; idx++) {
- let address = addresses.queryElementAt(idx, Ci.nsISupportsCString);
- json.tcpAddress.push(address.data);
- }
- json.tcpPort = aDescription.tcpPort;
- break;
- case Ci.nsIPresentationChannelDescription.TYPE_DATACHANNEL:
- json.dataChannelSDP = aDescription.dataChannelSDP;
- break;
- }
- return JSON.stringify(json);
-}
-
-const TOPIC_ANDROID_CAST_DEVICE_SYNCDEVICE = "AndroidCastDevice:SyncDevice";
-const TOPIC_ANDROID_CAST_DEVICE_ADDED = "AndroidCastDevice:Added";
-const TOPIC_ANDROID_CAST_DEVICE_REMOVED = "AndroidCastDevice:Removed";
-const TOPIC_ANDROID_CAST_DEVICE_START = "AndroidCastDevice:Start";
-const TOPIC_ANDROID_CAST_DEVICE_STOP = "AndroidCastDevice:Stop";
-const TOPIC_PRESENTATION_VIEW_READY = "presentation-view-ready";
-
-function LocalControlChannel(aProvider, aDeviceId, aRole) {
- log("LocalControlChannel - create new LocalControlChannel for : "
- + aRole);
- this._provider = aProvider;
- this._deviceId = aDeviceId;
- this._role = aRole;
-}
-
-LocalControlChannel.prototype = {
- _listener: null,
- _provider: null,
- _deviceId: null,
- _role: null,
- _isOnTerminating: false,
- _isOnDisconnecting: false,
- _pendingConnected: false,
- _pendingDisconnect: null,
- _pendingOffer: null,
- _pendingCandidate: null,
- /* For the controller, it would be the control channel of the receiver.
- * For the receiver, it would be the control channel of the controller. */
- _correspondingControlChannel: null,
-
- set correspondingControlChannel(aCorrespondingControlChannel) {
- this._correspondingControlChannel = aCorrespondingControlChannel;
- },
-
- get correspondingControlChannel() {
- return this._correspondingControlChannel;
- },
-
- notifyConnected: function LCC_notifyConnected() {
- this._pendingDisconnect = null;
-
- if (!this._listener) {
- this._pendingConnected = true;
- } else {
- this._listener.notifyConnected();
- }
- },
-
- onOffer: function LCC_onOffer(aOffer) {
- if (this._role == Ci.nsIPresentationService.ROLE_CONTROLLER) {
- log("LocalControlChannel - onOffer of controller should not be called.");
- return;
- }
- if (!this._listener) {
- this._pendingOffer = aOffer;
- } else {
- this._listener.onOffer(aOffer);
- }
- },
-
- onAnswer: function LCC_onAnswer(aAnswer) {
- if (this._role == Ci.nsIPresentationService.ROLE_RECEIVER) {
- log("LocalControlChannel - onAnswer of receiver should not be called.");
- return;
- }
- this._listener.onAnswer(aAnswer);
- },
-
- notifyIceCandidate: function LCC_notifyIceCandidate(aCandidate) {
- if (!this._listener) {
- this._pendingCandidate = aCandidate;
- } else {
- this._listener.onIceCandidate(aCandidate);
- }
- },
-
- // nsIPresentationControlChannel
- get listener() {
- return this._listener;
- },
-
- set listener(aListener) {
- this._listener = aListener;
-
- if (!this._listener) {
- return;
- }
-
- if (this._pendingConnected) {
- this.notifyConnected();
- this._pendingConnected = false;
- }
-
- if (this._pendingOffer) {
- this.onOffer(this._pendingOffer);
- this._pendingOffer = null;
- }
-
- if (this._pendingCandidate) {
- this.notifyIceCandidate(this._pendingCandidate);
- this._pendingCandidate = null;
- }
-
- if (this._pendingDisconnect != null) {
- this.disconnect(this._pendingDisconnect);
- this._pendingDisconnect = null;
- }
- },
-
- sendOffer: function LCC_sendOffer(aOffer) {
- if (this._role == Ci.nsIPresentationService.ROLE_RECEIVER) {
- log("LocalControlChannel - sendOffer of receiver should not be called.");
- return;
- }
- log("LocalControlChannel - sendOffer aOffer=" + descriptionToString(aOffer));
- this._correspondingControlChannel.onOffer(aOffer);
- },
-
- sendAnswer: function LCC_sendAnswer(aAnswer) {
- if (this._role == Ci.nsIPresentationService.ROLE_CONTROLLER) {
- log("LocalControlChannel - sendAnswer of controller should not be called.");
- return;
- }
- log("LocalControlChannel - sendAnswer aAnswer=" + descriptionToString(aAnswer));
- this._correspondingControlChannel.onAnswer(aAnswer);
- },
-
- sendIceCandidate: function LCC_sendIceCandidate(aCandidate) {
- log("LocalControlChannel - sendAnswer aCandidate=" + aCandidate);
- this._correspondingControlChannel.notifyIceCandidate(aCandidate);
- },
-
- launch: function LCC_launch(aPresentationId, aUrl) {
- log("LocalControlChannel - launch aPresentationId="
- + aPresentationId + " aUrl=" + aUrl);
- // Create control channel for receiver directly.
- let controlChannel = new LocalControlChannel(this._provider,
- this._deviceId,
- Ci.nsIPresentationService.ROLE_RECEIVER);
-
- // Set up the corresponding control channels for both controller and receiver.
- this._correspondingControlChannel = controlChannel;
- controlChannel._correspondingControlChannel = this;
-
- this._provider.onSessionRequest(this._deviceId,
- aUrl,
- aPresentationId,
- controlChannel);
- controlChannel.notifyConnected();
- },
-
- terminate: function LCC_terminate(aPresentationId) {
- log("LocalControlChannel - terminate aPresentationId="
- + aPresentationId);
-
- if (this._isOnTerminating) {
- return;
- }
-
- // Create control channel for corresponding role directly.
- let correspondingRole = this._role == Ci.nsIPresentationService.ROLE_CONTROLLER
- ? Ci.nsIPresentationService.ROLE_RECEIVER
- : Ci.nsIPresentationService.ROLE_CONTROLLER;
- let controlChannel = new LocalControlChannel(this._provider,
- this._deviceId,
- correspondingRole);
- // Prevent the termination recursion.
- controlChannel._isOnTerminating = true;
-
- // Set up the corresponding control channels for both controller and receiver.
- this._correspondingControlChannel = controlChannel;
- controlChannel._correspondingControlChannel = this;
-
- this._provider.onTerminateRequest(this._deviceId,
- aPresentationId,
- controlChannel,
- this._role == Ci.nsIPresentationService.ROLE_RECEIVER);
- controlChannel.notifyConnected();
- },
-
- disconnect: function LCC_disconnect(aReason) {
- log("LocalControlChannel - disconnect aReason=" + aReason);
-
- if (this._isOnDisconnecting) {
- return;
- }
-
- this._pendingOffer = null;
- this._pendingCandidate = null;
- this._pendingConnected = false;
-
- // this._pendingDisconnect is a nsresult.
- // If it is null, it means no pending disconnect.
- // If it is NS_OK, it means this control channel is disconnected normally.
- // If it is other nsresult value, it means this control channel is
- // disconnected abnormally.
-
- // Remote endpoint closes the control channel with abnormal reason.
- if (aReason == Cr.NS_OK &&
- this._pendingDisconnect != null &&
- this._pendingDisconnect != Cr.NS_OK) {
- aReason = this._pendingDisconnect;
- }
-
- if (!this._listener) {
- this._pendingDisconnect = aReason;
- return;
- }
-
- this._isOnDisconnecting = true;
- this._correspondingControlChannel.disconnect(aReason);
- this._listener.notifyDisconnected(aReason);
- },
-
- reconnect: function LCC_reconnect(aPresentationId, aUrl) {
- log("1-UA on Android doesn't support reconnect.");
- throw Cr.NS_ERROR_FAILURE;
- },
-
- classID: Components.ID("{c9be9450-e5c7-4294-a287-376971b017fd}"),
- QueryInterface: XPCOMUtils.generateQI([Ci.nsIPresentationControlChannel]),
-};
-
-function ChromecastRemoteDisplayDevice(aProvider, aId, aName, aRole) {
- this._provider = aProvider;
- this._id = aId;
- this._name = aName;
- this._role = aRole;
-}
-
-ChromecastRemoteDisplayDevice.prototype = {
- _id: null,
- _name: null,
- _role: null,
- _provider: null,
- _ctrlChannel: null,
-
- update: function CRDD_update(aName) {
- this._name = aName || this._name;
- },
-
- // nsIPresentationDevice
- get id() { return this._id; },
-
- get name() { return this._name; },
-
- get type() { return "chromecast"; },
-
- establishControlChannel: function CRDD_establishControlChannel() {
- this._ctrlChannel = new LocalControlChannel(this._provider,
- this._id,
- this._role);
-
- if (this._role == Ci.nsIPresentationService.ROLE_CONTROLLER) {
- // Only connect to Chromecast for controller.
- // Monitor the receiver being ready.
- Services.obs.addObserver(this, TOPIC_PRESENTATION_VIEW_READY, true);
-
- // Launch Chromecast service in Android.
- Messaging.sendRequestForResult({
- type: TOPIC_ANDROID_CAST_DEVICE_START,
- id: this.id
- }).then(result => {
- log("Chromecast is connected.");
- }).catch(error => {
- log("Can not connect to Chromecast.");
- // If Chromecast can not be launched, remove the observer.
- Services.obs.removeObserver(this, TOPIC_PRESENTATION_VIEW_READY);
- this._ctrlChannel.disconnect(Cr.NS_ERROR_FAILURE);
- });
- } else {
- // If establishControlChannel called from the receiver, we don't need to
- // wait the 'presentation-view-ready' event.
- this._ctrlChannel.notifyConnected();
- }
-
- return this._ctrlChannel;
- },
-
- disconnect: function CRDD_disconnect() {
- // Disconnect from Chromecast.
- Messaging.sendRequestForResult({
- type: TOPIC_ANDROID_CAST_DEVICE_STOP,
- id: this.id
- });
- },
-
- isRequestedUrlSupported: function CRDD_isRequestedUrlSupported(aUrl) {
- let url = Cc["@mozilla.org/network/io-service;1"]
- .getService(Ci.nsIIOService)
- .newURI(aUrl, null, null);
- return url.scheme == "http" || url.scheme == "https";
- },
-
- // nsIPresentationLocalDevice
- get windowId() { return this._id; },
-
- // nsIObserver
- observe: function CRDD_observe(aSubject, aTopic, aData) {
- if (aTopic == TOPIC_PRESENTATION_VIEW_READY) {
- log("ChromecastRemoteDisplayDevice - observe: aTopic="
- + aTopic + " data=" + aData);
- if (this.windowId === aData) {
- Services.obs.removeObserver(this, TOPIC_PRESENTATION_VIEW_READY);
- this._ctrlChannel.notifyConnected();
- }
- }
- },
-
- QueryInterface: XPCOMUtils.generateQI([Ci.nsIPresentationDevice,
- Ci.nsIPresentationLocalDevice,
- Ci.nsISupportsWeakReference,
- Ci.nsIObserver]),
-};
-
-function AndroidCastDeviceProvider() {
-}
-
-AndroidCastDeviceProvider.prototype = {
- _listener: null,
- _deviceList: new Map(),
-
- onSessionRequest: function APDP_onSessionRequest(aDeviceId,
- aUrl,
- aPresentationId,
- aControlChannel) {
- log("AndroidCastDeviceProvider - onSessionRequest"
- + " aDeviceId=" + aDeviceId);
- let device = this._deviceList.get(aDeviceId);
- let receiverDevice = new ChromecastRemoteDisplayDevice(this,
- device.id,
- device.name,
- Ci.nsIPresentationService.ROLE_RECEIVER);
- this._listener.onSessionRequest(receiverDevice,
- aUrl,
- aPresentationId,
- aControlChannel);
- },
-
- onTerminateRequest: function APDP_onTerminateRequest(aDeviceId,
- aPresentationId,
- aControlChannel,
- aIsFromReceiver) {
- log("AndroidCastDeviceProvider - onTerminateRequest"
- + " aDeviceId=" + aDeviceId
- + " aPresentationId=" + aPresentationId
- + " aIsFromReceiver=" + aIsFromReceiver);
- let device = this._deviceList.get(aDeviceId);
- this._listener.onTerminateRequest(device,
- aPresentationId,
- aControlChannel,
- aIsFromReceiver);
- },
-
- // nsIPresentationDeviceProvider
- set listener(aListener) {
- this._listener = aListener;
-
- // When unload this provider.
- if (!this._listener) {
- // remove observer
- Services.obs.removeObserver(this, TOPIC_ANDROID_CAST_DEVICE_ADDED);
- Services.obs.removeObserver(this, TOPIC_ANDROID_CAST_DEVICE_REMOVED);
- return;
- }
-
- // Sync all device already found by Android.
- Services.obs.notifyObservers(null, TOPIC_ANDROID_CAST_DEVICE_SYNCDEVICE, "");
- // Observer registration
- Services.obs.addObserver(this, TOPIC_ANDROID_CAST_DEVICE_ADDED, false);
- Services.obs.addObserver(this, TOPIC_ANDROID_CAST_DEVICE_REMOVED, false);
- },
-
- get listener() {
- return this._listener;
- },
-
- forceDiscovery: function APDP_forceDiscovery() {
- // There is no API to do force discovery in Android SDK.
- },
-
- // nsIObserver
- observe: function APDP_observe(aSubject, aTopic, aData) {
- switch (aTopic) {
- case TOPIC_ANDROID_CAST_DEVICE_ADDED: {
- let deviceInfo = JSON.parse(aData);
- let deviceId = deviceInfo.uuid;
-
- if (!this._deviceList.has(deviceId)) {
- let device = new ChromecastRemoteDisplayDevice(this,
- deviceInfo.uuid,
- deviceInfo.friendlyName,
- Ci.nsIPresentationService.ROLE_CONTROLLER);
- this._deviceList.set(device.id, device);
- this._listener.addDevice(device);
- } else {
- let device = this._deviceList.get(deviceId);
- device.update(deviceInfo.friendlyName);
- this._listener.updateDevice(device);
- }
- break;
- }
- case TOPIC_ANDROID_CAST_DEVICE_REMOVED: {
- let deviceId = aData;
- let device = this._deviceList.get(deviceId);
- this._listener.removeDevice(device);
- this._deviceList.delete(deviceId);
- break;
- }
- }
- },
-
- classID: Components.ID("{7394f24c-dbc3-48c8-8a47-cd10169b7c6b}"),
- QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
- Ci.nsIPresentationDeviceProvider]),
-};
-
-this.NSGetFactory = XPCOMUtils.generateNSGetFactory([AndroidCastDeviceProvider]);