diff options
Diffstat (limited to 'dom/system/gonk/TetheringService.js')
-rw-r--r-- | dom/system/gonk/TetheringService.js | 891 |
1 files changed, 0 insertions, 891 deletions
diff --git a/dom/system/gonk/TetheringService.js b/dom/system/gonk/TetheringService.js deleted file mode 100644 index c5c4781806..0000000000 --- a/dom/system/gonk/TetheringService.js +++ /dev/null @@ -1,891 +0,0 @@ -/* 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/. */ - -"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/FileUtils.jsm"); -Cu.import("resource://gre/modules/systemlibs.js"); - -const TETHERINGSERVICE_CONTRACTID = "@mozilla.org/tethering/service;1"; -const TETHERINGSERVICE_CID = - Components.ID("{527a4121-ee5a-4651-be9c-f46f59cf7c01}"); - -XPCOMUtils.defineLazyServiceGetter(this, "gNetworkManager", - "@mozilla.org/network/manager;1", - "nsINetworkManager"); - -XPCOMUtils.defineLazyServiceGetter(this, "gNetworkService", - "@mozilla.org/network/service;1", - "nsINetworkService"); - -XPCOMUtils.defineLazyServiceGetter(this, "gSettingsService", - "@mozilla.org/settingsService;1", - "nsISettingsService"); - -XPCOMUtils.defineLazyServiceGetter(this, "gMobileConnectionService", - "@mozilla.org/mobileconnection/mobileconnectionservice;1", - "nsIMobileConnectionService"); - -XPCOMUtils.defineLazyGetter(this, "gRil", function() { - try { - return Cc["@mozilla.org/ril;1"].getService(Ci.nsIRadioInterfaceLayer); - } catch (e) {} - - return null; -}); - -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_MANAGE_OFFLINE_STATUS = "network.gonk.manage-offline-status"; -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"; - -const TETHERING_TYPE_WIFI = "WiFi"; -const TETHERING_TYPE_USB = "USB"; - -const WIFI_FIRMWARE_AP = "AP"; -const WIFI_FIRMWARE_STATION = "STA"; -const WIFI_SECURITY_TYPE_NONE = "open"; -const WIFI_SECURITY_TYPE_WPA_PSK = "wpa-psk"; -const WIFI_SECURITY_TYPE_WPA2_PSK = "wpa2-psk"; -const WIFI_CTRL_INTERFACE = "wl0.1"; - -const NETWORK_INTERFACE_UP = "up"; -const NETWORK_INTERFACE_DOWN = "down"; - -const TETHERING_STATE_ONGOING = "ongoing"; -const TETHERING_STATE_IDLE = "idle"; -const TETHERING_STATE_ACTIVE = "active"; - -// Settings DB path for USB tethering. -const SETTINGS_USB_ENABLED = "tethering.usb.enabled"; -const SETTINGS_USB_IP = "tethering.usb.ip"; -const SETTINGS_USB_PREFIX = "tethering.usb.prefix"; -const SETTINGS_USB_DHCPSERVER_STARTIP = "tethering.usb.dhcpserver.startip"; -const SETTINGS_USB_DHCPSERVER_ENDIP = "tethering.usb.dhcpserver.endip"; -const SETTINGS_USB_DNS1 = "tethering.usb.dns1"; -const SETTINGS_USB_DNS2 = "tethering.usb.dns2"; - -// Settings DB path for WIFI tethering. -const SETTINGS_WIFI_DHCPSERVER_STARTIP = "tethering.wifi.dhcpserver.startip"; -const SETTINGS_WIFI_DHCPSERVER_ENDIP = "tethering.wifi.dhcpserver.endip"; - -// Settings DB patch for dun required setting. -const SETTINGS_DUN_REQUIRED = "tethering.dun.required"; - -// Default value for USB tethering. -const DEFAULT_USB_IP = "192.168.0.1"; -const DEFAULT_USB_PREFIX = "24"; -const DEFAULT_USB_DHCPSERVER_STARTIP = "192.168.0.10"; -const DEFAULT_USB_DHCPSERVER_ENDIP = "192.168.0.30"; - -const DEFAULT_DNS1 = "8.8.8.8"; -const DEFAULT_DNS2 = "8.8.4.4"; - -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; - -var debug; -function updateDebug() { - let debugPref = false; // set default value here. - try { - debugPref = debugPref || Services.prefs.getBoolPref(PREF_NETWORK_DEBUG_ENABLED); - } catch (e) {} - - 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.prefs.addObserver(PREF_NETWORK_DEBUG_ENABLED, this, false); - Services.prefs.addObserver(PREF_MANAGE_OFFLINE_STATUS, this, false); - - try { - this._manageOfflineStatus = - Services.prefs.getBoolPref(PREF_MANAGE_OFFLINE_STATUS); - } catch(ex) { - // Ignore. - } - - 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 = {}; - this._tetheringInterface[TETHERING_TYPE_USB] = { - externalInterface: DEFAULT_3G_INTERFACE_NAME, - internalInterface: DEFAULT_USB_INTERFACE_NAME - }; - this._tetheringInterface[TETHERING_TYPE_WIFI] = { - externalInterface: DEFAULT_3G_INTERFACE_NAME, - internalInterface: DEFAULT_WIFI_INTERFACE_NAME - }; - - this.tetheringSettings = {}; - this.initTetheringSettings(); - - let settingsLock = gSettingsService.createLock(); - // Read the default service id for data call. - settingsLock.get(SETTINGS_DATA_DEFAULT_SERVICE_ID, this); - - // Read usb tethering data from settings DB. - settingsLock.get(SETTINGS_USB_IP, this); - settingsLock.get(SETTINGS_USB_PREFIX, this); - settingsLock.get(SETTINGS_USB_DHCPSERVER_STARTIP, this); - settingsLock.get(SETTINGS_USB_DHCPSERVER_ENDIP, this); - settingsLock.get(SETTINGS_USB_DNS1, this); - settingsLock.get(SETTINGS_USB_DNS2, this); - settingsLock.get(SETTINGS_USB_ENABLED, this); - - // Read wifi tethering data from settings DB. - settingsLock.get(SETTINGS_WIFI_DHCPSERVER_STARTIP, this); - settingsLock.get(SETTINGS_WIFI_DHCPSERVER_ENDIP, this); - - this._usbTetheringSettingsToRead = [SETTINGS_USB_IP, - SETTINGS_USB_PREFIX, - SETTINGS_USB_DHCPSERVER_STARTIP, - SETTINGS_USB_DHCPSERVER_ENDIP, - SETTINGS_USB_DNS1, - SETTINGS_USB_DNS2, - SETTINGS_USB_ENABLED, - SETTINGS_WIFI_DHCPSERVER_STARTIP, - SETTINGS_WIFI_DHCPSERVER_ENDIP]; - - this.wantConnectionEvent = null; - - this.dunConnectTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); - - this.dunRetryTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); - - this._pendingTetheringRequests = []; -} -TetheringService.prototype = { - classID: TETHERINGSERVICE_CID, - classInfo: XPCOMUtils.generateCI({classID: TETHERINGSERVICE_CID, - contractID: TETHERINGSERVICE_CONTRACTID, - classDescription: "Tethering Service", - interfaces: [Ci.nsITetheringService]}), - QueryInterface: XPCOMUtils.generateQI([Ci.nsITetheringService, - Ci.nsISupportsWeakReference, - Ci.nsIObserver, - Ci.nsISettingsServiceCallback]), - - // Flag to record the default client id for data call. - _dataDefaultServiceId: null, - - // Number of usb tehering requests to be processed. - _usbTetheringRequestCount: 0, - - // Usb tethering state. - _usbTetheringAction: TETHERING_STATE_IDLE, - - // Tethering settings. - tetheringSettings: null, - - // Tethering settings need to be read from settings DB. - _usbTetheringSettingsToRead: null, - - // Previous usb tethering enabled state. - _oldUsbTetheringEnabledState: null, - - // External and internal interface name. - _tetheringInterface: null, - - // Dun connection timer. - dunConnectTimer: null, - - // Dun connection retry times. - dunRetryTimes: 0, - - // Dun retry timer. - dunRetryTimer: null, - - // Pending tethering request to handle after dun is connected. - _pendingTetheringRequests: null, - - // Flag to indicate wether wifi tethering is being processed. - _wifiTetheringRequestOngoing: false, - - // Arguments for pending wifi tethering request. - _pendingWifiTetheringRequestArgs: null, - - // The state of tethering. - state: Ci.nsITetheringService.TETHERING_STATE_INACTIVE, - - // Flag to check if we can modify the Services.io.offline. - _manageOfflineStatus: true, - - // 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.nsINetworkInfo); - debug("Network " + network.type + "/" + network.name + - " changed state to " + network.state); - this.onConnectionChanged(network); - 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.prefs.removeObserver(PREF_NETWORK_DEBUG_ENABLED, this); - Services.prefs.removeObserver(PREF_MANAGE_OFFLINE_STATUS, this); - - this.dunConnectTimer.cancel(); - this.dunRetryTimer.cancel(); - break; - case PREF_MANAGE_OFFLINE_STATUS: - try { - this._manageOfflineStatus = - Services.prefs.getBoolPref(PREF_MANAGE_OFFLINE_STATUS); - } catch(ex) { - // Ignore. - } - break; - } - }, - - // nsISettingsServiceCallback - - handle: function(aName, aResult) { - switch(aName) { - case SETTINGS_DATA_DEFAULT_SERVICE_ID: - this._dataDefaultServiceId = aResult || 0; - debug("'_dataDefaultServiceId' is now " + this._dataDefaultServiceId); - break; - case SETTINGS_USB_ENABLED: - this._oldUsbTetheringEnabledState = this.tetheringSettings[SETTINGS_USB_ENABLED]; - case SETTINGS_USB_IP: - case SETTINGS_USB_PREFIX: - case SETTINGS_USB_DHCPSERVER_STARTIP: - case SETTINGS_USB_DHCPSERVER_ENDIP: - case SETTINGS_USB_DNS1: - case SETTINGS_USB_DNS2: - case SETTINGS_WIFI_DHCPSERVER_STARTIP: - case SETTINGS_WIFI_DHCPSERVER_ENDIP: - if (aResult !== null) { - this.tetheringSettings[aName] = aResult; - } - debug("'" + aName + "'" + " is now " + this.tetheringSettings[aName]); - let index = this._usbTetheringSettingsToRead.indexOf(aName); - - if (index != -1) { - this._usbTetheringSettingsToRead.splice(index, 1); - } - - if (this._usbTetheringSettingsToRead.length) { - debug("We haven't read completely the usb Tethering data from settings db."); - break; - } - - if (this._oldUsbTetheringEnabledState === this.tetheringSettings[SETTINGS_USB_ENABLED]) { - debug("No changes for SETTINGS_USB_ENABLED flag. Nothing to do."); - this.handlePendingWifiTetheringRequest(); - break; - } - - this._usbTetheringRequestCount++; - if (this._usbTetheringRequestCount === 1) { - if (this._wifiTetheringRequestOngoing) { - debug('USB tethering request is blocked by ongoing wifi tethering request.'); - } else { - this.handleLastUsbTetheringRequest(); - } - } - break; - }; - }, - - handleError: function(aErrorMessage) { - debug("There was an error while reading Tethering settings."); - this.tetheringSettings = {}; - this.tetheringSettings[SETTINGS_USB_ENABLED] = false; - }, - - initTetheringSettings: function() { - this.tetheringSettings[SETTINGS_USB_ENABLED] = false; - this.tetheringSettings[SETTINGS_USB_IP] = DEFAULT_USB_IP; - this.tetheringSettings[SETTINGS_USB_PREFIX] = DEFAULT_USB_PREFIX; - this.tetheringSettings[SETTINGS_USB_DHCPSERVER_STARTIP] = DEFAULT_USB_DHCPSERVER_STARTIP; - this.tetheringSettings[SETTINGS_USB_DHCPSERVER_ENDIP] = DEFAULT_USB_DHCPSERVER_ENDIP; - this.tetheringSettings[SETTINGS_USB_DNS1] = DEFAULT_DNS1; - this.tetheringSettings[SETTINGS_USB_DNS2] = DEFAULT_DNS2; - - this.tetheringSettings[SETTINGS_WIFI_DHCPSERVER_STARTIP] = DEFAULT_WIFI_DHCPSERVER_STARTIP; - this.tetheringSettings[SETTINGS_WIFI_DHCPSERVER_ENDIP] = DEFAULT_WIFI_DHCPSERVER_ENDIP; - - this.tetheringSettings[SETTINGS_DUN_REQUIRED] = - libcutils.property_get("ro.tethering.dun_required") === "1"; - }, - - getNetworkInfo: function(aType, aServiceId) { - for (let networkId in gNetworkManager.allNetworkInfo) { - let networkInfo = gNetworkManager.allNetworkInfo[networkId]; - if (networkInfo.type == aType) { - try { - if (networkInfo instanceof Ci.nsIRilNetworkInfo) { - let rilNetwork = networkInfo.QueryInterface(Ci.nsIRilNetworkInfo); - if (rilNetwork.serviceId != aServiceId) { - continue; - } - } - } catch (e) {} - return networkInfo; - } - } - return null; - }, - - handleLastUsbTetheringRequest: function() { - debug('handleLastUsbTetheringRequest... ' + this._usbTetheringRequestCount); - - if (this._usbTetheringRequestCount === 0) { - if (this.wantConnectionEvent) { - if (this.tetheringSettings[SETTINGS_USB_ENABLED]) { - this.wantConnectionEvent.call(this); - } - this.wantConnectionEvent = null; - } - this.handlePendingWifiTetheringRequest(); - return; - } - - // Cancel the accumlated count to 1 since we only care about the - // last state. - this._usbTetheringRequestCount = 1; - this.handleUSBTetheringToggle(this.tetheringSettings[SETTINGS_USB_ENABLED]); - this.wantConnectionEvent = null; - }, - - handlePendingWifiTetheringRequest: function() { - if (this._pendingWifiTetheringRequestArgs) { - this.setWifiTethering.apply(this, this._pendingWifiTetheringRequestArgs); - this._pendingWifiTetheringRequestArgs = null; - } - }, - - /** - * Callback when dun connection fails to connect within timeout. - */ - onDunConnectTimerTimeout: function() { - while (this._pendingTetheringRequests.length > 0) { - debug("onDunConnectTimerTimeout: callback without network info."); - let callback = this._pendingTetheringRequests.shift(); - if (typeof callback === 'function') { - callback(); - } - } - }, - - setupDunConnection: function() { - this.dunRetryTimer.cancel(); - let connection = - gMobileConnectionService.getItemByServiceId(this._dataDefaultServiceId); - let data = connection && connection.data; - if (data && data.state === "registered") { - let ril = gRil.getRadioInterface(this._dataDefaultServiceId); - - this.dunRetryTimes = 0; - ril.setupDataCallByType(Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_DUN); - this.dunConnectTimer.cancel(); - this.dunConnectTimer. - initWithCallback(this.onDunConnectTimerTimeout.bind(this), - MOBILE_DUN_CONNECT_TIMEOUT, Ci.nsITimer.TYPE_ONE_SHOT); - return; - } - - if (this.dunRetryTimes++ >= this.MOBILE_DUN_MAX_RETRIES) { - debug("setupDunConnection: max retries reached."); - this.dunRetryTimes = 0; - // same as dun connect timeout. - this.onDunConnectTimerTimeout(); - return; - } - - debug("Data not ready, retry dun after " + MOBILE_DUN_RETRY_INTERVAL + " ms."); - this.dunRetryTimer. - initWithCallback(this.setupDunConnection.bind(this), - MOBILE_DUN_RETRY_INTERVAL, Ci.nsITimer.TYPE_ONE_SHOT); - }, - - _dunActiveUsers: 0, - handleDunConnection: function(aEnable, aCallback) { - debug("handleDunConnection: " + aEnable); - let dun = this.getNetworkInfo( - Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_DUN, this._dataDefaultServiceId); - - if (!aEnable) { - this._dunActiveUsers--; - if (this._dunActiveUsers > 0) { - debug("Dun still needed by others, do not disconnect.") - return; - } - - this.dunRetryTimes = 0; - this.dunRetryTimer.cancel(); - this.dunConnectTimer.cancel(); - this._pendingTetheringRequests = []; - - if (dun && (dun.state == Ci.nsINetworkInfo.NETWORK_STATE_CONNECTED)) { - gRil.getRadioInterface(this._dataDefaultServiceId) - .deactivateDataCallByType(Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_DUN); - } - return; - } - - this._dunActiveUsers++; - if (!dun || (dun.state != Ci.nsINetworkInfo.NETWORK_STATE_CONNECTED)) { - debug("DUN data call inactive, setup dun data call!") - this._pendingTetheringRequests.push(aCallback); - this.dunRetryTimes = 0; - this.setupDunConnection(); - - return; - } - - this._tetheringInterface[TETHERING_TYPE_USB].externalInterface = dun.name; - aCallback(dun); - }, - - handleUSBTetheringToggle: function(aEnable) { - debug("handleUSBTetheringToggle: " + aEnable); - if (aEnable && - (this._usbTetheringAction === TETHERING_STATE_ONGOING || - this._usbTetheringAction === TETHERING_STATE_ACTIVE)) { - debug("Usb tethering already connecting/connected."); - this._usbTetheringRequestCount = 0; - this.handlePendingWifiTetheringRequest(); - return; - } - - if (!aEnable && - this._usbTetheringAction === TETHERING_STATE_IDLE) { - debug("Usb tethering already disconnected."); - this._usbTetheringRequestCount = 0; - this.handlePendingWifiTetheringRequest(); - return; - } - - if (!aEnable) { - this.tetheringSettings[SETTINGS_USB_ENABLED] = false; - gNetworkService.enableUsbRndis(false, this.enableUsbRndisResult.bind(this)); - return; - } - - this.tetheringSettings[SETTINGS_USB_ENABLED] = true; - this._usbTetheringAction = TETHERING_STATE_ONGOING; - - if (this.tetheringSettings[SETTINGS_DUN_REQUIRED]) { - this.handleDunConnection(true, (aNetworkInfo) => { - if (!aNetworkInfo){ - this.usbTetheringResultReport(aEnable, "Dun connection failed"); - return; - } - this._tetheringInterface[TETHERING_TYPE_USB].externalInterface = - aNetworkInfo.name; - gNetworkService.enableUsbRndis(true, this.enableUsbRndisResult.bind(this)); - }); - return; - } - - if (gNetworkManager.activeNetworkInfo) { - this._tetheringInterface[TETHERING_TYPE_USB].externalInterface = - gNetworkManager.activeNetworkInfo.name; - } else { - let mobile = this.getNetworkInfo( - Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE, this._dataDefaultServiceId); - if (mobile && mobile.name) { - this._tetheringInterface[TETHERING_TYPE_USB].externalInterface = mobile.name; - } - } - gNetworkService.enableUsbRndis(true, this.enableUsbRndisResult.bind(this)); - }, - - getUSBTetheringParameters: function(aEnable, aTetheringInterface) { - let interfaceIp = this.tetheringSettings[SETTINGS_USB_IP]; - let prefix = this.tetheringSettings[SETTINGS_USB_PREFIX]; - let wifiDhcpStartIp = this.tetheringSettings[SETTINGS_WIFI_DHCPSERVER_STARTIP]; - let wifiDhcpEndIp = this.tetheringSettings[SETTINGS_WIFI_DHCPSERVER_ENDIP]; - let usbDhcpStartIp = this.tetheringSettings[SETTINGS_USB_DHCPSERVER_STARTIP]; - let usbDhcpEndIp = this.tetheringSettings[SETTINGS_USB_DHCPSERVER_ENDIP]; - let dns1 = this.tetheringSettings[SETTINGS_USB_DNS1]; - let dns2 = this.tetheringSettings[SETTINGS_USB_DNS2]; - let internalInterface = aTetheringInterface.internalInterface; - let externalInterface = aTetheringInterface.externalInterface; - - // Using the default values here until application support these settings. - if (interfaceIp == "" || prefix == "" || - wifiDhcpStartIp == "" || wifiDhcpEndIp == "" || - usbDhcpStartIp == "" || usbDhcpEndIp == "") { - debug("Invalid subnet information."); - return null; - } - - return { - ifname: internalInterface, - ip: interfaceIp, - prefix: prefix, - wifiStartIp: wifiDhcpStartIp, - wifiEndIp: wifiDhcpEndIp, - usbStartIp: usbDhcpStartIp, - usbEndIp: usbDhcpEndIp, - dns1: dns1, - dns2: dns2, - internalIfname: internalInterface, - externalIfname: externalInterface, - enable: aEnable, - link: aEnable ? NETWORK_INTERFACE_UP : NETWORK_INTERFACE_DOWN - }; - }, - - notifyError: function(aResetSettings, aCallback, aMsg) { - if (aResetSettings) { - let settingsLock = gSettingsService.createLock(); - // Disable wifi tethering with a useful error message for the user. - settingsLock.set("tethering.wifi.enabled", false, null, aMsg); - } - - debug("setWifiTethering: " + (aMsg ? aMsg : "success")); - - if (aCallback) { - // Callback asynchronously to avoid netsted toggling. - Services.tm.currentThread.dispatch(() => { - aCallback.wifiTetheringEnabledChange(aMsg); - }, Ci.nsIThread.DISPATCH_NORMAL); - } - }, - - enableWifiTethering: function(aEnable, aConfig, aCallback) { - // Fill in config's required fields. - aConfig.ifname = this._tetheringInterface[TETHERING_TYPE_WIFI].internalInterface; - aConfig.internalIfname = this._tetheringInterface[TETHERING_TYPE_WIFI].internalInterface; - aConfig.externalIfname = this._tetheringInterface[TETHERING_TYPE_WIFI].externalInterface; - - this._wifiTetheringRequestOngoing = true; - gNetworkService.setWifiTethering(aEnable, aConfig, (aError) => { - // Change the tethering state to WIFI if there is no error. - if (aEnable && !aError) { - this.state = Ci.nsITetheringService.TETHERING_STATE_WIFI; - } else { - // If wifi thethering is disable, or any error happens, - // then consider the following statements. - - // Check whether the state is USB now or not. If no then just change - // it to INACTIVE, if yes then just keep it. - // It means that don't let the disable or error of WIFI affect - // the original active state. - if (this.state != Ci.nsITetheringService.TETHERING_STATE_USB) { - this.state = Ci.nsITetheringService.TETHERING_STATE_INACTIVE; - } - - // Disconnect dun on error or when wifi tethering is disabled. - if (this.tetheringSettings[SETTINGS_DUN_REQUIRED]) { - this.handleDunConnection(false); - } - } - - if (this._manageOfflineStatus) { - Services.io.offline = !this.isAnyConnected() && - (this.state === - Ci.nsITetheringService.TETHERING_STATE_INACTIVE); - } - - let resetSettings = aError; - debug('gNetworkService.setWifiTethering finished'); - this.notifyError(resetSettings, aCallback, aError); - this._wifiTetheringRequestOngoing = false; - if (this._usbTetheringRequestCount > 0) { - debug('Perform pending USB tethering requests.'); - this.handleLastUsbTetheringRequest(); - } - }); - }, - - // Enable/disable WiFi tethering by sending commands to netd. - setWifiTethering: function(aEnable, aInterfaceName, aConfig, aCallback) { - debug("setWifiTethering: " + aEnable); - if (!aInterfaceName) { - this.notifyError(true, aCallback, "invalid network interface name"); - return; - } - - if (!aConfig) { - this.notifyError(true, aCallback, "invalid configuration"); - return; - } - - if (this._usbTetheringRequestCount > 0) { - // If there's still pending usb tethering request, save - // the request params and redo |setWifiTethering| on - // usb tethering task complete. - debug('USB tethering request is being processed. Queue this wifi tethering request.'); - this._pendingWifiTetheringRequestArgs = Array.prototype.slice.call(arguments); - debug('Pending args: ' + JSON.stringify(this._pendingWifiTetheringRequestArgs)); - return; - } - - // Re-check again, test cases set this property later. - this.tetheringSettings[SETTINGS_DUN_REQUIRED] = - libcutils.property_get("ro.tethering.dun_required") === "1"; - - if (!aEnable) { - this.enableWifiTethering(false, aConfig, aCallback); - return; - } - - this._tetheringInterface[TETHERING_TYPE_WIFI].internalInterface = - aInterfaceName; - - if (this.tetheringSettings[SETTINGS_DUN_REQUIRED]) { - this.handleDunConnection(true, (aNetworkInfo) => { - if (!aNetworkInfo) { - this.notifyError(true, aCallback, "Dun connection failed"); - return; - } - this._tetheringInterface[TETHERING_TYPE_WIFI].externalInterface = - aNetworkInfo.name; - this.enableWifiTethering(true, aConfig, aCallback); - }); - return; - } - - let mobile = this.getNetworkInfo( - Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE, this._dataDefaultServiceId); - // Update the real interface name - if (mobile && mobile.name) { - this._tetheringInterface[TETHERING_TYPE_WIFI].externalInterface = mobile.name; - } - - this.enableWifiTethering(true, aConfig, aCallback); - }, - - // Enable/disable USB tethering by sending commands to netd. - setUSBTethering: function(aEnable, aTetheringInterface, aCallback) { - let params = this.getUSBTetheringParameters(aEnable, aTetheringInterface); - - if (params === null) { - gNetworkService.enableUsbRndis(false, function() { - this.usbTetheringResultReport(aEnable, "Invalid parameters"); - }); - return; - } - - gNetworkService.setUSBTethering(aEnable, params, aCallback); - }, - - getUsbInterface: function() { - // Find the rndis interface. - for (let i = 0; i < this.possibleInterface.length; i++) { - try { - let file = new FileUtils.File(KERNEL_NETWORK_ENTRY + "/" + - this.possibleInterface[i]); - if (file.exists()) { - return this.possibleInterface[i]; - } - } catch (e) { - debug("Not " + this.possibleInterface[i] + " interface."); - } - } - debug("Can't find rndis interface in possible lists."); - return DEFAULT_USB_INTERFACE_NAME; - }, - - enableUsbRndisResult: function(aSuccess, aEnable) { - if (aSuccess) { - // If enable is false, don't find usb interface cause it is already down, - // just use the internal interface in settings. - if (aEnable) { - this._tetheringInterface[TETHERING_TYPE_USB].internalInterface = - this.getUsbInterface(); - } - this.setUSBTethering(aEnable, - this._tetheringInterface[TETHERING_TYPE_USB], - this.usbTetheringResultReport.bind(this, aEnable)); - } else { - this.usbTetheringResultReport(aEnable, "enableUsbRndisResult failure"); - throw new Error("failed to set USB Function to adb"); - } - }, - - usbTetheringResultReport: function(aEnable, aError) { - this._usbTetheringRequestCount--; - - let settingsLock = gSettingsService.createLock(); - - debug('usbTetheringResultReport callback. enable: ' + aEnable + - ', error: ' + aError); - - // Disable tethering settings when fail to enable it. - if (aError) { - this.tetheringSettings[SETTINGS_USB_ENABLED] = false; - settingsLock.set("tethering.usb.enabled", false, null); - // Skip others request when we found an error. - this._usbTetheringRequestCount = 0; - this._usbTetheringAction = TETHERING_STATE_IDLE; - // If the thethering state is WIFI now, then just keep it, - // if not, just change the state to INACTIVE. - // It means that don't let the error of USB affect the original active state. - if (this.state != Ci.nsITetheringService.TETHERING_STATE_WIFI) { - this.state = Ci.nsITetheringService.TETHERING_STATE_INACTIVE; - } - if (this.tetheringSettings[SETTINGS_DUN_REQUIRED]) { - this.handleDunConnection(false); - } - } else { - if (aEnable) { - this._usbTetheringAction = TETHERING_STATE_ACTIVE; - this.state = Ci.nsITetheringService.TETHERING_STATE_USB; - } else { - this._usbTetheringAction = TETHERING_STATE_IDLE; - // If the state is now WIFI, don't let the disable of USB affect it. - if (this.state != Ci.nsITetheringService.TETHERING_STATE_WIFI) { - this.state = Ci.nsITetheringService.TETHERING_STATE_INACTIVE; - } - if (this.tetheringSettings[SETTINGS_DUN_REQUIRED]) { - this.handleDunConnection(false); - } - } - - if (this._manageOfflineStatus) { - Services.io.offline = !this.isAnyConnected() && - (this.state === - Ci.nsITetheringService.TETHERING_STATE_INACTIVE); - } - - this.handleLastUsbTetheringRequest(); - } - }, - - onConnectionChangedReport: function(aSuccess, aExternalIfname) { - debug("onConnectionChangedReport result: success " + aSuccess); - - if (aSuccess) { - // Update the external interface. - this._tetheringInterface[TETHERING_TYPE_USB].externalInterface = - aExternalIfname; - debug("Change the interface name to " + aExternalIfname); - } - }, - - onConnectionChanged: function(aNetworkInfo) { - if (aNetworkInfo.state != Ci.nsINetworkInfo.NETWORK_STATE_CONNECTED) { - debug("We are only interested in CONNECTED event"); - return; - } - - if (this.tetheringSettings[SETTINGS_DUN_REQUIRED] && - aNetworkInfo.type === Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_DUN) { - this.dunConnectTimer.cancel(); - debug("DUN data call connected, process callbacks."); - while (this._pendingTetheringRequests.length > 0) { - let callback = this._pendingTetheringRequests.shift(); - if (typeof callback === 'function') { - callback(aNetworkInfo); - } - } - return; - } - - if (!this.tetheringSettings[SETTINGS_USB_ENABLED]) { - debug("Usb tethering settings is not enabled"); - return; - } - - if (this.tetheringSettings[SETTINGS_DUN_REQUIRED] && - aNetworkInfo.type === Ci.nsINetworkInfo.NETWORK_TYPE_MOBILE_DUN && - this._tetheringInterface[TETHERING_TYPE_USB].externalInterface === - aNetworkInfo.name) { - debug("Dun required and dun interface is the same"); - return; - } - - if (this._tetheringInterface[TETHERING_TYPE_USB].externalInterface === - gNetworkManager.activeNetworkInfo.name) { - debug("The active interface is the same"); - return; - } - - let previous = { - internalIfname: this._tetheringInterface[TETHERING_TYPE_USB].internalInterface, - externalIfname: this._tetheringInterface[TETHERING_TYPE_USB].externalInterface - }; - - let current = { - internalIfname: this._tetheringInterface[TETHERING_TYPE_USB].internalInterface, - externalIfname: aNetworkInfo.name - }; - - let callback = (() => { - // Update external network interface. - debug("Update upstream interface to " + aNetworkInfo.name); - gNetworkService.updateUpStream(previous, current, - this.onConnectionChangedReport.bind(this)); - }); - - if (this._usbTetheringAction === TETHERING_STATE_ONGOING) { - debug("Postpone the event and handle it when state is idle."); - this.wantConnectionEvent = callback; - return; - } - this.wantConnectionEvent = null; - - callback.call(this); - }, - - isAnyConnected: function() { - let allNetworkInfo = gNetworkManager.allNetworkInfo; - for (let networkId in allNetworkInfo) { - if (allNetworkInfo.hasOwnProperty(networkId) && - allNetworkInfo[networkId].state === Ci.nsINetworkInfo.NETWORK_STATE_CONNECTED) { - return true; - } - } - return false; - }, -}; - -this.NSGetFactory = XPCOMUtils.generateNSGetFactory([TetheringService]); |