Bug 1016785 - Add more structured filtering to SSDP r=wesj

This commit is contained in:
Mark Finkle 2014-06-04 15:25:07 -04:00
parent 8a220c33ff
commit 909a1747e2
3 changed files with 74 additions and 9 deletions

View File

@ -24,13 +24,22 @@ function discovery_observer(subject, topic, data) {
run_next_test();
};
var testTarget = {
target: "test:service",
factory: function(service) { /* dummy */ }
};
add_test(function test_default() {
do_register_cleanup(function cleanup() {
SimpleServiceDiscovery.unregisterTarget(testTarget);
Services.obs.removeObserver(discovery_observer, "ssdp-service-found");
});
Services.obs.addObserver(discovery_observer, "ssdp-service-found", false);
// We need to register a target or processService will ignore us
SimpleServiceDiscovery.registerTarget(testTarget);
// Create a pretend service
let service = {
location: "http://mochi.test:8888/tests/robocop/simpleservice.xml",

View File

@ -3,6 +3,16 @@
* You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
// Define service targets. We should consider moving these to their respective
// JSM files, but we left them here to allow for better lazy JSM loading.
var rokuTarget = {
target: "roku:ecp",
factory: function(aService) {
Cu.import("resource://gre/modules/RokuApp.jsm");
return new RokuApp(aService);
}
};
var CastingApps = {
_castMenuId: -1,
@ -11,11 +21,8 @@ var CastingApps = {
return;
}
// Register a service target
SimpleServiceDiscovery.registerTarget("roku:ecp", function(aService) {
Cu.import("resource://gre/modules/RokuApp.jsm");
return new RokuApp(aService);
});
// Register targets
SimpleServiceDiscovery.registerTarget(rokuTarget);
// Search for devices continuously every 120 seconds
SimpleServiceDiscovery.search(120 * 1000);
@ -252,6 +259,10 @@ var CastingApps = {
},
_findCastableVideo: function _findCastableVideo(aBrowser) {
if (!aBrowser) {
return null;
}
// Scan for a <video> being actively cast. Also look for a castable <video>
// on the page.
let castableVideo = null;
@ -451,4 +462,3 @@ var CastingApps = {
}
}
};

View File

@ -225,10 +225,28 @@ var SimpleServiceDiscovery = {
}
},
registerTarget: function registerTarget(aTarget, aAppFactory) {
registerTarget: function registerTarget(aTarget) {
// We must have "target" and "factory" defined
if (!("target" in aTarget) || !("factory" in aTarget)) {
// Fatal for registration
throw "Registration requires a target and a location";
}
// Only add if we don't already know about this target
if (!this._targets.has(aTarget)) {
this._targets.set(aTarget, { target: aTarget, factory: aAppFactory });
if (!this._targets.has(aTarget.target)) {
this._targets.set(aTarget.target, aTarget);
}
},
unregisterTarget: function unregisterTarget(aTarget) {
// We must have "target" and "factory" defined
if (!("target" in aTarget) || !("factory" in aTarget)) {
return;
}
// Only remove if we know about this target
if (this._targets.has(aTarget.target)) {
this._targets.delete(aTarget.target);
}
},
@ -260,6 +278,29 @@ var SimpleServiceDiscovery = {
return array;
},
// Returns false if the service does not match the target's filters
_filterService: function _filterService(aService) {
let target = this._targets.get(aService.target);
if (!target) {
return false;
}
// If we have no filter, everything passes
if (!("filters" in target)) {
return true;
}
// If any filter fails, the service fails
let filters = target.filters;
for (let filter in filters) {
if (filter in aService && aService[filter] != filters[filter]) {
return false;
}
}
return true;
},
_processService: function _processService(aService) {
// Use the REST api to request more information about this service
let xhr = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].createInstance(Ci.nsIXMLHttpRequest);
@ -278,6 +319,11 @@ var SimpleServiceDiscovery = {
aService.manufacturer = doc.querySelector("manufacturer").textContent;
aService.modelName = doc.querySelector("modelName").textContent;
// Filter out services that do not match the target filter
if (!this._filterService(aService)) {
return;
}
// Only add and notify if we don't already know about this service
if (!this._services.has(aService.uuid)) {
this._services.set(aService.uuid, aService);