Bug 886110 - Convert WifiManager to WebIDL. r=mrbkap
authorDimi Lee <dlee@mozilla.com>
Wed, 19 Mar 2014 14:04:58 +0800
changeset 174464 463fa756b43be262180ef2002132106b6fdff134
parent 174463 98e386f7c01c5b5350ad236754461980aaf06e1d
child 174465 2246fe6ceae069598722f3477a9110df9f3b57ae
push id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
reviewersmrbkap
bugs886110
milestone31.0a1
Bug 886110 - Convert WifiManager to WebIDL. r=mrbkap
dom/permission/tests/test_wifi-manage.html
dom/tests/mochitest/general/test_interfaces.html
dom/webidl/MozWifiManager.webidl
dom/webidl/moz.build
dom/wifi/DOMWifiManager.js
dom/wifi/DOMWifiManager.manifest
dom/wifi/nsIWifi.idl
--- a/dom/permission/tests/test_wifi-manage.html
+++ b/dom/permission/tests/test_wifi-manage.html
@@ -25,17 +25,17 @@ function verifier(success, failure) {
   }
 }
 
 var gData = [
   {
     perm: ["wifi-manage"],
     needParentPerm: true,
     obj: "mozWifiManager",
-    idl: "nsIDOMWifiManager",
+    webidl: "MozWifiManager",
     verifier: verifier.toSource(),
   },
 ]
 </script>
 </pre>
 </body>
 </html>
 
--- a/dom/tests/mochitest/general/test_interfaces.html
+++ b/dom/tests/mochitest/general/test_interfaces.html
@@ -675,18 +675,26 @@ var interfaceNamesInGlobalScope =
     {name: "MozTimeManager", b2g: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "MozVoicemail", b2g: true, pref: "dom.voicemail.enabled"},
 // IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "MozVoicemailEvent", b2g: true, pref: "dom.voicemail.enabled"},
 // IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "MozWakeLock", b2g: true, pref: "dom.wakelock.enabled"},
 // IMPORTANT: Do not change this list without review from a DOM peer!
+    {name: "MozWifiConnection", b2g: true, permission: "wifi-manage"},
+// IMPORTANT: Do not change this list without review from a DOM peer!
+    {name: "MozWifiConnectionInfo", b2g: true, permission: "wifi-manage"},
+// IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "MozWifiConnectionInfoEvent", b2g: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
+    {name: "MozWifiManager", b2g: true, permission: "wifi-manage"},
+// IMPORTANT: Do not change this list without review from a DOM peer!
+    {name: "MozWifiNetwork", b2g: true, permission: "wifi-manage"},
+// IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "MozWifiStatusChangeEvent", b2g: true},
 // IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "MozWifiP2pGroupOwner", b2g: true, permission: "wifi-manage"},
 // IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "MozWifiP2pManager", b2g: true, permission: "wifi-manage"},
 // IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "MozWifiP2pStatusChangeEvent", b2g: true, permission: "wifi-manage"},
 // IMPORTANT: Do not change this list without review from a DOM peer!
