Bug 787421 - NetworkManager implementation. r=philikon
authorVincent Chang <vchang@mozilla.com>
Thu, 13 Sep 2012 15:19:08 +0800
changeset 107965 baf1182b6924c30251c909316712e3707402af97
parent 107964 c614f656bc13045bbbea3ba9298e067dc693b3e9
child 107966 598c1564bf418fb461a8a66523eda2bb905c876c
push id15298
push userryanvm@gmail.com
push dateTue, 25 Sep 2012 01:50:21 +0000
treeherdermozilla-inbound@3b1d2d4be337 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersphilikon
bugs787421
milestone18.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 787421 - NetworkManager implementation. r=philikon
dom/system/gonk/NetworkManager.js
dom/system/gonk/net_worker.js
--- a/dom/system/gonk/NetworkManager.js
+++ b/dom/system/gonk/NetworkManager.js
@@ -17,22 +17,16 @@ const NETWORKINTERFACE_CID =
   Components.ID("{266c3edd-78f0-4512-8178-2d6fee2d35ee}");
 
 const DEFAULT_PREFERRED_NETWORK_TYPE = Ci.nsINetworkInterface.NETWORK_TYPE_WIFI;
 
 XPCOMUtils.defineLazyServiceGetter(this, "gSettingsService",
                                    "@mozilla.org/settingsService;1",
                                    "nsISettingsService");
 
-XPCOMUtils.defineLazyGetter(this, "gWifi", function () {
-  return Cc["@mozilla.org/telephony/system-worker-manager;1"]
-           .getService(Ci.nsIInterfaceRequestor)
-           .getInterface(Ci.nsIWifi);
-});
-
 const TOPIC_INTERFACE_STATE_CHANGED  = "network-interface-state-changed";
 const TOPIC_INTERFACE_REGISTERED     = "network-interface-registered";
 const TOPIC_INTERFACE_UNREGISTERED   = "network-interface-unregistered";
 const TOPIC_DEFAULT_ROUTE_CHANGED    = "network-default-route-changed";
 const TOPIC_MOZSETTINGS_CHANGED      = "mozsettings-changed";
 const TOPIC_XPCOM_SHUTDOWN           = "xpcom-shutdown";
 
 // TODO, get USB RNDIS interface name automatically.(see Bug 776212)
