Bug 1188609 - Remove mirroring support from RokuApp (Toolkit) r=snorp
authorMark Finkle <mfinkle@mozilla.com>
Wed, 29 Jul 2015 16:09:25 -0400
changeset 286889 2e5739c2d44cb6230861ae361481deb03b041d90
parent 286888 09573cae39d381301c36bda5b1563aca42453cf9
child 286890 a9d0a5557f5c0c18a12caca53d0f9e1706d8cac3
push id5067
push userraliiev@mozilla.com
push dateMon, 21 Sep 2015 14:04:52 +0000
treeherdermozilla-beta@14221ffe5b2f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssnorp
bugs1188609
milestone42.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1188609 - Remove mirroring support from RokuApp (Toolkit) r=snorp
toolkit/modules/secondscreen/RokuApp.jsm
--- a/toolkit/modules/secondscreen/RokuApp.jsm
+++ b/toolkit/modules/secondscreen/RokuApp.jsm
@@ -7,36 +7,31 @@
 
 this.EXPORTED_SYMBOLS = ["RokuApp"];
 
 const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
 
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/AppConstants.jsm");
 
-const WEBRTC_PLAYER_NAME = "WebRTC Player";
-const MIRROR_PORT = 8011;
-const JSON_MESSAGE_TERMINATOR = "\r\n";
-
 function log(msg) {
   //Services.console.logStringMessage(msg);
 }
 
 const PROTOCOL_VERSION = 1;
 
 /* RokuApp is a wrapper for interacting with a Roku channel.
  * The basic interactions all use a REST API.
  * spec: http://sdkdocs.roku.com/display/sdkdoc/External+Control+Guide
  */
 function RokuApp(service) {
   this.service = service;
   this.resourceURL = this.service.location;
   this.app = AppConstants.RELEASE_BUILD ? "Firefox" : "Firefox Nightly";
   this.mediaAppID = -1;
-  this.mirrorAppID = -1;
 }
 
 RokuApp.prototype = {
   status: function status(callback) {
     // We have no way to know if the app is running, so just return "unknown"
     // but we use this call to fetch the mediaAppID for the given app name
     let url = this.resourceURL + "query/apps";
     let xhr = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].createInstance(Ci.nsIXMLHttpRequest);
@@ -46,18 +41,16 @@ RokuApp.prototype = {
 
     xhr.addEventListener("load", (function() {
       if (xhr.status == 200) {
         let doc = xhr.responseXML;
         let apps = doc.querySelectorAll("app");
         for (let app of apps) {
           if (app.textContent == this.app) {
             this.mediaAppID = app.id;
-          } else if (app.textContent == WEBRTC_PLAYER_NAME) {
-            this.mirrorAppID = app.id
           }
         }
       }
 
       // Since ECP has no way of telling us if an app is running, we always return "unknown"
       if (callback) {
         callback({ state: "unknown" });
       }
@@ -137,54 +130,16 @@ RokuApp.prototype = {
       if (callback) {
         callback(new RemoteMedia(this.resourceURL, listener));
       }
     } else {
       if (callback) {
         callback();
       }
     }
-  },
-
-  mirror: function(callback, win, viewport, mirrorStartedCallback, contentWindow) {
-    if (this.mirrorAppID == -1) {
-      // The status function may not have been called yet if mirrorAppID is -1
-      this.status(this._createRemoteMirror.bind(this, callback, win, viewport, mirrorStartedCallback, contentWindow));
-    } else {
-      this._createRemoteMirror(callback, win, viewport, mirrorStartedCallback, contentWindow);
-    }
-  },
-
-  _createRemoteMirror: function(callback, win, viewport, mirrorStartedCallback, contentWindow) {
-    if (this.mirrorAppID == -1) {
-      // TODO: Inform user to install Roku WebRTC Player Channel.
-      log("RokuApp: Failed to find Mirror App ID.");
-    } else {
-      let url = this.resourceURL + "launch/" + this.mirrorAppID;
-      let xhr = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].createInstance(Ci.nsIXMLHttpRequest);
-      xhr.open("POST", url, true);
-      xhr.overrideMimeType("text/plain");
-
-      xhr.addEventListener("load", (function() {
-        // 204 seems to be returned if the channel is already running
-        if ((xhr.status == 200) || (xhr.status == 204)) {
-          this.remoteMirror = new RemoteMirror(this.resourceURL, win, viewport, mirrorStartedCallback, contentWindow);
-        }
-      }).bind(this), false);
-
-      xhr.addEventListener("error", function() {
-        log("RokuApp: XHR Failed to launch application: " + WEBRTC_PLAYER_NAME);
-      }, false);
-
-      xhr.send(null);
-    }
-
-    if (callback) {
-      callback();
-    }
   }
 }
 
 /* RemoteMedia provides a wrapper for using TCP socket to control Roku apps.
  * The server implementation must be built into the Roku receiver app.
  */
 function RemoteMedia(url, listener) {
   this._url = url;
@@ -270,136 +225,8 @@ RemoteMedia.prototype = {
   load: function load(data) {
     this._sendMsg({ type: "LOAD", title: data.title, source: data.source, poster: data.poster });
   },
 
   get status() {
     return this._status;
   }
 }
-
-function RemoteMirror(url, win, viewport, mirrorStartedCallback, contentWindow) {
-  this._serverURI = Services.io.newURI(url , null, null);
-  this._window = win;
-  this._iceCandidates = [];
-  this.mirrorStarted = mirrorStartedCallback;
-
-  // This code insures the generated tab mirror is not wider than 1280 nor taller than 720
-  // Better dimensions should be chosen after the Roku Channel is working.
-  let windowId = contentWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils).outerWindowID;
-  const MAX_WIDTH = 1280;
-  const MAX_HEIGHT = 720;
-
-  let constraints = {
-    video: {
-      mediaSource: "browser",
-      browserWindow: windowId,
-      scrollWithPage: true,
-      advanced: [
-        {
-          width: { min: 0, max: MAX_WIDTH },
-          height: { min: 0, max: MAX_HEIGHT }
-        },
-        { aspectRatio: MAX_WIDTH/MAX_HEIGHT }
-      ]
-    }
-  };
-
-  this._window.navigator.mozGetUserMedia(constraints, this._onReceiveGUMStream.bind(this), function() {});
-}
-
-RemoteMirror.prototype = {
-  _sendOffer: function(offer) {
-    if (!this._baseSocket) {
-      this._baseSocket = Cc["@mozilla.org/tcp-socket;1"].createInstance(Ci.nsIDOMTCPSocket);
-    }
-    this._jsonOffer = JSON.stringify(offer);
-    this._socket = this._baseSocket.open(this._serverURI.host, MIRROR_PORT, { useSecureTransport: false, binaryType: "string" });
-    this._socket.onopen = this._onSocketOpen.bind(this);
-    this._socket.ondata = this._onSocketData.bind(this);
-    this._socket.onerror = this._onSocketError.bind(this);
-  },
-
-  _onReceiveGUMStream: function(stream) {
-    this._pc = new this._window.mozRTCPeerConnection;
-    this._pc.addStream(stream);
-    this._pc.onicecandidate = (evt => {
-      // Usually the last candidate is null, expected?
-      if (!evt.candidate) {
-        return;
-      }
-      let jsonCandidate = JSON.stringify(evt.candidate);
-      this._iceCandidates.push(jsonCandidate);
-      this._sendIceCandidates();
-    });
-
-    this._pc.createOffer(offer => {
-      this._pc.setLocalDescription(
-        new this._window.mozRTCSessionDescription(offer),
-        () => this._sendOffer(offer),
-        () => log("RemoteMirror: Failed to set local description."));
-    },
-    () => log("RemoteMirror: Failed to create offer."));
-  },
-
-  _stopMirror: function() {
-    if (this._socket) {
-      this._socket.close();
-      this._socket = null;
-    }
-    if (this._pc) {
-      this._pc.close();
-      this._pc = null;
-    }
-    this._jsonOffer = null;
-    this._iceCandidates = [];
-  },
-
-  _onSocketData: function(response) {
-    if (response.type == "data") {
-      response.data.split(JSON_MESSAGE_TERMINATOR).forEach(data => {
-        if (data) {
-          let parsedData = JSON.parse(data);
-          if (parsedData.type == "answer") {
-            this._pc.setRemoteDescription(
-              new this._window.mozRTCSessionDescription(parsedData),
-              () => this.mirrorStarted(this._stopMirror.bind(this)),
-              () => log("RemoteMirror: Failed to set remote description."));
-          } else {
-            this._pc.addIceCandidate(new this._window.mozRTCIceCandidate(parsedData))
-          }
-        } else {
-          log("RemoteMirror: data is null");
-        }
-      });
-    } else if (response.type == "error") {
-      log("RemoteMirror: Got socket error.");
-      this._stopMirror();
-    } else {
-      log("RemoteMirror: Got unhandled socket event: " + response.type);
-    }
-  },
-
-  _onSocketError: function(err) {
-    log("RemoteMirror: Error socket.onerror: " + (err.data ? err.data : "NO DATA"));
-    this._stopMirror();
-  },
-
-  _onSocketOpen: function() {
-    this._open = true;
-    if (this._jsonOffer) {
-      let jsonOffer = this._jsonOffer + JSON_MESSAGE_TERMINATOR;
-      this._socket.send(jsonOffer, jsonOffer.length);
-      this._jsonOffer = null;
-      this._sendIceCandidates();
-    }
-  },
-
-  _sendIceCandidates: function() {
-    if (this._socket && this._open) {
-      this._iceCandidates.forEach(value => {
-        value = value + JSON_MESSAGE_TERMINATOR;
-        this._socket.send(value, value.length);
-      });
-      this._iceCandidates = [];
-    }
-  }
-};