mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-12 21:05:36 +00:00
Bug 1197874 - Remove MatchstickApp.jsm from the build. r=mfinkle
This commit is contained in:
parent
38bd36d05f
commit
cc08782363
@ -21,4 +21,3 @@ modules/WebappManager.jsm
|
||||
|
||||
# Non-standard `(catch ex if ...)`
|
||||
components/Snippets.js
|
||||
modules/MatchstickApp.jsm
|
||||
|
@ -10,7 +10,6 @@ globals:
|
||||
SimpleServiceDiscovery: false
|
||||
TabMirror: false
|
||||
MediaPlayerApp: false
|
||||
MatchstickApp: false
|
||||
RokuApp: false
|
||||
SearchEngines: false
|
||||
ConsoleAPI: true
|
||||
|
@ -20,20 +20,6 @@ var rokuDevice = {
|
||||
extensions: ["mp4"]
|
||||
};
|
||||
|
||||
var matchstickDevice = {
|
||||
id: "matchstick:dial",
|
||||
target: "urn:dial-multiscreen-org:service:dial:1",
|
||||
filters: {
|
||||
manufacturer: "openflint"
|
||||
},
|
||||
factory: function(aService) {
|
||||
Cu.import("resource://gre/modules/MatchstickApp.jsm");
|
||||
return new MatchstickApp(aService);
|
||||
},
|
||||
types: ["video/mp4", "video/webm"],
|
||||
extensions: ["mp4", "webm"]
|
||||
};
|
||||
|
||||
var mediaPlayerDevice = {
|
||||
id: "media:router",
|
||||
target: "media:router",
|
||||
@ -85,7 +71,6 @@ var CastingApps = {
|
||||
|
||||
// Register targets
|
||||
SimpleServiceDiscovery.registerDevice(rokuDevice);
|
||||
SimpleServiceDiscovery.registerDevice(matchstickDevice);
|
||||
|
||||
// MediaPlayerDevice will notify us any time the native device list changes.
|
||||
mediaPlayerDevice.init();
|
||||
|
@ -1,375 +0,0 @@
|
||||
/* -*- js-indent-level: 2; indent-tabs-mode: nil -*- */
|
||||
/* 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/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["MatchstickApp"];
|
||||
|
||||
const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
function log(msg) {
|
||||
Services.console.logStringMessage(msg);
|
||||
}
|
||||
|
||||
const MATCHSTICK_PLAYER_URL = "http://openflint.github.io/flint-player/player.html";
|
||||
|
||||
const STATUS_RETRY_COUNT = 5; // Number of times we retry a partial status
|
||||
const STATUS_RETRY_WAIT = 1000; // Delay between attempts in milliseconds
|
||||
|
||||
/* MatchstickApp is a wrapper for interacting with a DIAL server.
|
||||
* The basic interactions all use a REST API.
|
||||
* See: https://github.com/openflint/openflint.github.io/wiki/Flint%20Protocol%20Docs
|
||||
*/
|
||||
function MatchstickApp(aServer) {
|
||||
this.server = aServer;
|
||||
this.app = "~flintplayer";
|
||||
this.resourceURL = this.server.appsURL + this.app;
|
||||
this.token = null;
|
||||
this.statusTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
|
||||
this.statusRetry = 0;
|
||||
}
|
||||
|
||||
MatchstickApp.prototype = {
|
||||
status: function status(aCallback) {
|
||||
// Query the server to see if an application is already running
|
||||
let xhr = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].createInstance(Ci.nsIXMLHttpRequest);
|
||||
xhr.open("GET", this.resourceURL, true);
|
||||
xhr.channel.loadFlags |= Ci.nsIRequest.INHIBIT_CACHING;
|
||||
xhr.setRequestHeader("Accept", "application/xml; charset=utf8");
|
||||
xhr.setRequestHeader("Authorization", this.token);
|
||||
|
||||
xhr.addEventListener("load", (function() {
|
||||
if (xhr.status == 200) {
|
||||
let doc = xhr.responseXML;
|
||||
let state = doc.querySelector("state").textContent;
|
||||
|
||||
// The serviceURL can be missing if the player is not completely loaded
|
||||
let serviceURL = null;
|
||||
let serviceNode = doc.querySelector("channelBaseUrl");
|
||||
if (serviceNode) {
|
||||
serviceURL = serviceNode.textContent + "/senders/" + this.token;
|
||||
}
|
||||
|
||||
if (aCallback)
|
||||
aCallback({ state: state, serviceURL: serviceURL });
|
||||
} else {
|
||||
if (aCallback)
|
||||
aCallback({ state: "error" });
|
||||
}
|
||||
}).bind(this), false);
|
||||
|
||||
xhr.addEventListener("error", (function() {
|
||||
if (aCallback)
|
||||
aCallback({ state: "error" });
|
||||
}).bind(this), false);
|
||||
|
||||
xhr.send(null);
|
||||
},
|
||||
|
||||
start: function start(aCallback) {
|
||||
// Start a given app with any extra query data. Each app uses it's own data scheme.
|
||||
let xhr = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].createInstance(Ci.nsIXMLHttpRequest);
|
||||
xhr.open("POST", this.resourceURL, true);
|
||||
xhr.overrideMimeType("text/xml");
|
||||
xhr.setRequestHeader("Content-Type", "application/json");
|
||||
|
||||
xhr.addEventListener("load", (function() {
|
||||
if (xhr.status == 200 || xhr.status == 201) {
|
||||
this.statusRetry = 0;
|
||||
|
||||
let response = JSON.parse(xhr.responseText);
|
||||
this.token = response.token;
|
||||
this.pingInterval = response.interval;
|
||||
|
||||
if (aCallback)
|
||||
aCallback(true);
|
||||
} else {
|
||||
if (aCallback)
|
||||
aCallback(false);
|
||||
}
|
||||
}).bind(this), false);
|
||||
|
||||
xhr.addEventListener("error", (function() {
|
||||
if (aCallback)
|
||||
aCallback(false);
|
||||
}).bind(this), false);
|
||||
|
||||
let data = {
|
||||
type: "launch",
|
||||
app_info: {
|
||||
url: MATCHSTICK_PLAYER_URL,
|
||||
useIpc: true,
|
||||
maxInactive: -1
|
||||
}
|
||||
};
|
||||
|
||||
xhr.send(JSON.stringify(data));
|
||||
},
|
||||
|
||||
stop: function stop(aCallback) {
|
||||
// Send command to kill an app, if it's already running.
|
||||
let xhr = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].createInstance(Ci.nsIXMLHttpRequest);
|
||||
xhr.open("DELETE", this.resourceURL + "/run", true);
|
||||
xhr.overrideMimeType("text/plain");
|
||||
xhr.setRequestHeader("Accept", "application/xml; charset=utf8");
|
||||
xhr.setRequestHeader("Authorization", this.token);
|
||||
|
||||
xhr.addEventListener("load", (function() {
|
||||
if (xhr.status == 200) {
|
||||
if (aCallback)
|
||||
aCallback(true);
|
||||
} else {
|
||||
if (aCallback)
|
||||
aCallback(false);
|
||||
}
|
||||
}).bind(this), false);
|
||||
|
||||
xhr.addEventListener("error", (function() {
|
||||
if (aCallback)
|
||||
aCallback(false);
|
||||
}).bind(this), false);
|
||||
|
||||
xhr.send(null);
|
||||
},
|
||||
|
||||
remoteMedia: function remoteMedia(aCallback, aListener) {
|
||||
this.status((aStatus) => {
|
||||
if (aStatus.serviceURL) {
|
||||
if (aCallback) {
|
||||
aCallback(new RemoteMedia(aStatus.serviceURL, aListener, this));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// It can take a few moments for the player app to load. Let's use a small delay
|
||||
// and retry a few times.
|
||||
if (this.statusRetry < STATUS_RETRY_COUNT) {
|
||||
this.statusRetry++;
|
||||
this.statusTimer.initWithCallback(() => {
|
||||
this.remoteMedia(aCallback, aListener);
|
||||
}, STATUS_RETRY_WAIT, Ci.nsITimer.TYPE_ONE_SHOT);
|
||||
} else {
|
||||
// Fail
|
||||
if (aCallback) {
|
||||
aCallback();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/* RemoteMedia provides a wrapper for using WebSockets and Flint protocol to control
|
||||
* the Matchstick media player
|
||||
* See: https://github.com/openflint/openflint.github.io/wiki/Flint%20Protocol%20Docs
|
||||
* See: https://github.com/openflint/flint-receiver-sdk/blob/gh-pages/v1/libs/mediaplayer.js
|
||||
*/
|
||||
function RemoteMedia(aURL, aListener, aApp) {
|
||||
this._active = false;
|
||||
this._status = "uninitialized";
|
||||
|
||||
this.app = aApp;
|
||||
this.listener = aListener;
|
||||
|
||||
this.pingTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
|
||||
|
||||
let uri = Services.io.newURI(aURL, null, null);
|
||||
this.ws = Cc["@mozilla.org/network/protocol;1?name=ws"].createInstance(Ci.nsIWebSocketChannel);
|
||||
this.ws.initLoadInfo(null, // aLoadingNode
|
||||
Services.scriptSecurityManager.getSystemPrincipal(),
|
||||
null, // aTriggeringPrincipal
|
||||
Ci.nsILoadInfo.SEC_NORMAL,
|
||||
Ci.nsIContentPolicy.TYPE_WEBSOCKET);
|
||||
|
||||
this.ws.asyncOpen(uri, aURL, this, null);
|
||||
}
|
||||
|
||||
// Used to give us a small gap between not pinging too often and pinging too late
|
||||
const PING_INTERVAL_BACKOFF = 200;
|
||||
|
||||
RemoteMedia.prototype = {
|
||||
_ping: function _ping() {
|
||||
if (this.app.pingInterval == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
let xhr = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].createInstance(Ci.nsIXMLHttpRequest);
|
||||
xhr.open("GET", this.app.resourceURL, true);
|
||||
xhr.setRequestHeader("Accept", "application/xml; charset=utf8");
|
||||
xhr.setRequestHeader("Authorization", this.app.token);
|
||||
|
||||
xhr.addEventListener("load", () => {
|
||||
if (xhr.status == 200) {
|
||||
this.pingTimer.initWithCallback(() => {
|
||||
this._ping();
|
||||
}, this.app.pingInterval - PING_INTERVAL_BACKOFF, Ci.nsITimer.TYPE_ONE_SHOT);
|
||||
}
|
||||
});
|
||||
|
||||
xhr.send(null);
|
||||
},
|
||||
|
||||
_changeStatus: function _changeStatus(status) {
|
||||
if (this._status != status) {
|
||||
this._status = status;
|
||||
if ("onRemoteMediaStatus" in this.listener) {
|
||||
this.listener.onRemoteMediaStatus(this);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_teardown: function _teardown() {
|
||||
if (!this._active) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Stop any queued ping event
|
||||
this.pingTimer.cancel();
|
||||
|
||||
// Let the listener know we are finished
|
||||
this._active = false;
|
||||
if (this.listener && "onRemoteMediaStop" in this.listener) {
|
||||
this.listener.onRemoteMediaStop(this);
|
||||
}
|
||||
},
|
||||
|
||||
_sendMsg: function _sendMsg(params) {
|
||||
// Convert payload to a string
|
||||
params.payload = JSON.stringify(params.payload);
|
||||
|
||||
try {
|
||||
this.ws.sendMsg(JSON.stringify(params));
|
||||
} catch (e if e.result == Cr.NS_ERROR_NOT_CONNECTED) {
|
||||
// This shouldn't happen unless something gets out of sync with the
|
||||
// connection. Let's make sure we try to cleanup.
|
||||
this._teardown();
|
||||
} catch (e) {
|
||||
log("Send Error: " + e)
|
||||
}
|
||||
},
|
||||
|
||||
get active() {
|
||||
return this._active;
|
||||
},
|
||||
|
||||
get status() {
|
||||
return this._status;
|
||||
},
|
||||
|
||||
shutdown: function shutdown() {
|
||||
this.ws.close(Ci.nsIWebSocketChannel.CLOSE_NORMAL, "shutdown");
|
||||
},
|
||||
|
||||
play: function play() {
|
||||
if (!this._active) {
|
||||
return;
|
||||
}
|
||||
|
||||
let params = {
|
||||
namespace: "urn:flint:org.openflint.fling.media",
|
||||
payload: {
|
||||
type: "PLAY",
|
||||
requestId: "requestId-5",
|
||||
}
|
||||
};
|
||||
|
||||
this._sendMsg(params);
|
||||
},
|
||||
|
||||
pause: function pause() {
|
||||
if (!this._active) {
|
||||
return;
|
||||
}
|
||||
|
||||
let params = {
|
||||
namespace: "urn:flint:org.openflint.fling.media",
|
||||
payload: {
|
||||
type: "PAUSE",
|
||||
requestId: "requestId-4",
|
||||
}
|
||||
};
|
||||
|
||||
this._sendMsg(params);
|
||||
},
|
||||
|
||||
load: function load(aData) {
|
||||
if (!this._active) {
|
||||
return;
|
||||
}
|
||||
|
||||
let params = {
|
||||
namespace: "urn:flint:org.openflint.fling.media",
|
||||
payload: {
|
||||
type: "LOAD",
|
||||
requestId: "requestId-2",
|
||||
media: {
|
||||
contentId: aData.source,
|
||||
contentType: "video/mp4",
|
||||
metadata: {
|
||||
title: "",
|
||||
subtitle: ""
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this._sendMsg(params);
|
||||
},
|
||||
|
||||
onStart: function(aContext) {
|
||||
this._active = true;
|
||||
if (this.listener && "onRemoteMediaStart" in this.listener) {
|
||||
this.listener.onRemoteMediaStart(this);
|
||||
}
|
||||
|
||||
this._ping();
|
||||
},
|
||||
|
||||
onStop: function(aContext, aStatusCode) {
|
||||
// This will be called for internal socket failures and timeouts. Make
|
||||
// sure we cleanup.
|
||||
this._teardown();
|
||||
},
|
||||
|
||||
onAcknowledge: function(aContext, aSize) {},
|
||||
onBinaryMessageAvailable: function(aContext, aMessage) {},
|
||||
|
||||
onMessageAvailable: function(aContext, aMessage) {
|
||||
let msg = JSON.parse(aMessage);
|
||||
if (!msg) {
|
||||
return;
|
||||
}
|
||||
|
||||
let payload = JSON.parse(msg.payload);
|
||||
if (!payload) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle state changes using the player notifications
|
||||
if (payload.type == "MEDIA_STATUS") {
|
||||
let status = payload.status[0];
|
||||
let state = status.playerState.toLowerCase();
|
||||
if (state == "playing") {
|
||||
this._changeStatus("started");
|
||||
} else if (state == "paused") {
|
||||
this._changeStatus("paused");
|
||||
} else if (state == "idle" && "idleReason" in status) {
|
||||
// Make sure we are really finished. IDLE can be sent at other times.
|
||||
let reason = status.idleReason.toLowerCase();
|
||||
if (reason == "finished") {
|
||||
this._changeStatus("completed");
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
onServerClose: function(aContext, aStatusCode, aReason) {
|
||||
// This will be fired from _teardown when we close the websocket, but it
|
||||
// can also be called for other internal socket failures and timeouts. We
|
||||
// make sure the _teardown bails on reentry.
|
||||
this._teardown();
|
||||
}
|
||||
}
|
@ -17,7 +17,6 @@ EXTRA_JS_MODULES += [
|
||||
'JavaAddonManager.jsm',
|
||||
'JNI.jsm',
|
||||
'LightweightThemeConsumer.jsm',
|
||||
'MatchstickApp.jsm',
|
||||
'MediaPlayerApp.jsm',
|
||||
'Messaging.jsm',
|
||||
'MulticastDNS.jsm',
|
||||
|
Loading…
Reference in New Issue
Block a user