@@ -290,17 +284,16 @@ NetworkManager.prototype = {
   },
 
   handleWorkerMessage: function handleWorkerMessage(e) {
     let response = e.data;
     let id = response.id;
     let callback = this.controlCallbacks[id];
     if (callback) {
       callback.call(this, response);
-      delete this.controlCallbacks[id];
     }
     debug("NetworkManager received message from worker: " + JSON.stringify(e));
   },
 
   /**
    * Determine the active interface and configure it.
    */
   setAndConfigureActive: function setAndConfigureActive() {
@@ -435,19 +428,20 @@ NetworkManager.prototype = {
 
   tetheringSettings: {},
 
   handle: function handle(aName, aResult) {
     switch(aName) {
       case SETTINGS_USB_ENABLED:
         this.handleUSBTetheringToggle(aResult);
         break;
-      case SETTINGS_WIFI_ENABLED:
-        this.handleWifiTetheringToggle(aResult);
-        break;
+      // SETTINGS_WIFI_ENABLED is handled in WifiManager.js to deal with
+      // the interaction between wifi and wifi tethering settings. Also, we
+      // update tetheringSettings[SETTINGS_WIFI_ENABLED] in setWifiTethering
+      // function.
       case SETTINGS_WIFI_SSID:
       case SETTINGS_WIFI_SECURITY_TYPE:
       case SETTINGS_WIFI_SECURITY_PASSWORD:
       case SETTINGS_WIFI_IP:
       case SETTINGS_WIFI_PREFIX:
       case SETTINGS_WIFI_DHCPSERVER_STARTIP:
       case SETTINGS_WIFI_DHCPSERVER_ENDIP:
       case SETTINGS_USB_IP:
@@ -481,17 +475,17 @@ NetworkManager.prototype = {
 
   handleUSBTetheringToggle: function handleUSBTetheringToggle(enable) {
     if (this.tetheringSettings[SETTINGS_USB_ENABLED] == enable) {
       return;
     }
 
     if (!enable) {
       this.tetheringSettings[SETTINGS_USB_ENABLED] = false;
-      this.disableTethering(TETHERING_TYPE_USB);
+      this.setUSBFunction(false, USB_FUNCTION_ADB, this.setUSBFunctionResult);
       return;
     }
 
     if (this.active) {
       this._tetheringInterface[TETHERING_TYPE_USB].externalInterface = this.active.name
     } else {
       let mobile = this.getNetworkInterface(Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE);
       if (!mobile) {
@@ -502,77 +496,17 @@ NetworkManager.prototype = {
         };
         this.usbTetheringResultReport(params);
         debug("Can't enable usb tethering - no active network interface.");
         return;
       }
       this._tetheringInterface[TETHERING_TYPE_USB].externalInterface = mobile.name;
     }
     this.tetheringSettings[SETTINGS_USB_ENABLED] = true;
-    this.enableTethering(TETHERING_TYPE_USB);
-  },
-
-  handleWifiTetheringToggle: function handleWifiTetheringToggle(enable) {
-    if (this.tetheringSettings[SETTINGS_WIFI_ENABLED] == enable) {
-      return;
-    }
-
-    let mobile = this.getNetworkInterface(Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE);
-    if (!mobile) {
-      let params = {
-        enable: enable,
-        unload: false,
-        resultCode: NETD_COMMAND_ERROR,
-        resultReason: "Mobile interface is not registered"
-      };
-      this.wifiTetheringResultReport(params);
-      debug("Can't enable wifi tethering, MOBILE interface is not registered.");
-      return;
-    }
-    this._tetheringInterface[TETHERING_TYPE_WIFI].externalInterface = mobile.name;
-
-    if (enable) {
-      this.tetheringSettings[SETTINGS_WIFI_ENABLED] = true;
-      this.enableTethering(TETHERING_TYPE_WIFI);
-    } else {
-      this.tetheringSettings[SETTINGS_WIFI_ENABLED] = false;
-      this.disableTethering(TETHERING_TYPE_WIFI);
-    }
-  },
-
-  // Callback to enable Wifi tethering.
-  setWifiTetheringEnabledResult: function setWifiTetheringEnabledResult(result, network) {
-    if (!network || result < 0) {
-      let params = {
-        enable: true,
-        unload: false,
-        resultCode: NETD_COMMAND_ERROR,
-        resultReason: "Can't enable wifi tethering"
-      };
-      debug("WifiWorker reports enable tethering result ..." + params.resultReason);
-      this.wifiTetheringResultReport(params);
-      return;
-    }
-    this._tetheringInterface[TETHERING_TYPE_WIFI].internalInterface = network.name;
-    this.setWifiTethering(true, this._tetheringInterface[TETHERING_TYPE_WIFI]);
-  },
-
-  // Callback to involve after wifi manager unloads wifi driver.
-  setWifiTetheringDisabledResult: function setWifiTetheringDisabledResult(result, network) {
-    if (result < 0) {
-      let params = {
-        enable: false,
-        unload: false,
-        resultCode: NETD_COMMAND_ERROR,
-        resultReason: "Can't enable wifi tethering"
-      };
-      debug("WifiWorker reports disable tethering result ..." + params.resultReason);
-      this.wifiTetheringResultReport(params);
-      return;
-    }
+    this.setUSBFunction(true, USB_FUNCTION_RNDIS, this.setUSBFunctionResult);
   },
 
   getWifiTetheringParameters: function getWifiTetheringParameters(enable, tetheringinterface) {
     let ssid;
     let securityType;
     let securityId;
     let interfaceIp;
     let prefix;
@@ -662,34 +596,79 @@ NetworkManager.prototype = {
       dns2: "",
       internalIfname: internalInterface,
       externalIfname: externalInterface,
       enable: enable,
       link: enable ? NETWORK_INTERFACE_UP : NETWORK_INTERFACE_DOWN
     };
   },
 
-  // Enable/disable WiFi tethering by sending commands to netd.
-  setWifiTethering: function setWifiTethering(enable, tetheringInterface) {
-    let params = this.getWifiTetheringParameters(enable, tetheringInterface);
+  get wifiTetheringEnabled() {
+    return this.tetheringSettings[SETTINGS_WIFI_ENABLED];
+  },
+
+  notifyError: function notifyError(resetSettings, callback, msg) {
+    if (resetSettings) {
+      let settingsLock = gSettingsService.createLock();
+      this.tetheringSettings[SETTINGS_WIFI_ENABLED] = false;
+      settingsLock.set("tethering.wifi.enabled", false, null);
+    }
 
-    if (params === null) {
-      params = {
-        enable: enable,
-        resultCode: NETD_COMMAND_ERROR,
-        resultReason: "Invalid parameters"
-      };
-      (enable) ? (params.unload = true) : (params.unload = false);
-      this.wifiTetheringResultReport(params);
+    debug("setWifiTethering: " + (msg ? msg : "success"));
+
+    if (callback) {
+      callback.wifiTetheringEnabledChange(msg);
+    }
+  },
+
+  // Enable/disable WiFi tethering by sending commands to netd.
+  setWifiTethering: function setWifiTethering(enable, network, callback) {
+    if (this.tetheringSettings[SETTINGS_WIFI_ENABLED] == enable) {
+      this.notifyError(false, callback, "no change");
       return;
     }
+
+    if (!network) {
+      this.notifyError(true, callback, "invalid network information");
+      return;
+    }
+    this._tetheringInterface[TETHERING_TYPE_WIFI].internalInterface = network.name;
+
+    let mobile = this.getNetworkInterface(Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE);
+    if (!mobile) {
+      this.notifyError(true, callback, "mobile interface is not registered");
+      return;
+    }
+    this._tetheringInterface[TETHERING_TYPE_WIFI].externalInterface = mobile.name;
+
+    let params = this.getWifiTetheringParameters(enable, this._tetheringInterface[TETHERING_TYPE_WIFI]);
+    if (!params) {
+      this.notifyError(true, callback, "invalid parameters");
+      return;
+    }
+
     params.cmd = "setWifiTethering";
     // The callback function in controlMessage may not be fired immediately.
     params.isAsync = true;
-    this.controlMessage(params, this.wifiTetheringResultReport);
+    this.controlMessage(params, function setWifiTetheringResult(data) {
+      let code = data.resultCode;
+      let reason = data.resultReason;
+      let enable = data.enable;
+      let enableString = enable ? "Enable" : "Disable";
+
+      debug(enableString + " Wifi tethering result: Code " + code + " reason " + reason);
+      // Update settings status.
+      this.tetheringSettings[SETTINGS_WIFI_ENABLED] = enable;
+
+      if (isError(code)) {
+        this.notifyError(true, callback, "netd command error");
+      } else {
+        this.notifyError(false, callback, null);
+      }
+    }.bind(this));
   },
 
   // Enable/disable USB tethering by sending commands to netd.
   setUSBTethering: function setUSBTethering(enable, tetheringInterface) {
     let params = this.getUSBTetheringParameters(enable, tetheringInterface);
 
     if (params === null) {
       params = {
@@ -703,39 +682,16 @@ NetworkManager.prototype = {
     }
 
     params.cmd = "setUSBTethering";
     // The callback function in controlMessage may not be fired immediately.
     params.isAsync = true;
     this.controlMessage(params, this.usbTetheringResultReport);
   },
 
-  // Send enable tehtering request to peripheral(WiFi/USB/Bluetooth) Manager module.
-  enableTethering: function enableTethering(type) {
-    if (type == TETHERING_TYPE_WIFI) {
-      debug("Notify WifiWorker to help !!!");
-      gWifi.setWifiTethering(true, this.setWifiTetheringEnabledResult.bind(this));
-    } else if (type == TETHERING_TYPE_USB) {
-      debug("Notify USB device manager to help !!!");
-      this.setUSBFunction(true, USB_FUNCTION_RNDIS, this.setUSBFunctionResult);
-    } else {
-      debug("Fatal error !!! Unsupported type.");
-    }
-  },
-
-  disableTethering: function disableTethering(type) {
-    if (type == TETHERING_TYPE_WIFI) {
-      this.setWifiTethering(false, this._tetheringInterface[TETHERING_TYPE_WIFI]);
-    } else if (type == TETHERING_TYPE_USB) {
-      this.setUSBFunction(false, USB_FUNCTION_ADB, this.setUSBFunctionResult);
-    } else {
-      debug("Fatal error !!! Unsupported type.");
-    }
-  },
-
   setUSBFunctionResult: function setUSBFunctionResult(data) {
     let result = data.result;
     let enable = data.enable;
     if (result) {
       this.setUSBTethering(enable, this._tetheringInterface[TETHERING_TYPE_USB]);
     } else {
       let params = {
         enable: false,
@@ -762,39 +718,16 @@ NetworkManager.prototype = {
       params.report = false;
     }
 
     // The callback function in controlMessage may not be fired immediately.
     params.isAsync = true;
     this.controlMessage(params, callback);
   },
 
-  wifiTetheringResultReport: function wifiTetheringResultReport(data) {
-    let code = data.resultCode;
-    let reason = data.resultReason;
-    let enable = data.enable;
-    let enableString = enable ? "Enable" : "Disable";
-    let unload = data.unload;
-    let settingsLock = gSettingsService.createLock();
-
-    debug(enableString + " Wifi tethering result: Code " + code + " reason " + reason);
-    // Unload wifi driver when
-    // 1. We have sent disable tethering commands to netd and switch wifi to station mode.
-    // 2. We fail to enable wifi tethering.
-    if (unload) {
-      gWifi.setWifiTethering(false, this.setWifiTetheringDisabledResult.bind(this));
-    }
-
-    // Disable tethering settings when fail to enable it.
-    if (isError(code)) {
-      this.tetheringSettings[SETTINGS_WIFI_ENABLED] = false;
-      settingsLock.set("tethering.wifi.enabled", false, null);
-    }
-  },
-
   usbTetheringResultReport: function usbTetheringResultReport(data) {
     let code = data.resultCode;
     let reason = data.resultReason;
     let enable = data.enable;
     let enableString = enable ? "Enable" : "Disable";
     let settingsLock = gSettingsService.createLock();
 
     debug(enableString + " USB tethering result: Code " + code + " reason " + reason);
--- a/dom/system/gonk/net_worker.js
+++ b/dom/system/gonk/net_worker.js
@@ -54,43 +54,28 @@ function isComplete(code) {
   return (type != NETD_COMMAND_PROCEEDING);
 }
 
 let gWifiFailChain = [stopSoftAP,
                       setIpForwardingEnabled,
                       stopTethering];
 
 function wifiTetheringFail(params) {
-  let unload = false;
-
-  // Unload wifi driver when failing to enable tethering.
-  if (params.enable) {
-    unload = true;
-  }
-  params.unload = unload;
   // Notify the main thread.
   postMessage(params);
 
   // If one of the stages fails, we try roll back to ensure
   // we don't leave the network systems in limbo.
 
   // This parameter is used to disable ipforwarding.
   params.enable = false;
   chain(params, gWifiFailChain, null);
 }
 
 function wifiTetheringSuccess(params) {
-  let unload = false;
-
-  // Unload wifi driver after switch wifi to station mode.
-  if (!params.enable) {
-    unload = true;
-  }
-
-  params.unload = unload;
   // Notify the main thread.
   postMessage(params);
   return true;
 }
 
 let gUSBFailChain = [stopSoftAP,
                      setIpForwardingEnabled,
                      stopTethering];