Bug 787552 - Expose the IP address and MAC address to content. r=vchang f=kaze
authorBlake Kaplan <mrbkap@gmail.com>
Thu, 27 Sep 2012 14:14:06 -0400
changeset 108440 c4f422d91514a38474bd47e5fc3ba184597da970
parent 108439 1da958ae4a001bc064a546961ba851a720edb07d
child 108441 bbfb9d9241e4fb0b2caa01317fd338596daf42ae
push id82
push usershu@rfrn.org
push dateFri, 05 Oct 2012 13:20:22 +0000
reviewersvchang
bugs787552
milestone18.0a1
Bug 787552 - Expose the IP address and MAC address to content. r=vchang f=kaze
content/events/src/nsDOMWifiEvent.cpp
content/events/src/nsDOMWifiEvent.h
dom/interfaces/events/nsIWifiEventInits.idl
dom/wifi/DOMWifiManager.js
dom/wifi/WifiWorker.js
dom/wifi/nsIWifi.idl
--- a/content/events/src/nsDOMWifiEvent.cpp
+++ b/content/events/src/nsDOMWifiEvent.cpp
@@ -124,44 +124,54 @@ nsDOMMozWifiConnectionInfoEvent::GetRelS
 NS_IMETHODIMP
 nsDOMMozWifiConnectionInfoEvent::GetLinkSpeed(int32_t* aLinkSpeed)
 {
   *aLinkSpeed = mLinkSpeed;
   return NS_OK;
 }
 
 NS_IMETHODIMP
+nsDOMMozWifiConnectionInfoEvent::GetIpAddress(nsAString& aIpAddress)
+{
+    aIpAddress = mIpAddress;
+    return NS_OK;
+}
+
+NS_IMETHODIMP
 nsDOMMozWifiConnectionInfoEvent::InitMozWifiConnectionInfoEvent(const nsAString& aType,
                                                                 bool aCanBubble,
                                                                 bool aCancelable,
                                                                 nsIVariant *aNetwork,
                                                                 int16_t aSignalStrength,
                                                                 int16_t aRelSignalStrength,
-                                                                int32_t aLinkSpeed)
+                                                                int32_t aLinkSpeed,
+                                                                const nsAString &aIpAddress)
 {
   nsresult rv = nsDOMEvent::InitEvent(aType, aCanBubble, aCancelable);
   NS_ENSURE_SUCCESS(rv, rv);
 
   mNetwork = aNetwork;
   mSignalStrength = aSignalStrength;
   mRelSignalStrength = aRelSignalStrength;
   mLinkSpeed = aLinkSpeed;
+  mIpAddress = aIpAddress;
 
   return NS_OK;
 }
 
 nsresult
 nsDOMMozWifiConnectionInfoEvent::InitFromCtor(const nsAString& aType,
                                               JSContext* aCx, jsval* aVal)
 {
   mozilla::dom::MozWifiConnectionInfoEventInit d;
   nsresult rv = d.Init(aCx, aVal);
   NS_ENSURE_SUCCESS(rv, rv);
   return InitMozWifiConnectionInfoEvent(aType, d.bubbles, d.cancelable, d.network,
-                                        d.signalStrength, d.relSignalStrength, d.linkSpeed);
+                                        d.signalStrength, d.relSignalStrength, d.linkSpeed,
+                                        d.ipAddress);
 }
 
 nsresult
 NS_NewDOMMozWifiConnectionInfoEvent(nsIDOMEvent** aInstancePtrResult,
                                     nsPresContext* aPresContext,
                                     nsEvent* aEvent) 
 {
   nsDOMMozWifiConnectionInfoEvent* e = new nsDOMMozWifiConnectionInfoEvent(aPresContext, aEvent);
--- a/content/events/src/nsDOMWifiEvent.h
+++ b/content/events/src/nsDOMWifiEvent.h
@@ -11,17 +11,17 @@
 #include "nsDOMEvent.h"
 
 class nsDOMMozWifiStatusChangeEvent : public nsDOMEvent,
                                    public nsIDOMMozWifiStatusChangeEvent
 {
 public:
   nsDOMMozWifiStatusChangeEvent(nsPresContext* aPresContext, nsEvent* aEvent)
     : nsDOMEvent(aPresContext, aEvent) {}
-                     
+
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsDOMMozWifiStatusChangeEvent, nsDOMEvent)
   // Forward to base class
   NS_FORWARD_TO_NSDOMEVENT
 
   NS_DECL_NSIDOMMOZWIFISTATUSCHANGEEVENT
 
   virtual nsresult InitFromCtor(const nsAString& aType,
@@ -32,26 +32,27 @@ private:
 };
 
 class nsDOMMozWifiConnectionInfoEvent : public nsDOMEvent,
                                         public nsIDOMMozWifiConnectionInfoEvent
 {
 public:
   nsDOMMozWifiConnectionInfoEvent(nsPresContext* aPresContext, nsEvent* aEvent)
     : nsDOMEvent(aPresContext, aEvent) {}
-                     
+
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsDOMMozWifiConnectionInfoEvent, nsDOMEvent)
   // Forward to base class
   NS_FORWARD_TO_NSDOMEVENT
 
   NS_DECL_NSIDOMMOZWIFICONNECTIONINFOEVENT
 
   virtual nsresult InitFromCtor(const nsAString& aType,
                                 JSContext* aCx, jsval* aVal);
 private:
   nsCOMPtr<nsIVariant> mNetwork;
   int16_t mSignalStrength;
   int16_t mRelSignalStrength;
   int32_t mLinkSpeed;
+  nsString mIpAddress;
 };
 
 #endif // nsDOMWifiEvent_h__
