Bug 736114 - Fire an event every 5 seconds containing the signal strength and link speed of the connection. Also add a synchronous API for clients that don't want to wait for the signal. r=cjones DONTBUILD

This commit is contained in:
Blake Kaplan 2012-03-26 18:26:32 +02:00
parent d1bcd8a045
commit cbffc9c65b
3 changed files with 165 additions and 12 deletions

View File

@ -48,18 +48,21 @@ DOMWifiManager.prototype = {
// Maintain this state for synchronous APIs.
this._currentNetwork = null;
this._enabled = true;
this._lastConnectionInfo = null;
const messages = ["WifiManager:setEnabled:Return:OK", "WifiManager:setEnabled:Return:NO",
"WifiManager:getNetworks:Return:OK", "WifiManager:getNetworks:Return:NO",
"WifiManager:associate:Return:OK", "WifiManager:associate:Return:NO",
"WifiManager:onconnecting", "WifiManager:onassociate",
"WifiManager:onconnect", "WifiManager:ondisconnect"];
"WifiManager:onconnect", "WifiManager:ondisconnect",
"WifiManager:connectionInfoUpdate"];
this.initHelper(aWindow, messages);
this._mm = Cc["@mozilla.org/childprocessmessagemanager;1"].getService(Ci.nsISyncMessageSender);
var state = this._mm.sendSyncMessage("WifiManager:getState");
this._currentNetwork = state[0].network;
this._enabled = state[0].enabled;
var state = this._mm.sendSyncMessage("WifiManager:getState")[0];
this._currentNetwork = state.network;
this._lastConnectionInfo = state.connectionInfo;
this._enabled = state.enabled;
},
uninit: function() {
@ -67,6 +70,7 @@ DOMWifiManager.prototype = {
this._onAssociate = null;
this._onConnect = null;
this._onDisconnect = null;
this._onConnectionInfoUpdate = null;
},
_sendMessageForRequest: function(name, data, request) {
@ -132,6 +136,12 @@ DOMWifiManager.prototype = {
case "WifiManager:ondisconnect":
this._fireOnDisconnect(this._currentNetwork);
this._currentNetwork = null;
this._lastConnectionInfo = null;
break;
case "WifiManager:connectionInfoUpdate":
this._lastConnectionInfo = msg;
this._fireConnectionInfoUpdate(msg);
break;
}
},
@ -152,8 +162,17 @@ DOMWifiManager.prototype = {
},
_fireOnDisconnect: function onDisconnect(network) {
if (this._onDisconnect) {
if (this._onDisconnect)
this._onDisconnect.handleEvent(new WifiStateChangeEvent(network));
},
_fireConnectionInfoUpdate: function connectionInfoUpdate(info) {
if (this._onConnectionInfoUpdate) {
var evt = new ConnectionInfoUpdate(this._currentNetwork,
info.signalStrength,
info.relSignalStrength,
info.linkSpeed);
this._onConnectionInfoUpdate(evt);
}
},
@ -194,6 +213,12 @@ DOMWifiManager.prototype = {
return this._currentNetwork;
},
get connectionInfo() {
if (!this._hasPrivileges)
throw new Components.Exception("Denied", Cr.NS_ERROR_FAILURE);
return this._lastConnectionInfo;
},
set onconnecting(callback) {
if (!this._hasPrivileges)
throw new Components.Exception("Denied", Cr.NS_ERROR_FAILURE);
@ -216,6 +241,12 @@ DOMWifiManager.prototype = {
if (!this._hasPrivileges)
throw new Components.Exception("Denied", Cr.NS_ERROR_FAILURE);
this._onDisconnect = callback;
},
set connectionInfoUpdate(callback) {
if (!this._hasPrivileges)
throw new Components.Exception("Denied", Cr.NS_ERROR_FAILURE);
this._onConnectionInfoUpdate = callback;
}
};
@ -233,6 +264,23 @@ WifiStateChangeEvent.prototype = {
classDescription: "Wifi State Change Event"})
};
function ConnectionInfoUpdate(network, signalStrength, relSignalStrength, linkSpeed) {
this.network = network;
this.signalStrength = signalStrength;
this.relSignalStrength = relSignalStrength;
this.linkSpeed = linkSpeed;
}
ConnectionInfoUpdate.prototype = {
QueryInterface: XPCOMUtils.generateQI([Ci.nsIDOMWifiConnectionInfoEvent]),
classInfo: XPCOMUtils.generateCI({classID: Components.ID("{aba4c481-7ea2-464a-b14c-7254a5c99454}"),
contractID: "@mozilla.org/wifi/connectioninfo-event;1",
interfaces: [Ci.nsIDOMWifiConnectionInfoEvent],
flags: Ci.nsIClassInfo.DOM_OBJECT,
classDescription: "Wifi Connection Info Event"})
};
const NSGetFactory = XPCOMUtils.generateNSGetFactory([DOMWifiManager]);
let debug;

