Bug 1139736 - Part 2: define network debug function dynamically. r=echen
authorJessica Jong <jjong@mozilla.com>
Wed, 18 Mar 2015 17:38:20 +0800
changeset 234312 883bea484ad4104d3149a9a8ec6a6b79566ab9fc
parent 234311 846fa7616502973e5d7bbbfea3443e133402c5c5
child 234313 c7e5c48efa1151836be1b1769edfae97c1b5260e
push id28441
push userkwierso@gmail.com
push dateWed, 18 Mar 2015 22:53:16 +0000
treeherdermozilla-central@09f6642f7d24 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersechen
bugs1139736
milestone39.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 1139736 - Part 2: define network debug function dynamically. r=echen
dom/system/gonk/NetworkManager.js
dom/system/gonk/NetworkService.js
dom/system/gonk/TetheringService.js
--- a/dom/system/gonk/NetworkManager.js
+++ b/dom/system/gonk/NetworkManager.js
@@ -33,38 +33,48 @@ XPCOMUtils.defineLazyServiceGetter(this,
 
 const TOPIC_INTERFACE_REGISTERED     = "network-interface-registered";
 const TOPIC_INTERFACE_UNREGISTERED   = "network-interface-unregistered";
 const TOPIC_ACTIVE_CHANGED           = "network-active-changed";
 const TOPIC_PREF_CHANGED             = "nsPref:changed";
 const TOPIC_XPCOM_SHUTDOWN           = "xpcom-shutdown";
 const TOPIC_CONNECTION_STATE_CHANGED = "network-connection-state-changed";
 const PREF_MANAGE_OFFLINE_STATUS     = "network.gonk.manage-offline-status";
+const PREF_NETWORK_DEBUG_ENABLED     = "network.debugging.enabled";
 
 const IPV4_ADDRESS_ANY                 = "0.0.0.0";
 const IPV6_ADDRESS_ANY                 = "::0";
 
 const IPV4_MAX_PREFIX_LENGTH           = 32;
 const IPV6_MAX_PREFIX_LENGTH           = 128;
 
 // Connection Type for Network Information API
 const CONNECTION_TYPE_CELLULAR  = 0;
 const CONNECTION_TYPE_BLUETOOTH = 1;
 const CONNECTION_TYPE_ETHERNET  = 2;
 const CONNECTION_TYPE_WIFI      = 3;
 const CONNECTION_TYPE_OTHER     = 4;
 const CONNECTION_TYPE_NONE      = 5;
 
-let DEBUG = false;
+let debug;
+function updateDebug() {
+  let debugPref = false; // set default value here.
+  try {
+    debugPref = debugPref || Services.prefs.getBoolPref(PREF_NETWORK_DEBUG_ENABLED);
+  } catch (e) {}
 
-// Read debug setting from pref.
-try {
-  let debugPref = Services.prefs.getBoolPref("network.debugging.enabled");
-  DEBUG = DEBUG || debugPref;
-} catch (e) {}
+  if (debugPref) {
+    debug = function(s) {
+      dump("-*- NetworkManager: " + s + "\n");
+    };
+  } else {
+    debug = function(s) {};
+  }
+}
+updateDebug();
 
 function defineLazyRegExp(obj, name, pattern) {
   obj.__defineGetter__(name, function() {
     delete obj[name];
     return obj[name] = new RegExp(pattern);
   });
 }
 
@@ -116,16 +126,17 @@ function NetworkManager() {
 
   try {
     this._manageOfflineStatus =
       Services.prefs.getBoolPref(PREF_MANAGE_OFFLINE_STATUS);
   } catch(ex) {
     // Ignore.
   }
   Services.prefs.addObserver(PREF_MANAGE_OFFLINE_STATUS, this, false);
+  Services.prefs.addObserver(PREF_NETWORK_DEBUG_ENABLED, this, false);
   Services.obs.addObserver(this, TOPIC_XPCOM_SHUTDOWN, false);
 
   this.setAndConfigureActive();
 
   ppmm.addMessageListener('NetworkInterfaceList:ListInterface', this);
 
   // Used in resolveHostname().
   defineLazyRegExp(this, "REGEXP_IPV4", "^\\d{1,3}(?:\\.\\d{1,3}){3}$");
@@ -142,23 +153,28 @@ NetworkManager.prototype = {
                                          Ci.nsIObserver,
                                          Ci.nsISettingsServiceCallback]),
 
   // nsIObserver
 
   observe: function(subject, topic, data) {
     switch (topic) {
       case TOPIC_PREF_CHANGED:
-        this._manageOfflineStatus =
-          Services.prefs.getBoolPref(PREF_MANAGE_OFFLINE_STATUS);
-        debug(PREF_MANAGE_OFFLINE_STATUS + " has changed to " + this._manageOfflineStatus);
+        if (data === PREF_NETWORK_DEBUG_ENABLED) {
+          updateDebug();
+        } else if (data === PREF_MANAGE_OFFLINE_STATUS) {
+          this._manageOfflineStatus =
+            Services.prefs.getBoolPref(PREF_MANAGE_OFFLINE_STATUS);
+          debug(PREF_MANAGE_OFFLINE_STATUS + " has changed to " + this._manageOfflineStatus);
+        }
         break;
       case TOPIC_XPCOM_SHUTDOWN:
         Services.obs.removeObserver(this, TOPIC_XPCOM_SHUTDOWN);
         Services.prefs.removeObserver(PREF_MANAGE_OFFLINE_STATUS, this);
+        Services.prefs.removeObserver(PREF_NETWORK_DEBUG_ENABLED, this);
         break;
     }
   },
 
   receiveMessage: function(aMsg) {
     switch (aMsg.name) {
       case "NetworkInterfaceList:ListInterface": {
         let excludeMms = aMsg.json.excludeMms;
@@ -710,18 +726,18 @@ NetworkManager.prototype = {
         retval.push(aRecord.getNextAddrAsString());
       }
 
       if (!retval.length) {
         deferred.reject(new Error("No valid address after DNS lookup!"));
         return;
       }
 
-      if (DEBUG) debug("hostname is resolved: " + hostname);
-      if (DEBUG) debug("Addresses: " + JSON.stringify(retval));
+      debug("hostname is resolved: " + hostname);
+      debug("Addresses: " + JSON.stringify(retval));
 
       deferred.resolve(retval);
     };
 
     // Bug 1058282 - Explicitly request ipv4 to get around 8.8.8.8 probe at
     // http://androidxref.com/4.3_r2.1/xref/bionic/libc/netbsd/net/getaddrinfo.c#1923
     //
     // Whenever MMS connection is the only network interface, there is no
@@ -848,19 +864,9 @@ let CaptivePortalDetectionHelper = (func
 XPCOMUtils.defineLazyGetter(NetworkManager.prototype, "mRil", function() {
   try {
     return Cc["@mozilla.org/ril;1"].getService(Ci.nsIRadioInterfaceLayer);
   } catch (e) {}
 
   return null;
 });
 
-this.NSGetFactory = XPCOMUtils.generateNSGetFactory([NetworkManager]);
-
-
-let debug;
-if (DEBUG) {
-  debug = function(s) {
-    dump("-*- NetworkManager: " + s + "\n");
-  };
-} else {
-  debug = function(s) {};
-}
+this.NSGetFactory = XPCOMUtils.generateNSGetFactory([NetworkManager]);
\ No newline at end of file
--- a/dom/system/gonk/NetworkService.js
+++ b/dom/system/gonk/NetworkService.js
@@ -10,16 +10,20 @@ Cu.import("resource://gre/modules/XPCOMU
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/NetUtil.jsm");
 Cu.import("resource://gre/modules/FileUtils.jsm");
 Cu.import("resource://gre/modules/Promise.jsm");
 
 const NETWORKSERVICE_CONTRACTID = "@mozilla.org/network/service;1";
 const NETWORKSERVICE_CID = Components.ID("{baec696c-c78d-42db-8b44-603f8fbfafb4}");
 
+const TOPIC_PREF_CHANGED             = "nsPref:changed";
+const TOPIC_XPCOM_SHUTDOWN           = "xpcom-shutdown";
+const PREF_NETWORK_DEBUG_ENABLED     = "network.debugging.enabled";
+
 XPCOMUtils.defineLazyServiceGetter(this, "gNetworkWorker",
                                    "@mozilla.org/network/worker;1",
                                    "nsINetworkWorker");
 
 // 1xx - Requested action is proceeding
 const NETD_COMMAND_PROCEEDING   = 100;
 // 2xx - Requested action has been successfully completed
 const NETD_COMMAND_OKAY         = 200;
@@ -30,37 +34,42 @@ const NETD_COMMAND_FAIL         = 400;
 const NETD_COMMAND_ERROR        = 500;
 // 6xx - Unsolicited broadcasts
 const NETD_COMMAND_UNSOLICITED  = 600;
 
 const WIFI_CTRL_INTERFACE = "wl0.1";
 
 const MANUAL_PROXY_CONFIGURATION = 1;
 
-let DEBUG = false;
+let debug;
+function updateDebug() {
+  let debugPref = false; // set default value here.
+  try {
+    debugPref = debugPref || Services.prefs.getBoolPref(PREF_NETWORK_DEBUG_ENABLED);
+  } catch (e) {}
 
-// Read debug setting from pref.
-try {
-  let debugPref = Services.prefs.getBoolPref("network.debugging.enabled");
-  DEBUG = DEBUG || debugPref;
-} catch (e) {}
+  if (debugPref) {
+    debug = function(s) {
+      dump("-*- NetworkService: " + s + "\n");
+    };
+  } else {
+    debug = function(s) {};
+  }
+}
+updateDebug();
 
 function netdResponseType(code) {
   return Math.floor(code / 100) * 100;
 }
 
 function isError(code) {
   let type = netdResponseType(code);
   return (type !== NETD_COMMAND_PROCEEDING && type !== NETD_COMMAND_OKAY);
 }
 
-function debug(msg) {
-  dump("-*- NetworkService: " + msg + "\n");
-}
-
 function Task(id, params, setupFunction) {
   this.id = id;
   this.params = params;
   this.setupFunction = setupFunction;
 }
 
 function NetworkWorkerRequestQueue(networkService) {
   this.networkService = networkService;
@@ -68,45 +77,45 @@ function NetworkWorkerRequestQueue(netwo
 }
 NetworkWorkerRequestQueue.prototype = {
   runQueue: function() {
     if (this.tasks.length === 0) {
       return;
     }
 
     let task = this.tasks[0];
-    if (DEBUG) debug("run task id: " + task.id);
+    debug("run task id: " + task.id);
 
     if (typeof task.setupFunction === 'function') {
       // If setupFunction returns false, skip sending to Network Worker but call
       // handleWorkerMessage() directly with task id, as if the response was
       // returned from Network Worker.
       if (!task.setupFunction()) {
         this.networkService.handleWorkerMessage({id: task.id});
         return;
       }
     }
 
     gNetworkWorker.postMessage(task.params);
   },
 
   enqueue: function(id, params, setupFunction) {
-    if (DEBUG) debug("enqueue id: " + id);
+    debug("enqueue id: " + id);
     this.tasks.push(new Task(id, params, setupFunction));
 
     if (this.tasks.length === 1) {
       this.runQueue();
     }
   },
 
   dequeue: function(id) {
-    if (DEBUG) debug("dequeue id: " + id);
+    debug("dequeue id: " + id);
 
     if (!this.tasks.length || this.tasks[0].id != id) {
-      if (DEBUG) debug("Id " + id + " is not on top of the queue");
+      debug("Id " + id + " is not on top of the queue");
       return;
     }
 
     this.tasks.shift();
     if (this.tasks.length > 0) {
       // Run queue on the next tick.
       Services.tm.currentThread.dispatch(() => {
         this.runQueue();
@@ -116,17 +125,17 @@ NetworkWorkerRequestQueue.prototype = {
 };
 
 
 /**
  * This component watches for network interfaces changing state and then
  * adjusts routes etc. accordingly.
  */
 function NetworkService() {
-  if(DEBUG) debug("Starting net_worker.");
+  debug("Starting net_worker.");
 
   let self = this;
 
   if (gNetworkWorker) {
     let networkListener = {
       onEvent: function(event) {
         self.handleWorkerMessage(event);
       }
@@ -134,30 +143,59 @@ function NetworkService() {
     gNetworkWorker.start(networkListener);
   }
   // Callbacks to invoke when a reply arrives from the net_worker.
   this.controlCallbacks = Object.create(null);
 
   this.addedRoutes = new Map();
   this.netWorkerRequestQueue = new NetworkWorkerRequestQueue(this);
   this.shutdown = false;
-  Services.obs.addObserver(this, "xpcom-shutdown", false);
+
+  Services.prefs.addObserver(PREF_NETWORK_DEBUG_ENABLED, this, false);
+  Services.obs.addObserver(this, TOPIC_XPCOM_SHUTDOWN, false);
 }
 
 NetworkService.prototype = {
   classID:   NETWORKSERVICE_CID,
   classInfo: XPCOMUtils.generateCI({classID: NETWORKSERVICE_CID,
                                     contractID: NETWORKSERVICE_CONTRACTID,
                                     classDescription: "Network Service",
                                     interfaces: [Ci.nsINetworkService]}),
-  QueryInterface: XPCOMUtils.generateQI([Ci.nsINetworkService]),
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsINetworkService,
+                                         Ci.nsIObserver]),
+
+  addedRoutes: null,
+
+  shutdown: false,
+
+  // nsIObserver
+
+  observe: function(subject, topic, data) {
+    switch (topic) {
+      case TOPIC_PREF_CHANGED:
+        if (data === PREF_NETWORK_DEBUG_ENABLED) {
+          updateDebug();
+        }
+        break;
+      case TOPIC_XPCOM_SHUTDOWN:
+        debug("NetworkService shutdown");
+        this.shutdown = true;
+        if (gNetworkWorker) {
+          gNetworkWorker.shutdown();
+          gNetworkWorker = null;
+        }
+
+        Services.obs.removeObserver(this, TOPIC_XPCOM_SHUTDOWN);
+        Services.prefs.removeObserver(PREF_NETWORK_DEBUG_ENABLED, this);
+        break;
+    }
+  },
 
   // Helpers
 
-  addedRoutes: null,
   idgen: 0,
   controlMessage: function(params, callback, setupFunction) {
     if (this.shutdown) {
       return;
     }
 
     let id = this.idgen++;
     params.id = id;
@@ -173,17 +211,17 @@ NetworkService.prototype = {
     }
 
     if (gNetworkWorker) {
       gNetworkWorker.postMessage(params);
     }
   },
 
   handleWorkerMessage: function(response) {
-    if(DEBUG) debug("NetworkManager received message from worker: " + JSON.stringify(response));
+    debug("NetworkManager received message from worker: " + JSON.stringify(response));
     let id = response.id;
     if (response.broadcast === true) {
       Services.obs.notifyObservers(null, response.topic, response.reason);
       return;
     }
     let callback = this.controlCallbacks[id];
     if (callback) {
       callback.call(this, response);
@@ -191,17 +229,17 @@ NetworkService.prototype = {
     }
 
     this.netWorkerRequestQueue.dequeue(id);
   },
 
   // nsINetworkService
 
   getNetworkInterfaceStats: function(networkName, callback) {
-    if(DEBUG) debug("getNetworkInterfaceStats for " + networkName);
+    debug("getNetworkInterfaceStats for " + networkName);
 
     let file = new FileUtils.File("/proc/net/dev");
     if (!file) {
       callback.networkStatsAvailable(false, 0, 0, Date.now());
       return;
     }
 
     NetUtil.asyncFetch2(file, function(inputStream, status) {
@@ -252,17 +290,17 @@ NetworkService.prototype = {
         return
       }
 
       self._setNetworkInterfaceAlarm(networkName, threshold, callback);
     });
   },
 
   _setNetworkInterfaceAlarm: function(networkName, threshold, callback) {
-    if(DEBUG) debug("setNetworkInterfaceAlarm for " + networkName + " at " + threshold + "bytes");
+    debug("setNetworkInterfaceAlarm for " + networkName + " at " + threshold + "bytes");
 
     let params = {
       cmd: "setNetworkInterfaceAlarm",
       ifname: networkName,
       threshold: threshold
     };
 
     params.report = true;
@@ -273,17 +311,17 @@ NetworkService.prototype = {
         return;
       }
 
       this._enableNetworkInterfaceAlarm(networkName, threshold, callback);
     });
   },
 
   _enableNetworkInterfaceAlarm: function(networkName, threshold, callback) {
-    if(DEBUG) debug("enableNetworkInterfaceAlarm for " + networkName + " at " + threshold + "bytes");
+    debug("enableNetworkInterfaceAlarm for " + networkName + " at " + threshold + "bytes");
 
     let params = {
       cmd: "enableNetworkInterfaceAlarm",
       ifname: networkName,
       threshold: threshold
     };
 
     params.report = true;
@@ -293,32 +331,32 @@ NetworkService.prototype = {
         callback.networkUsageAlarmResult(null);
         return;
       }
       callback.networkUsageAlarmResult(result.reason);
     });
   },
 
   _disableNetworkInterfaceAlarm: function(networkName, callback) {
-    if(DEBUG) debug("disableNetworkInterfaceAlarm for " + networkName);
+    debug("disableNetworkInterfaceAlarm for " + networkName);
 
     let params = {
       cmd: "disableNetworkInterfaceAlarm",
       ifname: networkName,
     };
 
     params.report = true;
 
     this.controlMessage(params, function(result) {
       callback(result);
     });
   },
 
   setWifiOperationMode: function(interfaceName, mode, callback) {
-    if(DEBUG) debug("setWifiOperationMode on " + interfaceName + " to " + mode);
+    debug("setWifiOperationMode on " + interfaceName + " to " + mode);
 
     let params = {
       cmd: "setWifiOperationMode",
       ifname: interfaceName,
       mode: mode
     };
 
     params.report = true;
@@ -337,45 +375,45 @@ NetworkService.prototype = {
       cmd: "removeNetworkRoute",
       ifname: network.name
     };
 
     this.controlMessage(options);
   },
 
   setDNS: function(networkInterface, callback) {
-    if (DEBUG) debug("Going DNS to " + networkInterface.name);
+    debug("Going DNS to " + networkInterface.name);
     let dnses = networkInterface.getDnses();
     let options = {
       cmd: "setDNS",
       ifname: networkInterface.name,
       domain: "mozilla." + networkInterface.name + ".doman",
       dnses: dnses
     };
     this.controlMessage(options, function(result) {
       callback.setDnsResult(result.success ? null : result.reason);
     });
   },
 
   setDefaultRoute: function(network, oldInterface, callback) {
-    if (DEBUG) debug("Going to change default route to " + network.name);
+    debug("Going to change default route to " + network.name);
     let gateways = network.getGateways();
     let options = {
       cmd: "setDefaultRoute",
       ifname: network.name,
       oldIfname: (oldInterface && oldInterface !== network) ? oldInterface.name : null,
       gateways: gateways
     };
     this.controlMessage(options, function(result) {
       callback.nativeCommandResult(!result.error);
     });
   },
 
   removeDefaultRoute: function(network) {
-    if(DEBUG) debug("Remove default route for " + network.name);
+    debug("Remove default route for " + network.name);
     let gateways = network.getGateways();
     let options = {
       cmd: "removeDefaultRoute",
       ifname: network.name,
       gateways: gateways
     };
     this.controlMessage(options);
   },
@@ -390,36 +428,36 @@ NetworkService.prototype = {
     switch (action) {
       case Ci.nsINetworkService.MODIFY_ROUTE_ADD:
         command = 'addHostRoute';
         break;
       case Ci.nsINetworkService.MODIFY_ROUTE_REMOVE:
         command = 'removeHostRoute';
         break;
       default:
-        if (DEBUG) debug('Unknown action: ' + action);
+        debug('Unknown action: ' + action);
         return Promise.reject();
     }
 
     let route = this._routeToString(interfaceName, host, prefixLength, gateway);
     let setupFunc = () => {
       let count = this.addedRoutes.get(route);
-      if (DEBUG) debug(command + ": " + route + " -> " + count);
+      debug(command + ": " + route + " -> " + count);
 
       // Return false if there is no need to send the command to network worker.
       if ((action == Ci.nsINetworkService.MODIFY_ROUTE_ADD && count) ||
           (action == Ci.nsINetworkService.MODIFY_ROUTE_REMOVE &&
            (!count || count > 1))) {
         return false;
       }
 
       return true;
     };
 
-    if (DEBUG) debug(command + " " + host + " on " + interfaceName);
+    debug(command + " " + host + " on " + interfaceName);
     let options = {
       cmd: command,
       ifname: interfaceName,
       gateway: gateway,
       prefixLength: prefixLength,
       ip: host
     };
 
@@ -446,67 +484,67 @@ NetworkService.prototype = {
         }
 
         aResolve();
       }, setupFunc);
     });
   },
 
   addSecondaryRoute: function(ifname, route) {
-    if(DEBUG) debug("Going to add route to secondary table on " + ifname);
+    debug("Going to add route to secondary table on " + ifname);
     let options = {
       cmd: "addSecondaryRoute",
       ifname: ifname,
       ip: route.ip,
       prefix: route.prefix,
       gateway: route.gateway
     };
     this.controlMessage(options);
   },
 
   removeSecondaryRoute: function(ifname, route) {
-    if(DEBUG) debug("Going to remove route from secondary table on " + ifname);
+    debug("Going to remove route from secondary table on " + ifname);
     let options = {
       cmd: "removeSecondaryRoute",
       ifname: ifname,
       ip: route.ip,
       prefix: route.prefix,
       gateway: route.gateway
     };
     this.controlMessage(options);
   },
 
   setNetworkProxy: function(network) {
     try {
       if (!network.httpProxyHost || network.httpProxyHost === "") {
         // Sets direct connection to internet.
         this.clearNetworkProxy();
 
-        if (DEBUG) debug("No proxy support for " + network.name + " network interface.");
+        debug("No proxy support for " + network.name + " network interface.");
         return;
       }
 
-      if (DEBUG) debug("Going to set proxy settings for " + network.name + " network interface.");
+      debug("Going to set proxy settings for " + network.name + " network interface.");
       // Sets manual proxy configuration.
       Services.prefs.setIntPref("network.proxy.type", MANUAL_PROXY_CONFIGURATION);
       // Do not use this proxy server for all protocols.
       Services.prefs.setBoolPref("network.proxy.share_proxy_settings", false);
       Services.prefs.setCharPref("network.proxy.http", network.httpProxyHost);
       Services.prefs.setCharPref("network.proxy.ssl", network.httpProxyHost);
       let port = network.httpProxyPort === 0 ? 8080 : network.httpProxyPort;
       Services.prefs.setIntPref("network.proxy.http_port", port);
       Services.prefs.setIntPref("network.proxy.ssl_port", port);
     } catch(ex) {
-        if (DEBUG) debug("Exception " + ex + ". Unable to set proxy setting for " +
+        debug("Exception " + ex + ". Unable to set proxy setting for " +
                          network.name + " network interface.");
     }
   },
 
   clearNetworkProxy: function() {
-    if (DEBUG) debug("Going to clear all network proxy.");
+    debug("Going to clear all network proxy.");
 
     Services.prefs.clearUserPref("network.proxy.type");
     Services.prefs.clearUserPref("network.proxy.share_proxy_settings");
     Services.prefs.clearUserPref("network.proxy.http");
     Services.prefs.clearUserPref("network.proxy.http_port");
     Services.prefs.clearUserPref("network.proxy.ssl");
     Services.prefs.clearUserPref("network.proxy.ssl_port");
   },
@@ -540,17 +578,17 @@ NetworkService.prototype = {
 
     // The callback function in controlMessage may not be fired immediately.
     this.controlMessage(config, function setWifiTetheringResult(data) {
       let code = data.resultCode;
       let reason = data.resultReason;
       let enable = data.enable;
       let enableString = enable ? "Enable" : "Disable";
 
-      if(DEBUG) debug(enableString + " Wifi tethering result: Code " + code + " reason " + reason);
+      debug(enableString + " Wifi tethering result: Code " + code + " reason " + reason);
 
       if (isError(code)) {
         callback.wifiTetheringEnabledChange("netd command error");
       } else {
         callback.wifiTetheringEnabledChange(null);
       }
     });
   },
@@ -560,29 +598,29 @@ NetworkService.prototype = {
     config.cmd = "setUSBTethering";
     // The callback function in controlMessage may not be fired immediately.
     this.controlMessage(config, function setUsbTetheringResult(data) {
       let code = data.resultCode;
       let reason = data.resultReason;
       let enable = data.enable;
       let enableString = enable ? "Enable" : "Disable";
 
-      if(DEBUG) debug(enableString + " USB tethering result: Code " + code + " reason " + reason);
+      debug(enableString + " USB tethering result: Code " + code + " reason " + reason);
 
       if (isError(code)) {
         callback.usbTetheringEnabledChange("netd command error");
       } else {
         callback.usbTetheringEnabledChange(null);
       }
     });
   },
 
   // Switch usb function by modifying property of persist.sys.usb.config.
   enableUsbRndis: function(enable, callback) {
-    if(DEBUG) debug("enableUsbRndis: " + enable);
+    debug("enableUsbRndis: " + enable);
 
     let params = {
       cmd: "enableUsbRndis",
       enable: enable
     };
     // Ask net work to report the result when this value is set to true.
     if (callback) {
       params.report = true;
@@ -604,17 +642,17 @@ NetworkService.prototype = {
       preExternalIfname: previous.externalIfname,
       curInternalIfname: current.internalIfname,
       curExternalIfname: current.externalIfname
     };
 
     this.controlMessage(params, function(data) {
       let code = data.resultCode;
       let reason = data.resultReason;
-      if(DEBUG) debug("updateUpStream result: Code " + code + " reason " + reason);
+      debug("updateUpStream result: Code " + code + " reason " + reason);
       callback.updateUpStreamResult(!isError(code), data.curExternalIfname);
     });
   },
 
   configureInterface: function(config, callback) {
     let params = {
       cmd: "configureInterface",
       ifname: config.ifname,
@@ -690,27 +728,11 @@ NetworkService.prototype = {
       cmd: "destroyNetwork",
       ifname: interfaceName
     };
 
     this.controlMessage(params, function(result) {
       callback.nativeCommandResult(!result.error);
     });
   },
-
-  shutdown: false,
-
-  observe: function observe(aSubject, aTopic, aData) {
-    switch (aTopic) {
-      case "xpcom-shutdown":
-        debug("NetworkService shutdown");
-        this.shutdown = true;
-        Services.obs.removeObserver(this, "xpcom-shutdown");
-        if (gNetworkWorker) {
-          gNetworkWorker.shutdown();
-          gNetworkWorker = null;
-        }
-        break;
-    }
-  },
 };
 
 this.NSGetFactory = XPCOMUtils.generateNSGetFactory([NetworkService]);
--- a/dom/system/gonk/TetheringService.js
+++ b/dom/system/gonk/TetheringService.js
@@ -38,17 +38,19 @@ XPCOMUtils.defineLazyGetter(this, "gRil"
 
   return null;
 });
 
 const TOPIC_INTERFACE_REGISTERED     = "network-interface-registered";
 const TOPIC_INTERFACE_UNREGISTERED   = "network-interface-unregistered";
 const TOPIC_MOZSETTINGS_CHANGED      = "mozsettings-changed";
 const TOPIC_CONNECTION_STATE_CHANGED = "network-connection-state-changed";
+const TOPIC_PREF_CHANGED             = "nsPref:changed";
 const TOPIC_XPCOM_SHUTDOWN           = "xpcom-shutdown";
+const PREF_NETWORK_DEBUG_ENABLED     = "network.debugging.enabled";
 
 const POSSIBLE_USB_INTERFACE_NAME = "rndis0,usb0";
 const DEFAULT_USB_INTERFACE_NAME  = "rndis0";
 const DEFAULT_3G_INTERFACE_NAME   = "rmnet0";
 const DEFAULT_WIFI_INTERFACE_NAME = "wlan0";
 
 // The kernel's proc entry for network lists.
 const KERNEL_NETWORK_ENTRY = "/sys/class/net";
@@ -98,38 +100,40 @@ const DEFAULT_DNS2                     =
 const DEFAULT_WIFI_DHCPSERVER_STARTIP  = "192.168.1.10";
 const DEFAULT_WIFI_DHCPSERVER_ENDIP    = "192.168.1.30";
 
 const SETTINGS_DATA_DEFAULT_SERVICE_ID = "ril.data.defaultServiceId";
 const MOBILE_DUN_CONNECT_TIMEOUT       = 30000;
 const MOBILE_DUN_RETRY_INTERVAL        = 5000;
 const MOBILE_DUN_MAX_RETRIES           = 5;
 
-let DEBUG = false;
-// Read debug setting from pref.
-try {
-  let debugPref = Services.prefs.getBoolPref("network.debugging.enabled");
-  DEBUG = DEBUG || debugPref;
-} catch (e) {}
+let debug;
+function updateDebug() {
+  let debugPref = false; // set default value here.
+  try {
+    debugPref = debugPref || Services.prefs.getBoolPref(PREF_NETWORK_DEBUG_ENABLED);
+  } catch (e) {}
 
-let debug;
-if (DEBUG) {
-  debug = function(s) {
-    dump("-*- TetheringService: " + s + "\n");
-  };
-} else {
-  debug = function(s) {};
+  if (debugPref) {
+    debug = function(s) {
+      dump("-*- TetheringService: " + s + "\n");
+    };
+  } else {
+    debug = function(s) {};
+  }
 }
+updateDebug();
 
 function TetheringService() {
   Services.obs.addObserver(this, TOPIC_XPCOM_SHUTDOWN, false);
   Services.obs.addObserver(this, TOPIC_MOZSETTINGS_CHANGED, false);
   Services.obs.addObserver(this, TOPIC_CONNECTION_STATE_CHANGED, false);
   Services.obs.addObserver(this, TOPIC_INTERFACE_REGISTERED, false);
   Services.obs.addObserver(this, TOPIC_INTERFACE_UNREGISTERED, false);
+  Services.prefs.addObserver(PREF_NETWORK_DEBUG_ENABLED, this, false);
 
   this._dataDefaultServiceId = 0;
 
   // Possible usb tethering interfaces for different gonk platform.
   this.possibleInterface = POSSIBLE_USB_INTERFACE_NAME.split(",");
 
   // Default values for internal and external interfaces.
   this._tetheringInterface = {};
@@ -231,16 +235,21 @@ TetheringService.prototype = {
   _pendingWifiTetheringRequestArgs: null,
 
   // nsIObserver
 
   observe: function(aSubject, aTopic, aData) {
     let network;
 
     switch(aTopic) {
+      case TOPIC_PREF_CHANGED:
+        if (aData === PREF_NETWORK_DEBUG_ENABLED) {
+          updateDebug();
+        }
+        break;
       case TOPIC_MOZSETTINGS_CHANGED:
         if ("wrappedJSObject" in aSubject) {
           aSubject = aSubject.wrappedJSObject;
         }
         this.handle(aSubject.key, aSubject.value);
         break;
       case TOPIC_CONNECTION_STATE_CHANGED:
         network = aSubject.QueryInterface(Ci.nsINetworkInterface);
@@ -265,16 +274,17 @@ TetheringService.prototype = {
         }
         break;
       case TOPIC_XPCOM_SHUTDOWN:
         Services.obs.removeObserver(this, TOPIC_XPCOM_SHUTDOWN);
         Services.obs.removeObserver(this, TOPIC_MOZSETTINGS_CHANGED);
         Services.obs.removeObserver(this, TOPIC_CONNECTION_STATE_CHANGED);
         Services.obs.removeObserver(this, TOPIC_INTERFACE_REGISTERED);
         Services.obs.removeObserver(this, TOPIC_INTERFACE_UNREGISTERED);
+        Services.prefs.removeObserver(PREF_NETWORK_DEBUG_ENABLED, this);
 
         this.dunConnectTimer.cancel();
         this.dunRetryTimer.cancel();
         break;
     }
   },
 
   // nsISettingsServiceCallback