new file mode 100644
--- /dev/null
+++ b/dom/webidl/MozWifiManager.webidl
@@ -0,0 +1,237 @@
+/* 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/. */
+
+enum WifiWPSMethod {
+  "pbc",
+  "pin",
+  "cancel"
+};
+
+enum ConnectionStatus {
+  "connecting",
+  "associated",
+  "connected",
+  "disconnected"
+};
+
+dictionary WifiWPSInfo {
+  WifiWPSMethod method;
+  DOMString? pin;
+  DOMString? bssid;
+};
+
+dictionary NetworkProperties {
+  DOMString ssid;
+  sequence<DOMString>? security;
+  sequence<DOMString>? capabilities;
+  boolean known;
+  boolean connected;
+  boolean hidden;
+};
+
+[Constructor(optional NetworkProperties properties),
+ JSImplementation="@mozilla.org/mozwifinetwork;1"]
+interface MozWifiNetwork {
+  readonly attribute DOMString ssid;
+  readonly attribute any security;
+  readonly attribute any capabilities;
+  readonly attribute boolean known;
+  readonly attribute boolean connected;
+  readonly attribute boolean hidden;
+
+           attribute DOMString? bssid;
+           attribute DOMString? signalStrength;
+           attribute long? relSignalStrength;
+           attribute DOMString? psk;
+           attribute DOMString? keyManagement;
+           attribute DOMString? identity;
+           attribute DOMString? password;
+           attribute DOMString? phase1;
+           attribute DOMString? phase2;
+           attribute DOMString? eap;
+           attribute DOMString? pin;
+};
+
+[JSImplementation="@mozilla.org/mozwificonnection;1"]
+interface MozWifiConnection {
+  readonly attribute ConnectionStatus status;
+  readonly attribute MozWifiNetwork? network;
+};
+
+[JSImplementation="@mozilla.org/mozwificonnectioninfo;1"]
+interface MozWifiConnectionInfo {
+  readonly attribute short signalStrength;
+  readonly attribute short relSignalStrength;
+  readonly attribute long linkSpeed;
+  readonly attribute DOMString? ipAddress;
+};
+
+dictionary IPConfiguration {
+  boolean enabled;
+  DOMString ipaddr;
+  DOMString proxy;
+  short maskLength;
+  DOMString gateway;
+  DOMString dns1;
+  DOMString dns2;
+};
+
+[JSImplementation="@mozilla.org/wifimanager;1",
+ NavigatorProperty="mozWifiManager",
+ Func="Navigator::HasWifiManagerSupport"]
+interface MozWifiManager : EventTarget {
+  /**
+   * Returns the list of currently available 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.
+   * onerror: We were unable to obtain a list of property names.
+   */
+  DOMRequest getNetworks();
+
+  /**
+   * Returns the list of networks known to the system that will be
+   * automatically connected to if they're in range.
+   * onsuccess: request.value is an object whose property names are
+   *            SSIDs and values are network objects.
+   * onerror: We were unable to obtain a list of known networks.
+   */
+  DOMRequest getKnownNetworks();
+
+  /**
+   * Takes one of the networks returned from getNetworks and tries to
+   * connect to it.
+   * @param network A network object with information about the network,
+   *                such as the SSID, key management desired, etc.
+   * onsuccess: We have started attempting to associate with the network.
+   *            request.value is true.
+   * onerror: We were unable to select the network. This most likely means a
+   *          configuration error.
+   */
+  DOMRequest associate(MozWifiNetwork network);
+
+  /**
+   * Given a network, removes it from the list of networks that we'll
+   * automatically connect to. In order to re-connect to the network, it is
+   * necessary to call associate on it.
+   * @param network A network object with the SSID of the network to remove.
+   * onsuccess: We have removed this network. If we were previously
+   *            connected to it, we have started reconnecting to the next
+   *            network in the list.
+   * onerror: We were unable to remove the network.
+   */
+  DOMRequest forget(MozWifiNetwork network);
+
+  /**
+   * Wi-Fi Protected Setup functionality.
+   * @param detail WPS detail which has 'method' and 'pin' field.
+   *               The possible method field values are:
+   *                 - pbc: The Push Button Configuration.
+   *                 - pin: The PIN configuration.
+   *                 - cancel: Request to cancel WPS in progress.
+   *               If method field is 'pin', 'pin' field can exist and has
+   *               a PIN number.
+   *               If method field is 'pin', 'bssid' field can exist and has
+   *               a opposite BSSID.
+   * onsuccess: We have successfully started/canceled wps.
+   * onerror: We have failed to start/cancel wps.
+   */
+  DOMRequest wps(optional WifiWPSInfo detail);
+
+  /**
+   * Turn on/off wifi power saving mode.
+   * @param enabled true or false.
+   * onsuccess: We have successfully turn on/off wifi power saving mode.
+   * onerror: We have failed to turn on/off wifi power saving mode.
+   */
+  DOMRequest setPowerSavingMode(boolean enabled);
+
+  /**
+   * Given a network, configure using static IP instead of running DHCP
+   * @param network A network object with the SSID of the network to set static ip.
+   * @param info info should have following field:
+   *        - enabled True to enable static IP, false to use DHCP
+   *        - ipaddr configured static IP address
+   *        - proxy configured proxy server address
+   *        - maskLength configured mask length
+   *        - gateway configured gateway address
+   *        - dns1 configured first DNS server address
+   *        - dns2 configured seconf DNS server address
+   * onsuccess: We have successfully configure the static ip mode.
+   * onerror: We have failed to configure the static ip mode.
+   */
+  DOMRequest setStaticIpMode(MozWifiNetwork network, optional IPConfiguration info);
+
+  /**
+   * Given a network, configure http proxy when using wifi.
+   * @param network A network object with the SSID of the network to set http proxy.
+   * @param info info should have following field:
+   *        - httpProxyHost ip address of http proxy.
+   *        - httpProxyPort port of http proxy, set 0 to use default port 8080.
+   *        set info to null to clear http proxy.
+   * onsuccess: We have successfully configure http proxy.
+   * onerror: We have failed to configure http proxy.
+   */
+  DOMRequest setHttpProxy(MozWifiNetwork network, any info);
+
+  /**
+   * 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 MozWifiConnection? connection;
+
+  /**
+   * A connectionInformation object with the same information found in an
+   * nsIDOMMozWifiConnectionInfoEvent (but without the network).
+   * If we are not currently connected to a network, this will be null.
+   */
+  readonly attribute MozWifiConnectionInfo? connectionInformation;
+
+  /**
+   * State notification listeners. These all take an
+   * nsIDOMMozWifiStatusChangeEvent with the new status and a network (which
+   * may be null).
+   *
+   * The possible statuses are:
+   *   - connecting: Fires when we start the process of connecting to a
+   *                 network.
+   *   - associated: Fires when we have connected to an access point but do
+   *                 not yet have an IP address.
+   *   - connected: Fires once we are fully connected to an access point and
+   *                can access the internet.
+   *   - disconnected: Fires when we either fail to connect to an access
+   *                   point (transition: associated -> disconnected) or
+   *                   when we were connected to a network but have
+   *                   disconnected for any reason (transition: connected ->
+   *                   disconnected).
+   */
+  attribute EventHandler onstatuschange;
+
+  /**
+   * An event listener that is called with information about the signal
+   * strength and link speed every 5 seconds.
+   */
+  attribute EventHandler onconnectionInfoUpdate;
+
+  /**
+   * These two events fire when the wifi system is brought online or taken
+   * offline.
+   */
+  attribute EventHandler onenabled;
+  attribute EventHandler ondisabled;
+};
--- a/dom/webidl/moz.build
+++ b/dom/webidl/moz.build
@@ -548,16 +548,17 @@ if CONFIG['MOZ_NFC']:
          'MozNFCPeer.webidl',
          'MozNFCTag.webidl',
     ]
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
     WEBIDL_FILES += [
         'MozSpeakerManager.webidl',
         'MozWifiConnectionInfoEvent.webidl',
+        'MozWifiManager.webidl',
         'MozWifiP2pManager.webidl',
         'MozWifiP2pStatusChangeEvent.webidl',
         'MozWifiStatusChangeEvent.webidl',
     ]
 
 if CONFIG['MOZ_WEBSPEECH']:
     WEBIDL_FILES += [
         'SpeechRecognitionError.webidl',
--- a/dom/wifi/DOMWifiManager.js
+++ b/dom/wifi/DOMWifiManager.js
@@ -10,77 +10,84 @@ const {classes: Cc, interfaces: Ci, util
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/DOMRequestHelper.jsm");
 
 const DEBUG = false; // set to false to suppress debug messages
 
 const DOMWIFIMANAGER_CONTRACTID = "@mozilla.org/wifimanager;1";
-const DOMWIFIMANAGER_CID        = Components.ID("{2cf775a7-1837-410c-9e26-323c42e076da}");
+const DOMWIFIMANAGER_CID        = Components.ID("{c9b5f09e-25d2-40ca-aef4-c4d13d93c706}");
 
-function DOMWifiManager() {
-}
-
-function exposeCurrentNetwork(currentNetwork) {
-  currentNetwork.__exposedProps__ = exposeCurrentNetwork.currentNetworkApi;
+function MozWifiNetwork() {
 }
 
-exposeCurrentNetwork.currentNetworkApi = {
-  ssid: "r",
-  security: "r",
-  capabilities: "r",
-  known: "r"
+MozWifiNetwork.prototype = {
+
+  init: function(aWindow) {
+    this._window = aWindow;
+  },
+
+  __init: function(obj) {
+    this.ssid = obj.ssid;
+    this.security = obj.security;
+    this.capabilities = obj.capabilities;
+    this.known = obj.known;
+    this.connected = obj.connected;
+    this.hidden = obj.hidden;
+  },
+
+  classID: Components.ID("{c01fd751-43c0-460a-8b64-abf652ec7220}"),
+  contractID: "@mozilla.org/mozwifinetwork;1",
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports,
+                                         Ci.nsIDOMGlobalPropertyInitializer])
 };
 
-// For smaller, read-only APIs, we expose any property that doesn't begin with
-// an underscore.
-function exposeReadOnly(obj) {
-  var exposedProps = {};
-  for (let i in obj) {
-    if (i[0] === "_")
-      continue;
-    exposedProps[i] = "r";
-  }
+function MozWifiConnection(obj) {
+  this.status = obj.status;
+  this.network = obj.network;
+}
+
+MozWifiConnection.prototype = {
+  classID: Components.ID("{23579da4-201b-4319-bd42-9b7f337343ac}"),
+  contractID: "@mozilla.org/mozwificonnection;1",
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports])
+};
 
-  obj.__exposedProps__ = exposedProps;
-  return obj;
+function MozWifiConnectionInfo(obj) {
+  this.signalStrength = obj.signalStrength;
+  this.relSignalStrength = obj.relSignalStrength;
+  this.linkSpeed = obj.linkSpeed;
+  this.ipAddress = obj.ipAddress;
+}
+
+MozWifiConnectionInfo.prototype = {
+  classID: Components.ID("{83670352-6ed4-4c35-8de9-402296a1959c}"),
+  contractID: "@mozilla.org/mozwificonnectioninfo;1",
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports])
+}
+
+function DOMWifiManager() {
+  this.defineEventHandlerGetterSetter("onstatuschange");
+  this.defineEventHandlerGetterSetter("onconnectionInfoUpdate");
+  this.defineEventHandlerGetterSetter("onenabled");
+  this.defineEventHandlerGetterSetter("ondisabled");
 }
 
 DOMWifiManager.prototype = {
   __proto__: DOMRequestIpcHelper.prototype,
-
-  classID:   DOMWIFIMANAGER_CID,
-  classInfo: XPCOMUtils.generateCI({classID: DOMWIFIMANAGER_CID,
-                                    contractID: DOMWIFIMANAGER_CONTRACTID,
-                                    classDescription: "DOMWifiManager",
-                                    interfaces: [Ci.nsIDOMWifiManager],
-                                    flags: Ci.nsIClassInfo.DOM_OBJECT}),
-
-  QueryInterface: XPCOMUtils.generateQI([Ci.nsIDOMWifiManager,
-                                         Ci.nsIDOMGlobalPropertyInitializer,
+  classDescription: "DOMWifiManager",
+  classID: DOMWIFIMANAGER_CID,
+  contractID: DOMWIFIMANAGER_CONTRACTID,
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsIDOMGlobalPropertyInitializer,
                                          Ci.nsISupportsWeakReference,
                                          Ci.nsIObserver]),
 
   // nsIDOMGlobalPropertyInitializer implementation
   init: function(aWindow) {
-    let principal = aWindow.document.nodePrincipal;
-    let secMan = Cc["@mozilla.org/scriptsecuritymanager;1"].getService(Ci.nsIScriptSecurityManager);
-
-    let perm = principal == secMan.getSystemPrincipal()
-                 ? Ci.nsIPermissionManager.ALLOW_ACTION
-                 : Services.perms.testExactPermissionFromPrincipal(principal, "wifi-manage");
-
-    // Only pages with perm set can use the wifi manager.
-    this._hasPrivileges = perm == Ci.nsIPermissionManager.ALLOW_ACTION;
-
-    if (!this._hasPrivileges) {
-      return null;
-    }
-
     // Maintain this state for synchronous APIs.
     this._currentNetwork = null;
     this._connectionStatus = "disconnected";
     this._enabled = false;
     this._lastConnectionInfo = null;
 
     const messages = ["WifiManager:getNetworks:Return:OK", "WifiManager:getNetworks:Return:NO",
                       "WifiManager:getKnownNetworks:Return:OK", "WifiManager:getKnownNetworks:Return:NO",
@@ -96,37 +103,64 @@ DOMWifiManager.prototype = {
                       "WifiManager:onwpstimeout", "WifiManager:onwpsfail",
                       "WifiManager:onwpsoverlap", "WifiManager:connectionInfoUpdate",
                       "WifiManager:onconnectingfailed"];
     this.initDOMRequestHelper(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;
-      if (this._currentNetwork)
-        exposeCurrentNetwork(this._currentNetwork);
-      this._lastConnectionInfo = state.connectionInfo;
+      this._currentNetwork = this._convertWifiNetwork(state.network);
+      this._lastConnectionInfo = this._convertConnectionInfo(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;
+  _convertWifiNetworkToJSON: function(aNetwork) {
+    let json = {};
+
+    for (let key in aNetwork) {
+      // In WifiWorker.js there are lots of check using "key in network".
+      // So if the value of any property of WifiNetwork is undefined, do not clone it.
+      if (aNetwork[key] != undefined) {
+        json[key] = aNetwork[key];
+      }
+    }
+    return json;
+  },
+
+  _convertWifiNetwork: function(aNetwork) {
+    let network = aNetwork ? new this._window.MozWifiNetwork(aNetwork) : null;
+    return network;
+  },
+
+  _convertWifiNetworks: function(aNetworks) {
+    let networks = [];
+    for (let i in aNetworks) {
+      networks.push(this._convertWifiNetwork(aNetworks[i]));
+    }
+    return networks;
+  },
+
+  _convertConnection: function(aConn) {
+    let conn = aConn ? new MozWifiConnection(aConn) : null;
+    return conn;
+  },
+
+  _convertConnectionInfo: function(aInfo) {
+    let info = aInfo ? new MozWifiConnectionInfo(aInfo) : null;
+    return info;
   },
 
   _sendMessageForRequest: function(name, data, request) {
     let id = this.getRequestId(request);
     this._mm.sendAsyncMessage(name, { data: data, rid: id, mid: this._id });
   },
 
   receiveMessage: function(aMessage) {
@@ -139,25 +173,25 @@ DOMWifiManager.prototype = {
       request = this.takeRequest(msg.rid);
       if (!request) {
         return;
       }
     }
 
     switch (aMessage.name) {
       case "WifiManager:getNetworks:Return:OK":
-        Services.DOMRequest.fireSuccess(request, exposeReadOnly(msg.data));
+        Services.DOMRequest.fireSuccess(request, this._convertWifiNetworks(msg.data));
         break;
 
       case "WifiManager:getNetworks:Return:NO":
         Services.DOMRequest.fireError(request, "Unable to scan for networks");
         break;
 
       case "WifiManager:getKnownNetworks:Return:OK":
-        Services.DOMRequest.fireSuccess(request, exposeReadOnly(msg.data));
+        Services.DOMRequest.fireSuccess(request, this._convertWifiNetworks(msg.data));
         break;
 
       case "WifiManager:getKnownNetworks:Return:NO":
         Services.DOMRequest.fireError(request, "Unable to get known networks");
         break;
 
       case "WifiManager:associate:Return:OK":
         Services.DOMRequest.fireSuccess(request, true);
@@ -171,41 +205,41 @@ DOMWifiManager.prototype = {
         Services.DOMRequest.fireSuccess(request, true);
         break;
 
       case "WifiManager:forget:Return:NO":
         Services.DOMRequest.fireError(request, msg.data);
         break;
 
       case "WifiManager:wps:Return:OK":
-        Services.DOMRequest.fireSuccess(request, exposeReadOnly(msg.data));
+        Services.DOMRequest.fireSuccess(request, msg.data);
         break;
 
       case "WifiManager:wps:Return:NO":
         Services.DOMRequest.fireError(request, msg.data);
         break;
 
       case "WifiManager:setPowerSavingMode:Return:OK":
-        Services.DOMRequest.fireSuccess(request, exposeReadOnly(msg.data));
+        Services.DOMRequest.fireSuccess(request, msg.data);
         break;
 
       case "WifiManager:setPowerSavingMode:Return:NO":
         Services.DOMRequest.fireError(request, msg.data);
         break;
 
       case "WifiManager:setHttpProxy:Return:OK":
-        Services.DOMRequest.fireSuccess(request, exposeReadOnly(msg.data));
+        Services.DOMRequest.fireSuccess(request, msg.data);
         break;
 
       case "WifiManager:setHttpProxy:Return:NO":
         Services.DOMRequest.fireError(request, msg.data);
         break;
 
       case "WifiManager:setStaticIpMode:Return:OK":
-        Services.DOMRequest.fireSuccess(request, exposeReadOnly(msg.data));
+        Services.DOMRequest.fireSuccess(request, msg.data);
         break;
 
       case "WifiManager:setStaticIpMode:Return:NO":
         Services.DOMRequest.fireError(request, msg.data);
         break;
 
       case "WifiManager:wifiDown":
         this._enabled = false;
@@ -215,32 +249,29 @@ DOMWifiManager.prototype = {
 
       case "WifiManager:wifiUp":
         this._enabled = true;
         this._macAddress = msg.macAddress;
         this._fireEnabledOrDisabled(true);
         break;
 
       case "WifiManager:onconnecting":
-        this._currentNetwork = msg.network;
-        exposeCurrentNetwork(this._currentNetwork);
+        this._currentNetwork = this._convertWifiNetwork(msg.network);
         this._connectionStatus = "connecting";
         this._fireStatusChangeEvent();
         break;
 
       case "WifiManager:onassociate":
-        this._currentNetwork = msg.network;
-        exposeCurrentNetwork(this._currentNetwork);
+        this._currentNetwork = this._convertWifiNetwork(msg.network);
         this._connectionStatus = "associated";
         this._fireStatusChangeEvent();
         break;
 
       case "WifiManager:onconnect":
-        this._currentNetwork = msg.network;
-        exposeCurrentNetwork(this._currentNetwork);
+        this._currentNetwork = this._convertWifiNetwork(msg.network);
         this._connectionStatus = "connected";
         this._fireStatusChangeEvent();
         break;
 
       case "WifiManager:ondisconnect":
         this._currentNetwork = null;
         this._connectionStatus = "disconnected";
         this._lastConnectionInfo = null;
@@ -264,179 +295,138 @@ DOMWifiManager.prototype = {
       case "WifiManager:onwpsoverlap":
         this._currentNetwork = null;
         this._connectionStatus = "wps-overlapped";
         this._lastConnectionInfo = null;
         this._fireStatusChangeEvent();
         break;
 
       case "WifiManager:connectionInfoUpdate":
-        this._lastConnectionInfo = msg;
+        this._lastConnectionInfo = this._convertConnectionInfo(msg);
         this._fireConnectionInfoUpdate(msg);
         break;
       case "WifiManager:onconnectingfailed":
         this._currentNetwork = null;
         this._connectionStatus = "connectingfailed";
         this._lastConnectionInfo = null;
         this._fireStatusChangeEvent();
         break;
     }
   },
 
   _fireStatusChangeEvent: function StatusChangeEvent() {
-    if (this._onStatusChange) {
-      debug("StatusChangeEvent");
-      var event = new this._window.MozWifiStatusChangeEvent("statusChangeEvent",
-                                                            { network: this._currentNetwork,
-                                                              status: this._connectionStatus
-                                                            });
-      this._onStatusChange.handleEvent(event);
-    }
+    var event = new this._window.MozWifiStatusChangeEvent("statuschange",
+                                                          { network: this._currentNetwork,
+                                                            status: this._connectionStatus
+                                                          });
+    this.__DOM_IMPL__.dispatchEvent(event);
   },
 
-  _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,
-                                                              ipAddress: info.ipAddress,
-                                                            });
-      this._onConnectionInfoUpdate.handleEvent(evt);
-    }
+  _fireConnectionInfoUpdate: function onConnectionInfoUpdate(info) {
+    var evt = new this._window.MozWifiConnectionInfoEvent("connectioninfoupdate",
+                                                          { network: this._currentNetwork,
+                                                            signalStrength: info.signalStrength,
+                                                            relSignalStrength: info.relSignalStrength,
+                                                            linkSpeed: info.linkSpeed,
+                                                            ipAddress: info.ipAddress,
+                                                          });
+    this.__DOM_IMPL__.dispatchEvent(evt);
   },
 
   _fireEnabledOrDisabled: function enabledDisabled(enabled) {
-    var handler = enabled ? this._onEnabled : this._onDisabled;
-    if (handler) {
-      var evt = new this._window.Event("WifiEnabled");
-      handler.handleEvent(evt);
-    }
+    var evt = new this._window.Event(enabled ? "enabled" : "disabled");
+    this.__DOM_IMPL__.dispatchEvent(evt);
   },
 
-  // nsIDOMWifiManager
-  getNetworks: function nsIDOMWifiManager_getNetworks() {
-    if (!this._hasPrivileges)
-      throw new Components.Exception("Denied", Cr.NS_ERROR_FAILURE);
+  getNetworks: function getNetworks() {
     var request = this.createRequest();
     this._sendMessageForRequest("WifiManager:getNetworks", null, request);
     return request;
   },
 
-  getKnownNetworks: function nsIDOMWifiManager_getKnownNetworks() {
-    if (!this._hasPrivileges)
-      throw new Components.Exception("Denied", Cr.NS_ERROR_FAILURE);
+  getKnownNetworks: function getKnownNetworks() {
     var request = this.createRequest();
     this._sendMessageForRequest("WifiManager:getKnownNetworks", null, request);
     return request;
   },
 
-  associate: function nsIDOMWifiManager_associate(network) {
-    if (!this._hasPrivileges)
-      throw new Components.Exception("Denied", Cr.NS_ERROR_FAILURE);
+  associate: function associate(network) {
     var request = this.createRequest();
-    this._sendMessageForRequest("WifiManager:associate", network, request);
+    this._sendMessageForRequest("WifiManager:associate",
+                                this._convertWifiNetworkToJSON(network), request);
     return request;
   },
 
-  forget: function nsIDOMWifiManager_forget(network) {
-    if (!this._hasPrivileges)
-      throw new Components.Exception("Denied", Cr.NS_ERROR_FAILURE);
+  forget: function forget(network) {
     var request = this.createRequest();
-    this._sendMessageForRequest("WifiManager:forget", network, request);
+    this._sendMessageForRequest("WifiManager:forget",
+                                this._convertWifiNetworkToJSON(network), request);
     return request;
   },
 
-  wps: function nsIDOMWifiManager_wps(detail) {
-    if (!this._hasPrivileges)
-      throw new Components.Exception("Denied", Cr.NS_ERROR_FAILURE);
+  wps: function wps(detail) {
     var request = this.createRequest();
     this._sendMessageForRequest("WifiManager:wps", detail, request);
     return request;
   },
 
-  setPowerSavingMode: function nsIDOMWifiManager_setPowerSavingMode(enabled) {
-    if (!this._hasPrivileges)
-      throw new Components.Exception("Denied", Cr.NS_ERROR_FAILURE);
+  setPowerSavingMode: function setPowerSavingMode(enabled) {
     var request = this.createRequest();
     this._sendMessageForRequest("WifiManager:setPowerSavingMode", enabled, request);
     return request;
   },
 
-  setHttpProxy: function nsIDOMWifiManager_setHttpProxy(network, info) {
-    if (!this._hasPrivileges)
-      throw new Components.Exception("Denied", Cr.NS_ERROR_FAILURE);
+  setHttpProxy: function setHttpProxy(network, info) {
     var request = this.createRequest();
-    this._sendMessageForRequest("WifiManager:setHttpProxy", {network:network, info:info}, request);
+    this._sendMessageForRequest("WifiManager:setHttpProxy",
+                                { network: this._convertWifiNetworkToJSON(network), info:info}, request);
     return request;
   },
 
-  setStaticIpMode: function nsIDOMWifiManager_setStaticIpMode(network, info) {
-    if (!this._hasPrivileges)
-      throw new Components.Exception("Denied", Cr.NS_ERROR_FAILURE);
+  setStaticIpMode: function setStaticIpMode(network, info) {
     var request = this.createRequest();
-    this._sendMessageForRequest("WifiManager:setStaticIpMode", {network: network,info: info}, request);
+    this._sendMessageForRequest("WifiManager:setStaticIpMode",
+                                { network: this._convertWifiNetworkToJSON(network), info: info}, request);
     return request;
   },
 
   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 });
+    let _connection = this._convertConnection({ status: this._connectionStatus,
+                                                network: this._currentNetwork,
+                                              });
+    return _connection;
   },
 
   get connectionInformation() {
-    if (!this._hasPrivileges)
-      throw new Components.Exception("Denied", Cr.NS_ERROR_FAILURE);
-    return this._lastConnectionInfo
-           ? exposeReadOnly(this._lastConnectionInfo)
-           : null;
-  },
-
-  set onstatuschange(callback) {
-    if (!this._hasPrivileges)
-      throw new Components.Exception("Denied", Cr.NS_ERROR_FAILURE);
-    this._onStatusChange = callback;
+    return this._lastConnectionInfo;
   },
 
-  set connectionInfoUpdate(callback) {
-    if (!this._hasPrivileges)
-      throw new Components.Exception("Denied", Cr.NS_ERROR_FAILURE);
-    this._onConnectionInfoUpdate = callback;
+  defineEventHandlerGetterSetter: function(name) {
+    Object.defineProperty(this, name, {
+      get: function() {
+        return this.__DOM_IMPL__.getEventHandler(name);
+      },
+      set: function(handler) {
+        this.__DOM_IMPL__.setEventHandler(name, handler);
+      }
+    });
   },
-
-  set onenabled(callback) {
-    if (!this._hasPrivileges)
-      throw new Components.Exception("Denied", Cr.NS_ERROR_FAILURE);
-    this._onEnabled = callback;
-  },
-
-  set ondisabled(callback) {
-    if (!this._hasPrivileges)
-      throw new Components.Exception("Denied", Cr.NS_ERROR_FAILURE);
-    this._onDisabled = callback;
-  }
 };
 
-this.NSGetFactory = XPCOMUtils.generateNSGetFactory([DOMWifiManager]);
+this.NSGetFactory = XPCOMUtils.generateNSGetFactory([
+  DOMWifiManager, MozWifiNetwork, MozWifiConnection, MozWifiConnectionInfo
+]);
 
 let debug;
 if (DEBUG) {
   debug = function (s) {
     dump("-*- DOMWifiManager component: " + s + "\n");
   };
 } else {
   debug = function (s) {};
--- a/dom/wifi/DOMWifiManager.manifest
+++ b/dom/wifi/DOMWifiManager.manifest
@@ -1,4 +1,12 @@
 # DOMWifiManager.js
-component {2cf775a7-1837-410c-9e26-323c42e076da} DOMWifiManager.js
-contract @mozilla.org/wifimanager;1 {2cf775a7-1837-410c-9e26-323c42e076da}
-category JavaScript-navigator-property mozWifiManager @mozilla.org/wifimanager;1
+component {c9b5f09e-25d2-40ca-aef4-c4d13d93c706} DOMWifiManager.js
+contract @mozilla.org/wifimanager;1 {c9b5f09e-25d2-40ca-aef4-c4d13d93c706}
+
+component {c01fd751-43c0-460a-8b64-abf652ec7220} DOMWifiManager.js
+contract @mozilla.org/mozwifinetwork;1 {c01fd751-43c0-460a-8b64-abf652ec7220}
+
+component {23579da4-201b-4319-bd42-9b7f337343ac} DOMWifiManager.js
+contract @mozilla.org/mozwificonnection;1 {23579da4-201b-4319-bd42-9b7f337343ac}
+
+component {83670352-6ed4-4c35-8de9-402296a1959c} DOMWifiManager.js
+contract @mozilla.org/mozwificonnectioninfo;1 {83670352-6ed4-4c35-8de9-402296a1959c}
--- a/dom/wifi/nsIWifi.idl
+++ b/dom/wifi/nsIWifi.idl
@@ -53,168 +53,8 @@ interface nsIWifi : nsISupports
      * Returns the list of currently available networks as well as the list of
      * currently configured networks.
      *
      * On success a callback is notified with the list of networks.
      * On failure after 3 scan retry attempts a callback is notified of failure.
      */
     void getWifiScanResults(in nsIWifiScanResultsReady callback);
 };
-
-[scriptable, uuid(e5a72295-1c5f-4848-9cbb-f1d3785c16c1)]
-interface nsIDOMWifiManager : nsISupports
-{
-    /**
-     * Returns the list of currently available 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.
-     * onerror: We were unable to obtain a list of property names.
-     */
-    nsIDOMDOMRequest getNetworks();
-
-    /**
-     * Returns the list of networks known to the system that will be
-     * automatically connected to if they're in range.
-     * onsuccess: request.value is an object whose property names are
-     *            SSIDs and values are network objects.
-     * onerror: We were unable to obtain a list of known networks.
-     */
-    nsIDOMDOMRequest getKnownNetworks();
-
-    /**
-     * Takes one of the networks returned from getNetworks and tries to
-     * connect to it.
-     * @param network A network object with information about the network,
-     *                such as the SSID, key management desired, etc.
-     * onsuccess: We have started attempting to associate with the network.
-     *            request.value is true.
-     * onerror: We were unable to select the network. This most likely means a
-     *          configuration error.
-     */
-    nsIDOMDOMRequest associate(in jsval network);
-
-    /**
-     * Given a network, removes it from the list of networks that we'll
-     * automatically connect to. In order to re-connect to the network, it is
-     * necessary to call associate on it.
-     * @param network A network object with the SSID of the network to remove.
-     * onsuccess: We have removed this network. If we were previously
-     *            connected to it, we have started reconnecting to the next
-     *            network in the list.
-     * onerror: We were unable to remove the network.
-     */
-    nsIDOMDOMRequest forget(in jsval network);
-
-    /**
-     * Wi-Fi Protected Setup functionality.
-     * @param detail WPS detail which has 'method' and 'pin' field.
-     *               The possible method field values are:
-     *                 - pbc: The Push Button Configuration.
-     *                 - pin: The PIN configuration.
-     *                 - cancel: Request to cancel WPS in progress.
-     *               If method field is 'pin', 'pin' field can exist and has
-     *               a PIN number.
-     *               If method field is 'pin', 'bssid' field can exist and has
-     *               a opposite BSSID.
-     * onsuccess: We have successfully started/canceled wps.
-     * onerror: We have failed to start/cancel wps.
-     */
-    nsIDOMDOMRequest wps(in jsval detail);
-
-    /**
-     * Turn on/off wifi power saving mode.
-     * @param enabled true or false.
-     * onsuccess: We have successfully turn on/off wifi power saving mode.
-     * onerror: We have failed to turn on/off wifi power saving mode.
-     */
-    nsIDOMDOMRequest setPowerSavingMode(in boolean enabled);
-
-    /**
-     * Given a network, configure using static IP instead of running DHCP
-     * @param network A network object with the SSID of the network to set static ip.
-     * @param info info should have following field:
-     *        - enabled True to enable static IP, false to use DHCP
-     *        - ipaddr configured static IP address
-     *        - proxy configured proxy server address
-     *        - maskLength configured mask length
-     *        - gateway configured gateway address
-     *        - dns1 configured first DNS server address
-     *        - dns2 configured seconf DNS server address
-     * onsuccess: We have successfully configure the static ip mode.
-     * onerror: We have failed to configure the static ip mode.
-     */
-    nsIDOMDOMRequest setStaticIpMode(in jsval network,
-                                     in jsval info);
-
-    /**
-     * Given a network, configure http proxy when using wifi.
-     * @param network A network object with the SSID of the network to set http proxy.
-     * @param info info should have following field:
-     *        - httpProxyHost ip address of http proxy.
-     *        - httpProxyPort port of http proxy, set 0 to use default port 8080.
-     *        set info to null to clear http proxy.
-     * onsuccess: We have successfully configure http proxy.
-     * onerror: We have failed to configure http proxy.
-     */
-    nsIDOMDOMRequest setHttpProxy(in jsval network,
-                                  in jsval info);
-
-    /**
-     * 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;
-
-    /**
-     * A connectionInformation object with the same information found in an
-     * nsIDOMMozWifiConnectionInfoEvent (but without the network).
-     * If we are not currently connected to a network, this will be null.
-     */
-    readonly attribute jsval connectionInformation;
-
-    /**
-     * State notification listeners. These all take an
-     * nsIDOMMozWifiStatusChangeEvent with the new status and a network (which
-     * may be null).
-     *
-     * The possible statuses are:
-     *   - connecting: Fires when we start the process of connecting to a
-     *                 network.
-     *   - associated: Fires when we have connected to an access point but do
-     *                 not yet have an IP address.
-     *   - connected: Fires once we are fully connected to an access point and
-     *                can access the internet.
-     *   - disconnected: Fires when we either fail to connect to an access
-     *                   point (transition: associated -> disconnected) or
-     *                   when we were connected to a network but have
-     *                   disconnected for any reason (transition: connected ->
-     *                   disconnected).
-     */
-    attribute nsIDOMEventListener onstatuschange;
-
-    /**
-     * An event listener that is called with information about the signal
-     * strength and link speed every 5 seconds.
-     */
-    attribute nsIDOMEventListener connectionInfoUpdate;
-
-    /**
-     * These two events fire when the wifi system is brought online or taken
-     * offline.
-     */
-    attribute nsIDOMEventListener onenabled;
-    attribute nsIDOMEventListener ondisabled;
-};