View File

@ -300,7 +300,7 @@ var WifiManager = (function() {
if (reply != "OK") {
// Format is: <SSID> rssi XX". SSID can contain spaces.
var offset = reply.lastIndexOf("rssi ");
if (offset != -1)
if (offset !== -1)
rssi = reply.substr(offset + 5) | 0;
}
}
@ -319,7 +319,7 @@ var WifiManager = (function() {
function getLinkSpeedCommand(callback) {
doStringCommand("DRIVER LINKSPEED", function(reply) {
if (reply)
reply = reply.split()[1] | 0; // Format: LinkSpeed XX
reply = reply.split(" ")[1] | 0; // Format: LinkSpeed XX
callback(reply);
});
}
@ -1035,6 +1035,8 @@ var WifiManager = (function() {
setScanModeCommand(mode === "active", callback);
}
manager.scan = scanCommand;
manager.getRssiApprox = getRssiApproxCommand;
manager.getLinkSpeed = getLinkSpeedCommand;
return manager;
})();
@ -1131,6 +1133,9 @@ function WifiWorker() {
this.currentNetwork = null;
this._lastConnectionInfo = null;
this._connectionInfoTimer = null;
// Given a connection status network, takes a network from
// self.configuredNetworks and prepares it for the DOM.
netToDOM = function(net) {
@ -1234,6 +1239,12 @@ function WifiWorker() {
WifiManager.onstatechange = function() {
debug("State change: " + this.prevState + " -> " + this.state);
if (self._connectionInfoTimer &&
this.state !== "CONNECTED" &&
this.state !== "COMPLETED") {
self._stopConnectionInfoTimer();
}
if (this.state === "DORMANT") {
// The dormant state is a bad state to be in since we won't
// automatically connect. Try to knock us out of it. We only
@ -1273,16 +1284,17 @@ function WifiWorker() {
WifiManager.getNetworkConfiguration(self.currentNetwork, function(){});
}
self._fireEvent("onassociate", netToDOM(self.currentNetwork));
self._startConnectionInfoTimer();
self._fireEvent("onassociate", { network: netToDOM(self.currentNetwork) });
} else if (this.state === "DISCONNECTED") {
self._fireEvent("ondisconnect");
self._fireEvent("ondisconnect", {});
self.currentNetwork = null;
}
};
WifiManager.ondhcpconnected = function() {
if (this.info)
self._fireEvent("onconnect", netToDOM(self.currentNetwork));
self._fireEvent("onconnect", { network: netToDOM(self.currentNetwork) });
else
WifiManager.disconnect(function(){});
};
@ -1387,10 +1399,66 @@ WifiWorker.prototype = {
}
},
_startConnectionInfoTimer: function() {
if (this._connectionInfoTimer)
return;
var self = this;
function getConnectionInformation() {
WifiManager.getRssiApprox(function(rssi) {
// See comments in calculateSignal for information about this.
if (rssi > 0)
rssi -= 256;
if (rssi <= MIN_RSSI)
rssi = MIN_RSSI;
else if (rssi >= MAX_RSSI)
rssi = MAX_RSSI;
WifiManager.getLinkSpeed(function(linkspeed) {
let info = { signalStrength: rssi,
relSignalStrength: calculateSignal(rssi),
linkSpeed: linkspeed };
let last = self._lastConnectionInfo;
// Only fire the event if the link speed changed or the signal
// strength changed by more than 10%.
function tensPlace(percent) ((percent / 10) | 0)
if (last && last.linkSpeed === info.linkSpeed &&
tensPlace(last.relSignalStrength) === tensPlace(info.relSignalStrength)) {
return;
}
self._lastConnectionInfo = info;
self._fireEvent("connectionInfoUpdate", info);
});
});
}
// Prime our _lastConnectionInfo immediately and fire the event at the
// same time.
getConnectionInformation();
// Now, set up the timer for regular updates.
this._connectionInfoTimer =
Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
this._connectionInfoTimer.init(getConnectionInformation, 5000,
Ci.nsITimer.TYPE_REPEATING_SLACK);
},
_stopConnectionInfoTimer: function() {
if (!this._connectionInfoTimer)
return;
this._connectionInfoTimer.cancel();
this._connectionInfoTimer = null;
this._lastConnectionInfo = null;
},
// nsIWifi
_fireEvent: function(message, data) {
this._mm.sendAsyncMessage("WifiManager:" + message, { network: data });
this._mm.sendAsyncMessage("WifiManager:" + message, data);
},
_sendMessage: function(message, success, data, rid, mid) {
@ -1413,6 +1481,7 @@ WifiWorker.prototype = {
case "WifiManager:getState": {
let net = this.currentNetwork ? netToDOM(this.currentNetwork) : null;
return { network: net,
connectionInfo: this._lastConnectionInfo,
enabled: WifiManager.state !== "UNINITIALIZED", };
}
}

View File

@ -47,7 +47,7 @@ interface nsIWifi : nsISupports {
void shutdown();
};
[scriptable, uuid(1509221f-470e-4445-b476-88e74fd5c617)]
[scriptable, uuid(7df14510-f58b-4c9a-9e35-a39a94255941)]
interface nsIDOMWifiManager : nsISupports {
/**
* TODO Remove in favor of a settings API.
@ -91,6 +91,13 @@ interface nsIDOMWifiManager : nsISupports {
*/
readonly attribute jsval connectedNetwork;
/**
* A connectionInformation object with the same information found in an
* nsIDOMWifiConnectionInfoEvent (but without the network).
* If we are not currently connected to a network, this will be null.
*/
readonly attribute jsval connectionInformation;
/**
* These four functions serve as state notification listeners.
* onconnecting: Fires when we start the process of connecting to a
@ -108,6 +115,12 @@ interface nsIDOMWifiManager : nsISupports {
attribute nsIDOMEventListener onassociate;
attribute nsIDOMEventListener onconnect;
attribute nsIDOMEventListener ondisconnect;
/**
* An event listener that is called with information about the signal
* strength and link speed every 5 seconds.
*/
attribute nsIDOMEventListener connectionInfoUpdate;
};
[scriptable, uuid(4674c6f1-ea64-44db-ac2f-e7bd6514dfd6)]
@ -118,3 +131,26 @@ interface nsIDOMWifiStateChangeEvent : nsIDOMEvent {
*/
readonly attribute jsval network;
};
[scriptable, uuid(5c9ee332-dd98-4227-b7fc-768418fd50e3)]
interface nsIDOMWifiConnectionInfoEvent : nsIDOMEvent {
/**
* Network object with an SSID field.
*/
readonly attribute jsval network;
/**
* Strength of the signal to network, in dBm between -55 and -100 dBm.
*/
readonly attribute short signalStrength;
/**
* Relative signal strength between 0 and 100.
*/
readonly attribute short relSignalStrength;
/**
* Link spead in Mb/s.
*/
readonly attribute long linkSpeed;
};