Bug 919426 - Part 3: Make use of WifiCommand/WifiNetNet in WifiWorker.js. r=vchang
authorHenry Chang <hchang@mozilla.com>
Mon, 30 Sep 2013 11:05:05 +0800
changeset 150510 f75c25e53e53db061a8143e6cc8d66ea125afa26
parent 150509 21754eba49313dbdef7ca874e2192951061bd1f2
child 150511 562abc4f545e9db5cd855f7f4c5c27053688ad54
push id3001
push userryanvm@gmail.com
push dateFri, 11 Oct 2013 21:03:10 +0000
treeherderfx-team@9ab188de8245 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersvchang
bugs919426
milestone27.0a1
Bug 919426 - Part 3: Make use of WifiCommand/WifiNetNet in WifiWorker.js. r=vchang
dom/wifi/WifiWorker.js
dom/wifi/moz.build
--- a/dom/wifi/WifiWorker.js
+++ b/dom/wifi/WifiWorker.js
@@ -6,16 +6,18 @@
 
 "use strict";
 
 const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/systemlibs.js");
+Cu.import("resource://gre/modules/WifiCommand.jsm");
+Cu.import("resource://gre/modules/WifiNetUtil.jsm");
 
 var DEBUG = false; // set to true to show debug messages.
 
 const WIFIWORKER_CONTRACTID = "@mozilla.org/wifi/worker;1";
 const WIFIWORKER_CID        = Components.ID("{a14e8977-d259-433a-a88d-58dd44657e5b}");
 
 const WIFIWORKER_WORKER     = "resource://gre/modules/wifi_worker.js";
 