--- a/dom/interfaces/events/nsIWifiEventInits.idl
+++ b/dom/interfaces/events/nsIWifiEventInits.idl
@@ -15,9 +15,10 @@ dictionary MozWifiStatusChangeEventInit 
 };
 
 dictionary MozWifiConnectionInfoEventInit : EventInit
 {
   nsIVariant network;
   short signalStrength;
   short relSignalStrength;
   long linkSpeed;
+  DOMString ipAddress;
 };
--- a/dom/wifi/DOMWifiManager.js
+++ b/dom/wifi/DOMWifiManager.js
@@ -91,21 +91,23 @@ DOMWifiManager.prototype = {
     var state = this._mm.sendSyncMessage("WifiManager:getState")[0];
     if (state) {
       this._currentNetwork = state.network;
       if (this._currentNetwork)
         exposeCurrentNetwork(this._currentNetwork);
       this._lastConnectionInfo = state.connectionInfo;
       this._enabled = state.enabled;
       this._connectionStatus = state.status;
+      this._macAddress = state.macAddress;
     } else {
       this._currentNetwork = null;
       this._lastConnectionInfo = null;
       this._enabled = false;
       this._connectionStatus = "disconnected";
+      this._macAddress = "";
     }
   },
 
   uninit: function() {
     this._onStatusChange = null;
     this._onConnectionInfoUpdate = null;
     this._onEnabled = null;
     this._onDisabled = null;
@@ -261,17 +263,18 @@ DOMWifiManager.prototype = {
 
   _fireConnectionInfoUpdate: function connectionInfoUpdate(info) {
     if (this._onConnectionInfoUpdate) {
       debug("ConnectionInfoEvent");
       var evt = new this._window.MozWifiConnectionInfoEvent("connectionInfoEvent",
                                                             { network: this._currentNetwork,
                                                               signalStrength: info.signalStrength,
                                                               relSignalStrength: info.relSignalStrength,
-                                                              linkSpeed: info.linkSpeed
+                                                              linkSpeed: info.linkSpeed,
+                                                              ipAddress: info.ipAddress,
                                                             });
       this._onConnectionInfoUpdate.handleEvent(evt);
     }
   },
 
   _fireEnabledOrDisabled: function enabledDisabled(enabled) {
     var handler = enabled ? this._onEnabled : this._onDisabled;
     if (handler) {
@@ -322,16 +325,22 @@ DOMWifiManager.prototype = {
   },
 
   get enabled() {
     if (!this._hasPrivileges)
       throw new Components.Exception("Denied", Cr.NS_ERROR_FAILURE);
     return this._enabled;
   },
 
+  get macAddress() {
+    if (!this._hasPrivileges)
+      throw new Components.Exception("Denied", Cr.NS_ERROR_FAILURE);
+    return this._macAddress;
+  },
+
   get connection() {
     if (!this._hasPrivileges)
       throw new Components.Exception("Denied", Cr.NS_ERROR_FAILURE);
     return exposeReadOnly({ status: this._connectionStatus,
                             network: this._currentNetwork });
   },
 
   get connectionInformation() {
--- a/dom/wifi/WifiWorker.js
+++ b/dom/wifi/WifiWorker.js
@@ -1403,16 +1403,17 @@ function WifiWorker() {
   // lists networks known to the wpa_supplicant. The SSID field (and other
   // fields) are quoted for ease of use with WifiManager commands.
   // Note that we don't have to worry about escaping embedded quotes since in
   // all cases, the supplicant will take the last quotation that we pass it as
   // the end of the string.
   this.configuredNetworks = Object.create(null);
 
   this.currentNetwork = null;
+  this.ipAddress = "";
 
   this._lastConnectionInfo = null;
   this._connectionInfoTimer = null;
   this._reconnectOnDisconnect = false;
 
   // A list of requests to turn wifi on or off.
   this._stateRequests = [];
 
@@ -1481,16 +1482,17 @@ function WifiWorker() {
     return net;
   };
 
   WifiManager.onsupplicantconnection = function() {
     debug("Connected to supplicant");
     WifiManager.enabled = true;
     self._updateWifiSetting(true);
     WifiManager.getMacAddress(function (mac) {
+      self.macAddress = mac;
       debug("Got mac: " + mac);
     });
 
     self._reloadConfiguredNetworks(function(ok) {
       // Prime this.networks.
       if (!ok)
         return;
       self.waitForScan(function firstScan() {});
@@ -1602,16 +1604,17 @@ function WifiWorker() {
         self._startConnectionInfoTimer();
         self._fireEvent("onassociate", { network: netToDOM(self.currentNetwork) });
         break;
       case "CONNECTED":
         break;
       case "DISCONNECTED":
         self._fireEvent("ondisconnect", {});
         self.currentNetwork = null;
+        self.ipAddress = "";
 
         WifiManager.connectionDropped(function() {
           // We've disconnected from a network because of a call to forgetNetwork.
           // Reconnect to the next available network (if any).
           if (self._reconnectOnDisconnect) {
             self._reconnectOnDisconnect = false;
             WifiManager.reconnect(function(){});
           }
@@ -1651,16 +1654,23 @@ function WifiWorker() {
       WifiNetworkInterface.broadcast = this.info.broadcast_str;
       WifiNetworkInterface.gateway = this.info.gateway_str;
       WifiNetworkInterface.dns1 = this.info.dns1_str;
       WifiNetworkInterface.dns2 = this.info.dns2_str;
       Services.obs.notifyObservers(WifiNetworkInterface,
                                    kNetworkInterfaceStateChangedTopic,
                                    null);
 
+      self.ipAddress = this.info.ipaddr_str;
+
+      // We start the connection information timer when we associate, but
+      // don't have our IP address until here. Make sure that we fire a new
+      // connectionInformation event with the IP address the next time the
+      // timer fires.
+      self._lastConnectionInfo = null;
       self._fireEvent("onconnect", { network: netToDOM(self.currentNetwork) });
     } else {
       WifiManager.reassociate(function(){});
     }
   };
 
   WifiManager.onscanresultsavailable = function() {
     if (self.wantScanResults.length === 0) {
@@ -1819,17 +1829,18 @@ WifiWorker.prototype = {
           rssi -= 256;
         if (rssi <= MIN_RSSI)
           rssi = MIN_RSSI;
         else if (rssi >= MAX_RSSI)
           rssi = MAX_RSSI;
 
         let info = { signalStrength: rssi,
                      relSignalStrength: calculateSignal(rssi),
-                     linkSpeed: linkspeed };
+                     linkSpeed: linkspeed,
+                     ipAddress: self.ipAddress };
         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)) {
@@ -2011,17 +2022,18 @@ WifiWorker.prototype = {
 
         if (i === this._domManagers.length) {
           this._domManagers.push({ manager: msg.manager, count: 1 });
         }
 
         return { network: net,
                  connectionInfo: this._lastConnectionInfo,
                  enabled: WifiManager.enabled,
-                 status: translateState(WifiManager.state) };
+                 status: translateState(WifiManager.state),
+                 macAddress: this.macAddress };
       }
       case "WifiManager:managerFinished": {
         for (let i = 0; i < this._domManagers.length; ++i) {
           let obj = this._domManagers[i];
           if (obj.manager === msg.manager) {
             if (--obj.count === 0) {
               this._domManagers.splice(i, 1);
             }
--- a/dom/wifi/nsIWifi.idl
+++ b/dom/wifi/nsIWifi.idl
@@ -12,17 +12,17 @@ interface nsIVariant;
 interface nsIWifi : nsISupports
 {
     /**
      * Shutdown the wifi system.
      */
     void shutdown();
 };
 
-[scriptable, uuid(e3a967e0-015e-11e2-a21f-0800200c9a66)]
+[scriptable, uuid(65286912-141e-4aec-ba48-cb7d74851fd8)]
 interface nsIDOMWifiManager : nsISupports
 {
     /**
      * Returns the list of currently available networks as well as the list of
      * currently configured networks.
      * onsuccess: We have obtained the current list of networks. request.value
      *            is an object whose property names are SSIDs and values are
      *            network objects.
@@ -77,16 +77,21 @@ interface nsIDOMWifiManager : nsISupport
     nsIDOMDOMRequest setPowerSavingMode(in boolean enabled);
 
     /**
      * Returns whether or not wifi is currently enabled.
      */
     readonly attribute boolean enabled;
 
     /**
+     * Returns the MAC address of the wifi adapter.
+     */
+    readonly attribute DOMString macAddress;
+
+    /**
      * 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 connection;
@@ -149,17 +154,17 @@ interface nsIDOMMozWifiStatusChangeEvent
 
     [noscript] void initMozWifiStatusChangeEvent(in DOMString aType,
                                                  in boolean aCanBubble,
                                                  in boolean aCancelable,
                                                  in nsIVariant aNetwork,
                                                  in DOMString status);
 };
 
-[scriptable, builtinclass, uuid(34994296-d694-4aed-953d-fc25ee25c050)]
+[scriptable, builtinclass, uuid(1717f9d9-5fd8-43d8-a098-55924c6d37de)]
 interface nsIDOMMozWifiConnectionInfoEvent : nsIDOMEvent
 {
     /**
      * Network object with an SSID field.
      */
     readonly attribute nsIVariant network;
 
     /**
@@ -172,16 +177,22 @@ interface nsIDOMMozWifiConnectionInfoEve
      */
     readonly attribute short relSignalStrength;
 
     /**
      * Link speed in Mb/s.
      */
     readonly attribute long linkSpeed;
 
+    /**
+     * IP address in the dotted quad format.
+     */
+    readonly attribute DOMString ipAddress;
+
     [noscript] void initMozWifiConnectionInfoEvent(in DOMString aType,
                                                    in boolean aCanBubble,
                                                    in boolean aCancelable,
                                                    in nsIVariant aNetwork,
                                                    in short signalStrength,
                                                    in short relSignalStrength,
-                                                   in long linkSpeed);
+                                                   in long linkSpeed,
+                                                   in DOMString ipAddress);
 };