202 lines
6.6 KiB
JavaScript
202 lines
6.6 KiB
JavaScript
/* 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";
|
|
|
|
const { classes: Cc, interfaces: Ci, results: Cr, utils: Cu } = Components;
|
|
|
|
Cu.import("resource://gre/modules/ExtensionUtils.jsm");
|
|
Cu.import('resource://gre/modules/Services.jsm');
|
|
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
|
|
|
let { PlatformInfo } = ExtensionUtils;
|
|
|
|
if (PlatformInfo.os == "android" && !Services.prefs.getBoolPref("network.mdns.use_js_fallback")) {
|
|
Cu.import("resource://gre/modules/MulticastDNSAndroid.jsm");
|
|
} else {
|
|
Cu.import("resource://gre/modules/MulticastDNS.jsm");
|
|
}
|
|
|
|
const DNSSERVICEDISCOVERY_CID = Components.ID("{f9346d98-f27a-4e89-b744-493843416480}");
|
|
const DNSSERVICEDISCOVERY_CONTRACT_ID = "@mozilla.org/toolkit/components/mdnsresponder/dns-sd;1";
|
|
const DNSSERVICEINFO_CONTRACT_ID = "@mozilla.org/toolkit/components/mdnsresponder/dns-info;1";
|
|
|
|
function log(aMsg) {
|
|
dump("-*- nsDNSServiceDiscovery.js : " + aMsg + "\n");
|
|
}
|
|
|
|
function generateUuid() {
|
|
var uuidGenerator = Components.classes["@mozilla.org/uuid-generator;1"].
|
|
getService(Ci.nsIUUIDGenerator);
|
|
return uuidGenerator.generateUUID().toString();
|
|
}
|
|
|
|
// Helper class to transform return objects to correct type.
|
|
function ListenerWrapper(aListener, aMdns) {
|
|
this.listener = aListener;
|
|
this.mdns = aMdns;
|
|
|
|
this.discoveryStarting = false;
|
|
this.stopDiscovery = false;
|
|
|
|
this.registrationStarting = false;
|
|
this.stopRegistration = false;
|
|
|
|
this.uuid = generateUuid();
|
|
}
|
|
|
|
ListenerWrapper.prototype = {
|
|
// Helper function for transforming an Object into nsIDNSServiceInfo.
|
|
makeServiceInfo: function (aServiceInfo) {
|
|
let serviceInfo = Cc[DNSSERVICEINFO_CONTRACT_ID].createInstance(Ci.nsIDNSServiceInfo);
|
|
|
|
for (let name of ['host', 'address', 'port', 'serviceName', 'serviceType']) {
|
|
try {
|
|
serviceInfo[name] = aServiceInfo[name];
|
|
} catch (e) {
|
|
// ignore exceptions
|
|
}
|
|
}
|
|
|
|
let attributes;
|
|
try {
|
|
attributes = _toPropertyBag2(aServiceInfo.attributes);
|
|
} catch (err) {
|
|
// Ignore unset attributes in object.
|
|
log("Caught unset attributes error: " + err + " - " + err.stack);
|
|
attributes = Cc['@mozilla.org/hash-property-bag;1']
|
|
.createInstance(Ci.nsIWritablePropertyBag2);
|
|
}
|
|
serviceInfo.attributes = attributes;
|
|
|
|
return serviceInfo;
|
|
},
|
|
|
|
/* transparent types */
|
|
onDiscoveryStarted: function(aServiceType) {
|
|
this.discoveryStarting = false;
|
|
this.listener.onDiscoveryStarted(aServiceType);
|
|
|
|
if (this.stopDiscovery) {
|
|
this.mdns.stopDiscovery(aServiceType, this);
|
|
}
|
|
},
|
|
onDiscoveryStopped: function(aServiceType) {
|
|
this.listener.onDiscoveryStopped(aServiceType);
|
|
},
|
|
onStartDiscoveryFailed: function(aServiceType, aErrorCode) {
|
|
log('onStartDiscoveryFailed: ' + aServiceType + ' (' + aErrorCode + ')');
|
|
this.discoveryStarting = false;
|
|
this.stopDiscovery = true;
|
|
this.listener.onStartDiscoveryFailed(aServiceType, aErrorCode);
|
|
},
|
|
onStopDiscoveryFailed: function(aServiceType, aErrorCode) {
|
|
log('onStopDiscoveryFailed: ' + aServiceType + ' (' + aErrorCode + ')');
|
|
this.listener.onStopDiscoveryFailed(aServiceType, aErrorCode);
|
|
},
|
|
|
|
/* transform types */
|
|
onServiceFound: function(aServiceInfo) {
|
|
this.listener.onServiceFound(this.makeServiceInfo(aServiceInfo));
|
|
},
|
|
onServiceLost: function(aServiceInfo) {
|
|
this.listener.onServiceLost(this.makeServiceInfo(aServiceInfo));
|
|
},
|
|
onServiceRegistered: function(aServiceInfo) {
|
|
this.registrationStarting = false;
|
|
this.listener.onServiceRegistered(this.makeServiceInfo(aServiceInfo));
|
|
|
|
if (this.stopRegistration) {
|
|
this.mdns.unregisterService(aServiceInfo, this);
|
|
}
|
|
},
|
|
onServiceUnregistered: function(aServiceInfo) {
|
|
this.listener.onServiceUnregistered(this.makeServiceInfo(aServiceInfo));
|
|
},
|
|
onServiceResolved: function(aServiceInfo) {
|
|
this.listener.onServiceResolved(this.makeServiceInfo(aServiceInfo));
|
|
},
|
|
|
|
onRegistrationFailed: function(aServiceInfo, aErrorCode) {
|
|
log('onRegistrationFailed: (' + aErrorCode + ')');
|
|
this.registrationStarting = false;
|
|
this.stopRegistration = true;
|
|
this.listener.onRegistrationFailed(this.makeServiceInfo(aServiceInfo), aErrorCode);
|
|
},
|
|
onUnregistrationFailed: function(aServiceInfo, aErrorCode) {
|
|
log('onUnregistrationFailed: (' + aErrorCode + ')');
|
|
this.listener.onUnregistrationFailed(this.makeServiceInfo(aServiceInfo), aErrorCode);
|
|
},
|
|
onResolveFailed: function(aServiceInfo, aErrorCode) {
|
|
log('onResolveFailed: (' + aErrorCode + ')');
|
|
this.listener.onResolveFailed(this.makeServiceInfo(aServiceInfo), aErrorCode);
|
|
}
|
|
};
|
|
|
|
function nsDNSServiceDiscovery() {
|
|
log("nsDNSServiceDiscovery");
|
|
this.mdns = new MulticastDNS();
|
|
}
|
|
|
|
nsDNSServiceDiscovery.prototype = {
|
|
classID: DNSSERVICEDISCOVERY_CID,
|
|
QueryInterface: XPCOMUtils.generateQI([Ci.nsISupportsWeakReference, Ci.nsIDNSServiceDiscovery]),
|
|
|
|
startDiscovery: function(aServiceType, aListener) {
|
|
log("startDiscovery");
|
|
let listener = new ListenerWrapper(aListener, this.mdns);
|
|
listener.discoveryStarting = true;
|
|
this.mdns.startDiscovery(aServiceType, listener);
|
|
|
|
return {
|
|
QueryInterface: XPCOMUtils.generateQI([Ci.nsICancelable]),
|
|
cancel: (function() {
|
|
if (this.discoveryStarting || this.stopDiscovery) {
|
|
this.stopDiscovery = true;
|
|
return;
|
|
}
|
|
this.mdns.stopDiscovery(aServiceType, listener);
|
|
}).bind(listener)
|
|
};
|
|
},
|
|
|
|
registerService: function(aServiceInfo, aListener) {
|
|
log("registerService");
|
|
let listener = new ListenerWrapper(aListener, this.mdns);
|
|
listener.registrationStarting = true;
|
|
this.mdns.registerService(aServiceInfo, listener);
|
|
|
|
return {
|
|
QueryInterface: XPCOMUtils.generateQI([Ci.nsICancelable]),
|
|
cancel: (function() {
|
|
if (this.registrationStarting || this.stopRegistration) {
|
|
this.stopRegistration = true;
|
|
return;
|
|
}
|
|
this.mdns.unregisterService(aServiceInfo, listener);
|
|
}).bind(listener)
|
|
};
|
|
},
|
|
|
|
resolveService: function(aServiceInfo, aListener) {
|
|
log("resolveService");
|
|
this.mdns.resolveService(aServiceInfo, new ListenerWrapper(aListener));
|
|
}
|
|
};
|
|
|
|
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([nsDNSServiceDiscovery]);
|
|
|
|
function _toPropertyBag2(obj)
|
|
{
|
|
if (obj.QueryInterface) {
|
|
return obj.QueryInterface(Ci.nsIPropertyBag2);
|
|
}
|
|
|
|
let result = Cc['@mozilla.org/hash-property-bag;1']
|
|
.createInstance(Ci.nsIWritablePropertyBag2);
|
|
for (let name in obj) {
|
|
result.setPropertyAsAString(name, obj[name]);
|
|
}
|
|
return result;
|
|
}
|