@@ -130,16 +132,19 @@ var WifiManager = (function() {
   // Emulator build runs to here.
   // The debug() should only be used after WifiManager.
   if (!ifname) {
     manager.ifname = DEFAULT_WLAN_INTERFACE;
   }
   manager.schedScanRecovery = schedScanRecovery;
   manager.driverDelay = driverDelay ? parseInt(driverDelay, 10) : DRIVER_READY_WAIT;
 
+  var wifiCommand = WifiCommand(controlMessage);
+  var netUtil = WifiNetUtil(controlMessage);
+
   // Callbacks to invoke when a reply arrives from the wifi service.
   var controlCallbacks = Object.create(null);
   var idgen = 0;
 
   function controlMessage(obj, callback) {
     var id = idgen++;
     obj.id = id;
     if (callback)
@@ -160,146 +165,46 @@ var WifiManager = (function() {
   var recvErrors = 0;
 
   function waitForEvent() {
     wifiService.waitForEvent();
   }
 
   // Commands to the control worker.
 
-  function voidControlMessage(cmd, callback) {
-    controlMessage({ cmd: cmd }, function (data) {
-      callback(data.status);
-    });
-  }
-
   var driverLoaded = false;
 
   function loadDriver(callback) {
     if (driverLoaded) {
       callback(0);
       return;
     }
 
-    voidControlMessage("load_driver", function(status) {
+    wifiCommand.loadDriver(function (status) {
       driverLoaded = (status >= 0);
       callback(status)
     });
   }
 
   function unloadDriver(callback) {
     if (!unloadDriverEnabled) {
       // Unloading drivers is generally unnecessary and
       // can trigger bugs in some drivers.
       // On properly written drivers, bringing the interface
       // down powers down the interface.
       callback(0);
       return;
     }
 
-    voidControlMessage("unload_driver", function(status) {
+    wifiCommand.unloadDriver(function(status) {
       driverLoaded = (status < 0);
       callback(status);
     });
   }
 
-  function startSupplicant(callback) {
-    voidControlMessage("start_supplicant", callback);
-  }
-
-  function terminateSupplicant(callback) {
-    doBooleanCommand("TERMINATE", "OK", callback);
-  }
-
-  function stopSupplicant(callback) {
-    voidControlMessage("stop_supplicant", callback);
-  }
-
-  function connectToSupplicant(callback) {
-    voidControlMessage("connect_to_supplicant", callback);
-  }
-
-  function closeSupplicantConnection(callback) {
-    voidControlMessage("close_supplicant_connection", callback);
-  }
-
-  function doCommand(request, callback) {
-    controlMessage({ cmd: "command", request: request }, callback);
-  }
-
-  function doIntCommand(request, callback) {
-    doCommand(request, function(data) {
-      callback(data.status ? -1 : (data.reply|0));
-    });
-  }
-
-  function doBooleanCommand(request, expected, callback) {
-    doCommand(request, function(data) {
-      callback(data.status ? false : (data.reply == expected));
-    });
-  }
-
-  function doStringCommand(request, callback) {
-    doCommand(request, function(data) {
-      callback(data.status ? null : data.reply);
-    });
-  }
-
-  function listNetworksCommand(callback) {
-    doStringCommand("LIST_NETWORKS", callback);
-  }
-
-  function addNetworkCommand(callback) {
-    doIntCommand("ADD_NETWORK", callback);
-  }
-
-  function setNetworkVariableCommand(netId, name, value, callback) {
-    doBooleanCommand("SET_NETWORK " + netId + " " + name + " " + value, "OK", callback);
-  }
-
-  function getNetworkVariableCommand(netId, name, callback) {
-    doStringCommand("GET_NETWORK " + netId + " " + name, callback);
-  }
-
-  function removeNetworkCommand(netId, callback) {
-    doBooleanCommand("REMOVE_NETWORK " + netId, "OK", callback);
-  }
-
-  function enableNetworkCommand(netId, disableOthers, callback) {
-    doBooleanCommand((disableOthers ? "SELECT_NETWORK " : "ENABLE_NETWORK ") + netId, "OK", callback);
-  }
-
-  function disableNetworkCommand(netId, callback) {
-    doBooleanCommand("DISABLE_NETWORK " + netId, "OK", callback);
-  }
-
-  function statusCommand(callback) {
-    doStringCommand("STATUS", callback);
-  }
-
-  function pingCommand(callback) {
-    doBooleanCommand("PING", "PONG", callback);
-  }
-
-  function scanResultsCommand(callback) {
-    doStringCommand("SCAN_RESULTS", callback);
-  }
-
-  function disconnectCommand(callback) {
-    doBooleanCommand("DISCONNECT", "OK", callback);
-  }
-
-  function reconnectCommand(callback) {
-    doBooleanCommand("RECONNECT", "OK", callback);
-  }
-
-  function reassociateCommand(callback) {
-    doBooleanCommand("REASSOCIATE", "OK", callback);
-  }
-
   // A note about background scanning:
   // Normally, background scanning shouldn't be necessary as wpa_supplicant
   // has the capability to automatically schedule its own scans at appropriate
   // intervals. However, with some drivers, this appears to get stuck after
   // three scans, so we enable the driver's background scanning to work around
   // that when we're not connected to any network. This ensures that we'll
   // automatically reconnect to networks if one falls out of range.
   var reEnableBackgroundScan = false;
@@ -309,70 +214,55 @@ var WifiManager = (function() {
   function setBackgroundScan(enable, callback) {
     var doEnable = (enable === "ON");
     if (doEnable === manager.backgroundScanEnabled) {
       callback(false, true);
       return;
     }
 
     manager.backgroundScanEnabled = doEnable;
-    doBooleanCommand("SET pno " + (manager.backgroundScanEnabled ? "1" : "0"),
-                     "OK",
-                     function(ok) {
-                       callback(true, ok);
-                     });
+    wifiCommand.setBackgroundScan(manager.backgroundScanEnabled, callback);
   }
 
   var scanModeActive = false;
 
-  function doSetScanModeCommand(setActive, callback) {
-    doBooleanCommand(setActive ? "DRIVER SCAN-ACTIVE" : "DRIVER SCAN-PASSIVE", "OK", callback);
-  }
-
-  function scanCommand(forceActive, callback) {
+  function scan(forceActive, callback) {
     if (forceActive && !scanModeActive) {
       // Note: we ignore errors from doSetScanMode.
-      doSetScanModeCommand(true, function(ignore) {
+      wifiCommand.doSetScanMode(true, function(ignore) {
         setBackgroundScan("OFF", function(turned, ignore) {
           reEnableBackgroundScan = turned;
-          doBooleanCommand("SCAN", "OK", function(ok) {
-            doSetScanModeCommand(false, function(ignore) {
+          wifiCommand.scan(function(ok) {
+            wifiCommand.doSetScanMode(false, function(ignore) {
               // The result of scanCommand is the result of the actual SCAN
               // request.
               callback(ok);
             });
           });
         });
       });
       return;
     }
-    doBooleanCommand("SCAN", "OK", callback);
+    wifiCommand.scan(callback);
   }
 
   var debugEnabled = false;
-  function setLogLevel(level, callback) {
-    doBooleanCommand("LOG_LEVEL " + level, "OK", callback);
-  }
 
   function syncDebug() {
     if (debugEnabled !== DEBUG) {
       let wanted = DEBUG;
-      setLogLevel(wanted ? "DEBUG" : "INFO", function(ok) {
+      wifiCommand.setLogLevel(wanted ? "DEBUG" : "INFO", function(ok) {
         if (ok)
           debugEnabled = wanted;
       });
     }
   }
 
-  function getLogLevel(callback) {
-    doStringCommand("LOG_LEVEL", callback);
-  }
-
   function getDebugEnabled(callback) {
-    getLogLevel(function(level) {
+    wifiCommand.getLogLevel(function(level) {
       if (level === null) {
         debug("Unable to get wpa_supplicant's log level");
         callback(false);
         return;
       }
 
       var lines = level.split("\n");
       for (let i = 0; i < lines.length; ++i) {
@@ -384,266 +274,19 @@ var WifiManager = (function() {
         }
       }
 
       // If we're here, we didn't get the current level.
       callback(false);
     });
   }
 
-  function setScanModeCommand(setActive, callback) {
+  function setScanMode(setActive, callback) {
     scanModeActive = setActive;
-    doSetScanModeCommand(setActive, callback);
-  }
-
-  function wpsPbcCommand(callback) {
-    doBooleanCommand("WPS_PBC", "OK", callback);
-  }
-
-  function wpsPinCommand(detail, callback) {
-    doStringCommand("WPS_PIN " +
-                    (detail.bssid === undefined ? "any" : detail.bssid) +
-                    (detail.pin === undefined ? "" : (" " + detail.pin)),
-                    callback);
-  }
-
-  function wpsCancelCommand(callback) {
-    doBooleanCommand("WPS_CANCEL", "OK", callback);
-  }
-
-  function startDriverCommand(callback) {
-    doBooleanCommand("DRIVER START", "OK");
-  }
-
-  function stopDriverCommand(callback) {
-    doBooleanCommand("DRIVER STOP", "OK");
-  }
-
-  function startPacketFiltering(callback) {
-    doBooleanCommand("DRIVER RXFILTER-ADD 0", "OK", function(ok) {
-      ok && doBooleanCommand("DRIVER RXFILTER-ADD 1", "OK", function(ok) {
-        ok && doBooleanCommand("DRIVER RXFILTER-ADD 3", "OK", function(ok) {
-          ok && doBooleanCommand("DRIVER RXFILTER-START", "OK", callback)
-        });
-      });
-    });
-  }
-
-  function stopPacketFiltering(callback) {
-    doBooleanCommand("DRIVER RXFILTER-STOP", "OK", function(ok) {
-      ok && doBooleanCommand("DRIVER RXFILTER-REMOVE 3", "OK", function(ok) {
-        ok && doBooleanCommand("DRIVER RXFILTER-REMOVE 1", "OK", function(ok) {
-          ok && doBooleanCommand("DRIVER RXFILTER-REMOVE 0", "OK", callback)
-        });
-      });
-    });
-  }
-
-  function doGetRssiCommand(cmd, callback) {
-    doCommand(cmd, function(data) {
-      var rssi = -200;
-
-      if (!data.status) {
-        // If we are associating, the reply is "OK".
-        var reply = data.reply;
-        if (reply != "OK") {
-          // Format is: <SSID> rssi XX". SSID can contain spaces.
-          var offset = reply.lastIndexOf("rssi ");
-          if (offset !== -1)
-            rssi = reply.substr(offset + 5) | 0;
-        }
-      }
-      callback(rssi);
-    });
-  }
-
-  function getRssiCommand(callback) {
-    doGetRssiCommand("DRIVER RSSI", callback);
-  }
-
-  function getRssiApproxCommand(callback) {
-    doGetRssiCommand("DRIVER RSSI-APPROX", callback);
-  }
-
-  function getLinkSpeedCommand(callback) {
-    doStringCommand("DRIVER LINKSPEED", function(reply) {
-      if (reply)
-        reply = reply.split(" ")[1] | 0; // Format: LinkSpeed XX
-      callback(reply);
-    });
-  }
-
-  function getConnectionInfoGB(callback) {
-    var rval = {};
-    getRssiApproxCommand(function(rssi) {
-      rval.rssi = rssi;
-      getLinkSpeedCommand(function(linkspeed) {
-        rval.linkspeed = linkspeed;
-        callback(rval);
-      });
-    });
-  }
-
-  function getConnectionInfoICS(callback) {
-    doStringCommand("SIGNAL_POLL", function(reply) {
-      if (!reply) {
-        callback(null);
-        return;
-      }
-
-      let rval = {};
-      var lines = reply.split("\n");
-      for (let i = 0; i < lines.length; ++i) {
-        let [key, value] = lines[i].split("=");
-        switch (key.toUpperCase()) {
-          case "RSSI":
-            rval.rssi = value | 0;
-            break;
-          case "LINKSPEED":
-            rval.linkspeed = value | 0;
-            break;
-          default:
-            // Ignore.
-        }
-      }
-
-      callback(rval);
-    });
-  }
-
-  function getMacAddressCommand(callback) {
-    doStringCommand("DRIVER MACADDR", function(reply) {
-      if (reply)
-        reply = reply.split(" ")[2]; // Format: Macaddr = XX.XX.XX.XX.XX.XX
-      callback(reply);
-    });
-  }
-
-  function setPowerModeCommandICS(mode, callback) {
-    doBooleanCommand("DRIVER POWERMODE " + (mode === "AUTO" ? 0 : 1), "OK", callback);
-  }
-
-  function setPowerModeCommandJB(mode, callback) {
-    doBooleanCommand("SET ps " + (mode === "AUTO" ? 1 : 0), "OK", callback);
-  }
-
-  function getPowerModeCommand(callback) {
-    doStringCommand("DRIVER GETPOWER", function(reply) {
-      if (reply)
-        reply = (reply.split()[2]|0); // Format: powermode = XX
-      callback(reply);
-    });
-  }
-
-  function setNumAllowedChannelsCommand(numChannels, callback) {
-    doBooleanCommand("DRIVER SCAN-CHANNELS " + numChannels, "OK", callback);
-  }
-
-  function getNumAllowedChannelsCommand(callback) {
-    doStringCommand("DRIVER SCAN-CHANNELS", function(reply) {
-      if (reply)
-        reply = (reply.split()[2]|0); // Format: Scan-Channels = X
-      callback(reply);
-    });
-  }
-
-  function setBluetoothCoexistenceModeCommand(mode, callback) {
-    doBooleanCommand("DRIVER BTCOEXMODE " + mode, "OK", callback);
-  }
-
-  function setBluetoothCoexistenceScanModeCommand(mode, callback) {
-    doBooleanCommand("DRIVER BTCOEXSCAN-" + (mode ? "START" : "STOP"), "OK", callback);
-  }
-
-  function saveConfigCommand(callback) {
-    // Make sure we never write out a value for AP_SCAN other than 1
-    doBooleanCommand("AP_SCAN 1", "OK", function(ok) {
-      doBooleanCommand("SAVE_CONFIG", "OK", callback);
-    });
-  }
-
-  function reloadConfigCommand(callback) {
-    doBooleanCommand("RECONFIGURE", "OK", callback);
-  }
-
-  function setScanResultHandlingCommand(mode, callback) {
-    doBooleanCommand("AP_SCAN " + mode, "OK", callback);
-  }
-
-  function addToBlacklistCommand(bssid, callback) {
-    doBooleanCommand("BLACKLIST " + bssid, "OK", callback);
-  }
-
-  function clearBlacklistCommand(callback) {
-    doBooleanCommand("BLACKLIST clear", "OK", callback);
-  }
-
-  function setSuspendOptimizationsCommand(enabled, callback) {
-    doBooleanCommand("DRIVER SETSUSPENDOPT " + (enabled ? 0 : 1), "OK", callback);
-  }
-
-  // Wrapper around libcutils.property_set that returns true if setting the
-  // value was successful.
-  // Note that the callback is not called asynchronously.
-  function setProperty(key, value, callback) {
-    let ok = true;
-    try {
-      libcutils.property_set(key, value);
-    } catch(e) {
-      ok = false;
-    }
-    callback(ok);
-  }
-
-  function enableInterface(ifname, callback) {
-    controlMessage({ cmd: "ifc_enable", ifname: ifname }, function(data) {
-      callback(!data.status);
-    });
-  }
-
-  function disableInterface(ifname, callback) {
-    controlMessage({ cmd: "ifc_disable", ifname: ifname }, function(data) {
-      callback(!data.status);
-    });
-  }
-
-  function addHostRoute(ifname, route, callback) {
-    controlMessage({ cmd: "ifc_add_host_route", ifname: ifname, route: route }, function(data) {
-      callback(!data.status);
-    });
-  }
-
-  function removeHostRoutes(ifname, callback) {
-    controlMessage({ cmd: "ifc_remove_host_routes", ifname: ifname }, function(data) {
-      callback(!data.status);
-    });
-  }
-
-  function setDefaultRoute(ifname, route, callback) {
-    controlMessage({ cmd: "ifc_set_default_route", ifname: ifname, route: route }, function(data) {
-      callback(!data.status);
-    });
-  }
-
-  function getDefaultRoute(ifname, callback) {
-    controlMessage({ cmd: "ifc_get_default_route", ifname: ifname }, function(data) {
-      callback(!data.route);
-    });
-  }
-
-  function removeDefaultRoute(ifname, callback) {
-    controlMessage({ cmd: "ifc_remove_default_route", ifname: ifname }, function(data) {
-      callback(!data.status);
-    });
-  }
-
-  function resetConnections(ifname, callback) {
-    controlMessage({ cmd: "ifc_reset_connections", ifname: ifname }, function(data) {
-      callback(!data.status);
-    });
+    wifiCommand.doSetScanMode(setActive, callback);
   }
 
   var httpProxyConfig = Object.create(null);
 
   /**
    * Given a network, configure http proxy when using wifi.
    * @param network A network object to update http proxy
    * @param info Info should have following field:
@@ -708,122 +351,53 @@ var WifiManager = (function() {
 
       // If the ssid of current connection is the same as configured ssid
       // It means we need update current connection to use static IP address.
       if (setNetworkKey == curNetworkKey) {
         // Use configureInterface directly doesn't work, the network iterface
         // and routing table is changed but still cannot connect to network
         // so the workaround here is disable interface the enable again to
         // trigger network reconnect with static ip.
-        disableInterface(manager.ifname, function (ok) {
-          enableInterface(manager.ifname, function (ok) {
+        netUtil.disableInterface(manager.ifname, function (ok) {
+          netUtil.enableInterface(manager.ifname, function (ok) {
           });
         });
       }
     });
   }
 
   var dhcpInfo = null;
-  function runDhcp(ifname) {
-    debug("Run Dhcp");
-    controlMessage({ cmd: "dhcp_do_request", ifname: ifname }, function(data) {
-      dhcpInfo = data.status ? null : data;
-      runIpConfig(ifname, dhcpInfo);
-    });
-  }
 
   function runStaticIp(ifname, key) {
     debug("Run static ip");
 
     // Read static ip information from settings.
     let staticIpInfo;
 
     if (!(key in staticIpConfig))
       return;
 
     staticIpInfo = staticIpConfig[key];
 
     // Stop dhcpd when use static IP
     if (dhcpInfo != null) {
-      stopDhcp(manager.ifname, function() {});
+      netUtil.stopDhcp(manager.ifname, function() {});
     }
 
     // Set ip, mask length, gateway, dns to network interface
-    configureInterface(ifname,
-                       staticIpInfo.ipaddr,
-                       staticIpInfo.maskLength,
-                       staticIpInfo.gateway,
-                       staticIpInfo.dns1,
-                       staticIpInfo.dns2, function (data) {
-      runIpConfig(ifname, staticIpInfo);
-    });
-  }
-
-  function stopProcess(service, process, callback) {
-    var count = 0;
-    var timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
-    function tick() {
-      let result = libcutils.property_get(service);
-      if (result === null) {
-        callback();
-        return;
-      }
-      if (result === "stopped" || ++count >= 5) {
-        // Either we succeeded or ran out of time.
-        timer = null;
-        callback();
-        return;
-      }
-
-      // Else it's still running, continue waiting.
-      timer.initWithCallback(tick, 1000, Ci.nsITimer.TYPE_ONE_SHOT);
-    }
-
-    setProperty("ctl.stop", process, tick);
-  }
-
-  function stopDhcp(ifname, callback) {
-    // This function does exactly what dhcp_stop does. Unforunately, if we call
-    // this function twice before the previous callback is returned. We may block
-    // our self waiting for the callback. It slows down the wifi startup procedure.
-    // Therefore, we have to roll our own version here.
-    let dhcpService = DHCP_PROP + "_" + ifname;
-    let suffix = (ifname.substr(0, 3) === "p2p") ? "p2p" : ifname;
-    let processName = DHCP + "_" + suffix;
-    stopProcess(dhcpService, processName, callback);
-  }
-
-  function releaseDhcpLease(ifname, callback) {
-    controlMessage({ cmd: "dhcp_release_lease", ifname: ifname }, function(data) {
-      dhcpInfo = null;
-      notify("dhcplost");
-      callback(!data.status);
-    });
-  }
-
-  function getDhcpError(callback) {
-    controlMessage({ cmd: "dhcp_get_errmsg" }, function(data) {
-      callback(data.error);
-    });
-  }
-
-  function configureInterface(ifname, ipaddr, mask, gateway, dns1, dns2, callback) {
-    let message = { cmd: "ifc_configure", ifname: ifname,
-                     ipaddr: ipaddr, mask: mask, gateway: gateway,
-                     dns1: dns1, dns2: dns2};
-    controlMessage(message, function(data) {
-      callback(!data.status);
-    });
-  }
-
-  function runDhcpRenew(ifname, callback) {
-    controlMessage({ cmd: "dhcp_do_request", ifname: ifname }, function(data) {
-      if (!data.status)
-        dhcpInfo = data;
-      callback(data.status ? null : data);
+    netUtil.configureInterface( { ifname: ifname,
+                                  ipaddr: staticIpInfo.ipaddr,
+                                  mask: staticIpInfo.maskLength,
+                                  gateway: staticIpInfo.gateway,
+                                  dns1: staticIpInfo.dns1,
+                                  dns2: staticIpInfo.dns2 }, function (data) {
+      netUtil.runIpConfig(ifname, staticIpInfo, function(data) {
+        dhcpInfo = data.info;
+        notify("networkconnected", data);
+      });
     });
   }
 
   var suppressEvents = false;
   function notify(eventName, eventObject) {
     if (suppressEvents)
       return;
     var handler = manager["on" + eventName];
@@ -928,43 +502,48 @@ var WifiManager = (function() {
       return;
     }
     if (connectTries++ < 3) {
       // Try again in 5 seconds.
       if (!retryTimer)
         retryTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
 
       retryTimer.initWithCallback(function(timer) {
-        connectToSupplicant(connectCallback);
+        wifiCommand.connectToSupplicant(connectCallback);
       }, 5000, Ci.nsITimer.TYPE_ONE_SHOT);
       return;
     }
 
     retryTimer = null;
     connectTries = 0;
     notify("supplicantlost", { success: false });
   }
 
   manager.connectionDropped = function(callback) {
     // Reset network interface when connection drop
-    configureInterface(manager.ifname, 0, 0, 0, 0, 0, function (data) {
+    netUtil.configureInterface( { ifname: manager.ifname,
+                                  ipaddr: 0,
+                                  mask: 0,
+                                  gateway: 0,
+                                  dns1: 0,
+                                  dns2: 0 }, function (data) {
     });
 
     // If we got disconnected, kill the DHCP client in preparation for
     // reconnection.
-    resetConnections(manager.ifname, function() {
-      stopDhcp(manager.ifname, function() {
+    netUtil.resetConnections(manager.ifname, function() {
+      netUtil.stopDhcp(manager.ifname, function() {
         callback();
       });
     });
   }
 
   manager.start = function() {
     debug("detected SDK version " + sdkVersion);
-    connectToSupplicant(connectCallback);
+    wifiCommand.connectToSupplicant(connectCallback);
   }
 
   function onconnected() {
     // For now we do our own DHCP. In the future, this should be handed
     // off to the Network Manager.
     let currentNetwork = Object.create(null);
     currentNetwork.netId = manager.connectionInfo.id;
 
@@ -972,47 +551,19 @@ var WifiManager = (function() {
       let key = getNetworkKey(currentNetwork);
       if (staticIpConfig  &&
           (key in staticIpConfig) &&
           staticIpConfig[key].enabled) {
           debug("Run static ip");
           runStaticIp(manager.ifname, key);
           return;
       }
-      runDhcp(manager.ifname);
-    });
-  }
-
-  function runIpConfig(name, data) {
-    if (!data) {
-      debug("IP config failed to run");
-      notify("networkconnected", { info: data });
-      return;
-    }
-
-    setProperty("net." + name + ".dns1", ipToString(data.dns1),
-                function(ok) {
-      if (!ok) {
-        debug("Unable to set net.<ifname>.dns1");
-        return;
-      }
-      setProperty("net." + name + ".dns2", ipToString(data.dns2),
-                  function(ok) {
-        if (!ok) {
-          debug("Unable to set net.<ifname>.dns2");
-          return;
-        }
-        setProperty("net." + name + ".gw", ipToString(data.gateway),
-                    function(ok) {
-          if (!ok) {
-            debug("Unable to set net.<ifname>.gw");
-            return;
-          }
-          notify("networkconnected", { info: data });
-        });
+      netUtil.runDhcp(manager.ifname, function(data) {
+        dhcpInfo = data.info;
+        notify("networkconnected", data);
       });
     });
   }
 
   var supplicantStatesMap = (sdkVersion >= 15) ?
     ["DISCONNECTED", "INTERFACE_DISABLED", "INACTIVE", "SCANNING",
      "AUTHENTICATING", "ASSOCIATING", "ASSOCIATED", "FOUR_WAY_HANDSHAKE",
      "GROUP_HANDSHAKE", "COMPLETED"]
@@ -1182,33 +733,24 @@ var WifiManager = (function() {
     if (eventData.indexOf("WPS-OVERLAP-DETECTED") === 0) {
       notifyStateChange({ state: "WPS_OVERLAP_DETECTED", BSSID: null, id: -1 });
       return true;
     }
     // Unknown event.
     return true;
   }
 
-  function killSupplicant(callback) {
-    // It is interesting to note that this function does exactly what
-    // wifi_stop_supplicant does. Unforunately, on the Galaxy S2, Samsung
-    // changed that function in a way that means that it doesn't recognize
-    // wpa_supplicant as already running. Therefore, we have to roll our own
-    // version here.
-    stopProcess(SUPP_PROP, WPA_SUPPLICANT, callback);
-  }
-
   function didConnectSupplicant(callback) {
     waitForEvent();
 
     // Load up the supplicant state.
     getDebugEnabled(function(ok) {
       syncDebug();
     });
-    statusCommand(function(status) {
+    wifiCommand.status(function(status) {
       parseStatus(status);
       notify("supplicantconnection");
       callback();
     });
   }
 
   function prepareForStartup(callback) {
     let status = libcutils.property_get(DHCP_PROP + "_" + manager.ifname);
@@ -1225,18 +767,18 @@ var WifiManager = (function() {
     // start, so we hand-roll it here.
     function tryStopSupplicant () {
       let status = libcutils.property_get(SUPP_PROP);
       if (status !== "running") {
         callback();
         return;
       }
       suppressEvents = true;
-      killSupplicant(function() {
-        disableInterface(manager.ifname, function (ok) {
+      wifiCommand.killSupplicant(function() {
+        netUtil.disableInterface(manager.ifname, function (ok) {
           suppressEvents = false;
           callback();
         });
       });
     }
   }
 
   // Initial state.
@@ -1300,27 +842,27 @@ var WifiManager = (function() {
             if (status) {
               callback(status);
               manager.state = "UNINITIALIZED";
               return;
             }
 
             function doStartSupplicant() {
               cancelWaitForDriverReadyTimer();
-              startSupplicant(function (status) {
+              wifiCommand.startSupplicant(function (status) {
                 if (status < 0) {
                   unloadDriver(function() {
                     callback(status);
                   });
                   manager.state = "UNINITIALIZED";
                   return;
                 }
 
                 manager.supplicantStarted = true;
-                enableInterface(manager.ifname, function (ok) {
+                netUtil.enableInterface(manager.ifname, function (ok) {
                   callback(ok ? 0 : -1);
                 });
               });
             }
             // Driver startup on certain platforms takes longer than it takes for us
             // to return from loadDriver, so wait 2 seconds before starting
             // the supplicant to give it a chance to start.
             if (manager.driverDelay > 0) {
@@ -1330,22 +872,22 @@ var WifiManager = (function() {
             }
           });
         });
       });
     } else {
       // Note these following calls ignore errors. If we fail to kill the
       // supplicant gracefully, then we need to continue telling it to die
       // until it does.
-      terminateSupplicant(function (ok) {
+      wifiCommand.terminateSupplicant(function (ok) {
         manager.connectionDropped(function () {
-          stopSupplicant(function (status) {
-            closeSupplicantConnection(function () {
+          wifiCommand.stopSupplicant(function (status) {
+            wifiCommand.closeSupplicantConnection(function () {
               manager.state = "UNINITIALIZED";
-              disableInterface(manager.ifname, function (ok) {
+              netUtil.disableInterface(manager.ifname, function (ok) {
                 unloadDriver(callback);
               });
             });
           });
         });
       });
     }
   }
@@ -1395,33 +937,33 @@ var WifiManager = (function() {
           }
           manager.tetheringState = "UNINITIALIZED";
           callback();
         });
       });
     }
   }
 
-  manager.disconnect = disconnectCommand;
-  manager.reconnect = reconnectCommand;
-  manager.reassociate = reassociateCommand;
+  manager.disconnect = wifiCommand.disconnect;
+  manager.reconnect = wifiCommand.reconnect;
+  manager.reassociate = wifiCommand.reassociate;
 
   var networkConfigurationFields = [
     "ssid", "bssid", "psk", "wep_key0", "wep_key1", "wep_key2", "wep_key3",
     "wep_tx_keyidx", "priority", "key_mgmt", "scan_ssid", "disabled",
     "identity", "password", "auth_alg", "phase1", "phase2", "eap", "pin",
     "pcsc"
   ];
 
   manager.getNetworkConfiguration = function(config, callback) {
     var netId = config.netId;
     var done = 0;
     for (var n = 0; n < networkConfigurationFields.length; ++n) {
       let fieldName = networkConfigurationFields[n];
-      getNetworkVariableCommand(netId, fieldName, function(value) {
+      wifiCommand.getNetworkVariable(netId, fieldName, function(value) {
         if (value !== null)
           config[fieldName] = value;
         if (++done == networkConfigurationFields.length)
           callback(config);
       });
     }
   }
   manager.setNetworkConfiguration = function(config, callback) {
@@ -1435,30 +977,30 @@ var WifiManager = (function() {
           // supplicant, and often we have a star in our config. In that case,
           // we need to avoid overwriting the correct password with a *.
           (fieldName === "password" ||
            fieldName === "wep_key0" ||
            fieldName === "psk") &&
           config[fieldName] === '*') {
         ++done;
       } else {
-        setNetworkVariableCommand(netId, fieldName, config[fieldName], function(ok) {
+        wifiCommand.setNetworkVariable(netId, fieldName, config[fieldName], function(ok) {
           if (!ok)
             ++errors;
           if (++done == networkConfigurationFields.length)
             callback(errors == 0);
         });
       }
     }
     // If config didn't contain any of the fields we want, don't lose the error callback.
     if (done == networkConfigurationFields.length)
       callback(false);
   }
   manager.getConfiguredNetworks = function(callback) {
-    listNetworksCommand(function (reply) {
+    wifiCommand.listNetworks(function (reply) {
       var networks = Object.create(null);
       var lines = reply.split("\n");
       if (lines.length === 1) {
         // We need to make sure we call the callback even if there are no
         // configured networks.
         callback(networks);
         return;
       }
@@ -1481,52 +1023,45 @@ var WifiManager = (function() {
           break;
         }
         manager.getNetworkConfiguration(config, function (ok) {
             if (!ok)
               ++errors;
             if (++done == lines.length - 1) {
               if (errors) {
                 // If an error occured, delete the new netId.
-                removeNetworkCommand(netId, function() {
+                wifiCommand.removeNetwork(netId, function() {
                   callback(null);
                 });
               } else {
                 callback(networks);
               }
             }
         });
       }
     });
   }
   manager.addNetwork = function(config, callback) {
-    addNetworkCommand(function (netId) {
+    wifiCommand.addNetwork(function (netId) {
       config.netId = netId;
       manager.setNetworkConfiguration(config, function (ok) {
         if (!ok) {
-          removeNetworkCommand(netId, function() { callback(false); });
+          wifiCommand.removeNetwork(netId, function() { callback(false); });
           return;
         }
 
         callback(ok);
       });
     });
   }
   manager.updateNetwork = function(config, callback) {
     manager.setNetworkConfiguration(config, callback);
   }
   manager.removeNetwork = function(netId, callback) {
-    removeNetworkCommand(netId, callback);
-  }
-
-  function ipToString(n) {
-    return String((n >>  0) & 0xFF) + "." +
-                 ((n >>  8) & 0xFF) + "." +
-                 ((n >> 16) & 0xFF) + "." +
-                 ((n >> 24) & 0xFF);
+    wifiCommand.removeNetwork(netId, callback);
   }
 
   function stringToIp(string) {
     let ip = 0;
     let start, end = -1;
     for (let i = 0; i < 4; i++) {
       start = end + 1;
       end = string.indexOf(".", start);
@@ -1557,48 +1092,48 @@ var WifiManager = (function() {
     let mask = 0;
     for (let i = 0; i < len; ++i) {
       mask |= (0x80000000 >> i);
     }
     return ntohl(mask);
   }
 
   manager.saveConfig = function(callback) {
-    saveConfigCommand(callback);
+    wifiCommand.saveConfig(callback);
   }
   manager.enableNetwork = function(netId, disableOthers, callback) {
-    enableNetworkCommand(netId, disableOthers, callback);
+    wifiCommand.enableNetwork(netId, disableOthers, callback);
   }
   manager.disableNetwork = function(netId, callback) {
-    disableNetworkCommand(netId, callback);
+    wifiCommand.disableNetwork(netId, callback);
   }
-  manager.getMacAddress = getMacAddressCommand;
-  manager.getScanResults = scanResultsCommand;
+  manager.getMacAddress = wifiCommand.getMacAddress;
+  manager.getScanResults = wifiCommand.scanResults;
   manager.setScanMode = function(mode, callback) {
-    setScanModeCommand(mode === "active", callback);
+    setScanMode(mode === "active", callback); // Use our own version.
   }
-  manager.setBackgroundScan = setBackgroundScan;
-  manager.scan = scanCommand;
-  manager.wpsPbc = wpsPbcCommand;
-  manager.wpsPin = wpsPinCommand;
-  manager.wpsCancel = wpsCancelCommand;
+  manager.setBackgroundScan = setBackgroundScan; // Use our own version.
+  manager.scan = scan; // Use our own version.
+  manager.wpsPbc = wifiCommand.wpsPbc;
+  manager.wpsPin = wifiCommand.wpsPin;
+  manager.wpsCancel = wifiCommand.wpsCancel;
   manager.setPowerMode = (sdkVersion >= 16)
-                         ? setPowerModeCommandJB
-                         : setPowerModeCommandICS;
+                         ? wifiCommand.setPowerModeJB
+                         : wifiCommand.setPowerModeICS;
   manager.getHttpProxyNetwork = getHttpProxyNetwork;
   manager.setHttpProxy = setHttpProxy;
   manager.configureHttpProxy = configureHttpProxy;
-  manager.setSuspendOptimizations = setSuspendOptimizationsCommand;
+  manager.setSuspendOptimizations = wifiCommand.setSuspendOptimizations;
   manager.setStaticIpMode = setStaticIpMode;
-  manager.getRssiApprox = getRssiApproxCommand;
-  manager.getLinkSpeed = getLinkSpeedCommand;
+  manager.getRssiApprox = wifiCommand.getRssiApprox;
+  manager.getLinkSpeed = wifiCommand.getLinkSpeed;
   manager.getDhcpInfo = function() { return dhcpInfo; }
   manager.getConnectionInfo = (sdkVersion >= 15)
-                              ? getConnectionInfoICS
-                              : getConnectionInfoGB;
+                              ? wifiCommand.getConnectionInfoICS
+                              : wifiCommand.getConnectionInfoGB;
 
   manager.isHandShakeState = function(state) {
     switch (state) {
       case "AUTHENTICATING":
       case "ASSOCIATING":
       case "ASSOCIATED":
       case "FOUR_WAY_HANDSHAKE":
       case "GROUP_HANDSHAKE":
--- a/dom/wifi/moz.build
+++ b/dom/wifi/moz.build
@@ -17,16 +17,21 @@ MODULE = 'dom'
 
 EXTRA_COMPONENTS += [
     'DOMWifiManager.js',
     'DOMWifiManager.manifest',
     'WifiWorker.js',
     'WifiWorker.manifest',
 ]
 
+EXTRA_JS_MODULES += [
+    'WifiCommand.jsm',
+    'WifiNetUtil.jsm',
+]
+
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
     CPP_SOURCES = [
         'NetUtils.cpp',
         'WifiProxyService.cpp',
         'WifiUtils.cpp',
     ]
 
 LIBXUL_LIBRARY = True