Bug 740079 - Provide a synchronous API to get precise information about the current connection status. r=cjones f=kaze
authorBlake Kaplan <mrbkap@gmail.com>
Mon, 09 Apr 2012 11:32:17 +0800
changeset 95066 14084207e9d112e399e553d16cf4aa21ff2c1e91
parent 95065 0066df252596904f0418d262117dec893e07e2de
child 95067 686e5bcf747ba2fc7b5e4babb791114ac734c5e3
child 97505 18b6a2def113996466fdc22734bce1555e717c47
push id886
push userlsblakk@mozilla.com
push dateMon, 04 Jun 2012 19:57:52 +0000
treeherdermozilla-beta@bbd8d5efd6d1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerscjones
bugs740079
milestone14.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 740079 - Provide a synchronous API to get precise information about the current connection status. r=cjones f=kaze
dom/wifi/DOMWifiManager.js
dom/wifi/WifiWorker.js
dom/wifi/nsIWifi.idl
--- a/dom/wifi/DOMWifiManager.js
+++ b/dom/wifi/DOMWifiManager.js
@@ -42,16 +42,17 @@ DOMWifiManager.prototype = {
                  Ci.nsIPermissionManager.ALLOW_ACTION :
                  Services.perms.testExactPermission(principal.URI, "wifi-manage");
 
     // Only pages with perm set can use the wifi manager.
     this._hasPrivileges = perm == Ci.nsIPermissionManager.ALLOW_ACTION;
 
     // Maintain this state for synchronous APIs.
     this._currentNetwork = null;
+    this._connectionStatus = "disconnected";
     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:forget:Return:OK", "WifiManager:forget:Return:NO",
                       "WifiManager:onconnecting", "WifiManager:onassociate",
@@ -60,20 +61,22 @@ DOMWifiManager.prototype = {
     this.initHelper(aWindow, messages);
     this._mm = Cc["@mozilla.org/childprocessmessagemanager;1"].getService(Ci.nsISyncMessageSender);
 
     var state = this._mm.sendSyncMessage("WifiManager:getState")[0];
     if (state) {
       this._currentNetwork = state.network;
       this._lastConnectionInfo = state.connectionInfo;
       this._enabled = state.enabled;
+      this._connectionStatus = state.status;
     } else {
       this._currentNetwork = null;
       this._lastConnectionInfo = null;
-      this._enabled = null;
+      this._enabled = false;
+      this._connectionStatus = "disconnected";
     }
   },
 
   uninit: function() {
     this._onConnecting = null;
     this._onAssociate = null;
     this._onConnect = null;
     this._onDisconnect = null;
@@ -132,32 +135,36 @@ DOMWifiManager.prototype = {
 
       case "WifiManager:forget:Return:NO":
         request = this.takeRequest(msg.rid);
         Services.DOMRequest.fireError(request, msg.data);
         break;
 
       case "WifiManager:onconnecting":
         this._currentNetwork = msg.network;
+        this._connectionStatus = "connecting";
         this._fireOnConnecting(msg.network);
         break;
 
       case "WifiManager:onassociate":
         this._currentNetwork = msg.network;
+        this._connectionStatus = "associated";
         this._fireOnAssociate(msg.network);
         break;
 
       case "WifiManager:onconnect":
         this._currentNetwork = msg.network;
+        this._connectionStatus = "connected";
         this._fireOnConnect(msg.network);
         break;
 
       case "WifiManager:ondisconnect":
         this._fireOnDisconnect(this._currentNetwork);
         this._currentNetwork = null;
+        this._connectionStatus = "disconnected";
         this._lastConnectionInfo = null;
         break;
 
       case "WifiManager:connectionInfoUpdate":
         this._lastConnectionInfo = msg;
         this._fireConnectionInfoUpdate(msg);
         break;
     }
@@ -227,20 +234,20 @@ DOMWifiManager.prototype = {
   },
 
   get enabled() {
     if (!this._hasPrivileges)
       throw new Components.Exception("Denied", Cr.NS_ERROR_FAILURE);
     return this._enabled;
   },
 
-  get connectedNetwork() {
+  get connection() {
     if (!this._hasPrivileges)
       throw new Components.Exception("Denied", Cr.NS_ERROR_FAILURE);
-    return this._currentNetwork;
+    return { status: this._connectionStatus, network: this._currentNetwork };
   },
 
   get connectionInfo() {
     if (!this._hasPrivileges)
       throw new Components.Exception("Denied", Cr.NS_ERROR_FAILURE);
     return this._lastConnectionInfo;
   },
 
--- a/dom/wifi/WifiWorker.js
+++ b/dom/wifi/WifiWorker.js
@@ -1021,16 +1021,17 @@ var WifiManager = (function() {
   manager.getMacAddress = getMacAddressCommand;
   manager.getScanResults = scanResultsCommand;
   manager.setScanMode = function(mode, callback) {
     setScanModeCommand(mode === "active", callback);
   }
   manager.scan = scanCommand;
   manager.getRssiApprox = getRssiApproxCommand;
   manager.getLinkSpeed = getLinkSpeedCommand;
+  manager.getDhcpInfo = function() { return dhcpInfo; }
   return manager;
 })();
 
 function getKeyManagement(flags) {
   var types = [];
   if (!flags)
     return types;
 
@@ -1369,16 +1370,37 @@ function WifiWorker() {
         WifiManager.start();
       else
         debug("Couldn't start Wifi");
     });
 
   debug("Wifi starting");
 }
 
+function translateState(state) {
+  switch (state) {
+    case "INTERFACE_DISABLED":
+    case "INACTIVE":
+    case "SCANNING":
+    case "DISCONNECTED":
+    default:
+      return "disconnected";
+
+    case "AUTHENTICATING":
+    case "ASSOCIATING":
+    case "ASSOCIATED":
+    case "FOUR_WAY_HANDSHAKE":
+    case "GROUP_HANDSHAKE":
+      return "connecting";
+
+    case "COMPLETED":
+      return WifiManager.getDhcpInfo() ? "connected" : "associated";
+  }
+}
+
 WifiWorker.prototype = {
   classID:   WIFIWORKER_CID,
   classInfo: XPCOMUtils.generateCI({classID: WIFIWORKER_CID,
                                     contractID: WIFIWORKER_CONTRACTID,
                                     classDescription: "WifiWorker",
                                     interfaces: [Ci.nsIWorkerHolder,
                                                  Ci.nsIWifi]}),
 
@@ -1578,17 +1600,18 @@ WifiWorker.prototype = {
         break;
       case "WifiManager:forget":
         this.forget(msg.data, msg.rid, msg.mid);
         break;
       case "WifiManager:getState": {
         let net = this.currentNetwork ? netToDOM(this.currentNetwork) : null;
         return { network: net,
                  connectionInfo: this._lastConnectionInfo,
-                 enabled: WifiManager.state !== "UNINITIALIZED", };
+                 enabled: WifiManager.state !== "UNINITIALIZED",
+                 status: translateState(WifiManager.state) };
       }
     }
   },
 
   getNetworks: function(rid, mid) {
     const message = "WifiManager:getNetworks:Return";
     if (WifiManager.state === "UNINITIALIZED") {
       this._sendMessage(message, false, "Wifi is disabled", rid, mid);
--- a/dom/wifi/nsIWifi.idl
+++ b/dom/wifi/nsIWifi.idl
@@ -94,19 +94,24 @@ interface nsIDOMWifiManager : nsISupport
 
     /**
      * TODO Remove in favor of a settings API.
      * Returns whether or not wifi is currently enabled.
      */
     readonly attribute boolean enabled;
 
     /**
-     * A network object describing the currently connected network.
+     * An non-null object containing the following information:
+     *  - status ("disconnected", "connecting", "associated", "connected")
+     *  - network
+     *
+     *  Note that the object returned is read only. Any changes required must
+     *  be done by calling other APIs.
      */
-    readonly attribute jsval connectedNetwork;
+    readonly attribute jsval connection;
 
     /**
      * 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;