mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 960865 - Part 4: dun support implementation in NetworkManager. r=vchang
This commit is contained in:
parent
b6005b9988
commit
44d60b81be
@ -9,6 +9,7 @@ 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 NETWORKMANAGER_CONTRACTID = "@mozilla.org/network/manager;1";
|
||||
const NETWORKMANAGER_CID =
|
||||
@ -78,6 +79,9 @@ const SETTINGS_USB_DNS2 = "tethering.usb.dns2";
|
||||
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";
|
||||
@ -90,6 +94,15 @@ 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 IPV4_ADDRESS_ANY = "0.0.0.0";
|
||||
const IPV6_ADDRESS_ANY = "::0";
|
||||
|
||||
const IPV4_MAX_PREFIX_LENGTH = 32;
|
||||
const IPV6_MAX_PREFIX_LENGTH = 128;
|
||||
|
||||
const PREF_DATA_DEFAULT_SERVICE_ID = "ril.data.defaultServiceId";
|
||||
|
||||
|
||||
const DEBUG = false;
|
||||
|
||||
function defineLazyRegExp(obj, name, pattern) {
|
||||
@ -198,6 +211,11 @@ NetworkManager.prototype = {
|
||||
}
|
||||
// Add extra host route. For example, mms proxy or mmsc.
|
||||
this.setExtraHostRoute(network);
|
||||
// Dun type is a special case where we add the default route to a
|
||||
// secondary table.
|
||||
if (network.type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_DUN) {
|
||||
this.setSecondaryDefaultRoute(network);
|
||||
}
|
||||
#endif
|
||||
// Remove pre-created default route and let setAndConfigureActive()
|
||||
// to set default route only on preferred network
|
||||
@ -226,6 +244,10 @@ NetworkManager.prototype = {
|
||||
}
|
||||
// Remove extra host route. For example, mms proxy or mmsc.
|
||||
this.removeExtraHostRoute(network);
|
||||
// Remove secondary default route for dun.
|
||||
if (network.type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_DUN) {
|
||||
this.removeSecondaryDefaultRoute(network);
|
||||
}
|
||||
#endif
|
||||
// Remove routing table in /proc/net/route
|
||||
if (network.type == Ci.nsINetworkInterface.NETWORK_TYPE_WIFI) {
|
||||
@ -256,11 +278,20 @@ NetworkManager.prototype = {
|
||||
let regNetwork = subject.QueryInterface(Ci.nsINetworkInterface);
|
||||
// Add extra host route. For example, mms proxy or mmsc.
|
||||
this.setExtraHostRoute(regNetwork);
|
||||
// Dun type is a special case where we add the default route to a
|
||||
// secondary table.
|
||||
if (regNetwork.type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_DUN) {
|
||||
this.setSecondaryDefaultRoute(regNetwork);
|
||||
}
|
||||
break;
|
||||
case TOPIC_INTERFACE_UNREGISTERED:
|
||||
let unregNetwork = subject.QueryInterface(Ci.nsINetworkInterface);
|
||||
// Remove extra host route. For example, mms proxy or mmsc.
|
||||
this.removeExtraHostRoute(unregNetwork);
|
||||
// Remove secondary default route for dun.
|
||||
if (unregNetwork.type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_DUN) {
|
||||
this.removeSecondaryDefaultRoute(unregNetwork);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
case TOPIC_MOZSETTINGS_CHANGED:
|
||||
@ -291,6 +322,7 @@ NetworkManager.prototype = {
|
||||
let excludeMms = aMsg.json.excludeMms;
|
||||
let excludeSupl = aMsg.json.excludeSupl;
|
||||
let excludeIms = aMsg.json.excludeIms;
|
||||
let excludeDun = aMsg.json.excludeDun;
|
||||
#endif
|
||||
let interfaces = [];
|
||||
|
||||
@ -298,7 +330,8 @@ NetworkManager.prototype = {
|
||||
#ifdef MOZ_B2G_RIL
|
||||
if ((i.type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_MMS && excludeMms) ||
|
||||
(i.type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_SUPL && excludeSupl) ||
|
||||
(i.type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_IMS && excludeIms)) {
|
||||
(i.type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_IMS && excludeIms) ||
|
||||
(i.type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_DUN && excludeDun)) {
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
@ -456,6 +489,39 @@ NetworkManager.prototype = {
|
||||
gNetworkService.removeHostRouteWithResolve(network, mmsHosts);
|
||||
}
|
||||
},
|
||||
|
||||
setSecondaryDefaultRoute: function(network) {
|
||||
// First, we need to add a host route to the gateway in the secondary
|
||||
// routing table to make the gateway reachable. Host route takes the max
|
||||
// prefix and gateway address 'any'.
|
||||
let route = {
|
||||
ip: network.gateway,
|
||||
prefix: IPV4_MAX_PREFIX_LENGTH,
|
||||
gateway: IPV4_ADDRESS_ANY
|
||||
};
|
||||
gNetworkService.addSecondaryRoute(network.name, route);
|
||||
// Now we can add the default route through gateway. Default route takes the
|
||||
// min prefix and destination ip 'any'.
|
||||
route.ip = IPV4_ADDRESS_ANY;
|
||||
route.prefix = 0;
|
||||
route.gateway = network.gateway;
|
||||
gNetworkService.addSecondaryRoute(network.name, route);
|
||||
},
|
||||
|
||||
removeSecondaryDefaultRoute: function(network) {
|
||||
// Remove both host route and default route.
|
||||
let route = {
|
||||
ip: network.gateway,
|
||||
prefix: IPV4_MAX_PREFIX_LENGTH,
|
||||
gateway: IPV4_ADDRESS_ANY
|
||||
};
|
||||
gNetworkService.removeSecondaryRoute(network.name, route);
|
||||
|
||||
route.ip = IPV4_ADDRESS_ANY;
|
||||
route.prefix = "0";
|
||||
route.gateway = network.gateway;
|
||||
gNetworkService.removeSecondaryRoute(network.name, route);
|
||||
},
|
||||
#endif // MOZ_B2G_RIL
|
||||
|
||||
/**
|
||||
@ -586,6 +652,11 @@ NetworkManager.prototype = {
|
||||
|
||||
this.tetheringSettings[SETTINGS_WIFI_DHCPSERVER_STARTIP] = DEFAULT_WIFI_DHCPSERVER_STARTIP;
|
||||
this.tetheringSettings[SETTINGS_WIFI_DHCPSERVER_ENDIP] = DEFAULT_WIFI_DHCPSERVER_ENDIP;
|
||||
|
||||
#ifdef MOZ_B2G_RIL
|
||||
this.tetheringSettings[SETTINGS_DUN_REQUIRED] =
|
||||
libcutils.property_get("ro.tethering.dun_required") === "1";
|
||||
#endif
|
||||
},
|
||||
|
||||
_requestCount: 0,
|
||||
@ -674,6 +745,33 @@ NetworkManager.prototype = {
|
||||
}
|
||||
},
|
||||
|
||||
#ifdef MOZ_B2G_RIL
|
||||
_pendingTetheringRequests: [],
|
||||
handleDunConnection: function(enable, callback) {
|
||||
debug("handleDunConnection: " + enable);
|
||||
let dun = this.getNetworkInterface(
|
||||
Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_DUN);
|
||||
|
||||
if (!enable) {
|
||||
if (dun && (dun.state == Ci.nsINetworkInterface.NETWORK_STATE_CONNECTED)) {
|
||||
this.mRil.getRadioInterface(this.gDataDefaultServiceId)
|
||||
.deactivateDataCallByType("dun");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!dun || (dun.state != Ci.nsINetworkInterface.NETWORK_STATE_CONNECTED)) {
|
||||
debug("DUN data call inactive, setup dun data call!")
|
||||
this._pendingTetheringRequests.push(callback);
|
||||
this.mRil.getRadioInterface(this.gDataDefaultServiceId)
|
||||
.setupDataCallByType("dun");
|
||||
return;
|
||||
}
|
||||
this._tetheringInterface[TETHERING_TYPE_USB].externalInterface = dun.name;
|
||||
callback(dun);
|
||||
},
|
||||
#endif
|
||||
|
||||
handleUSBTetheringToggle: function(enable) {
|
||||
if (!enable) {
|
||||
this.tetheringSettings[SETTINGS_USB_ENABLED] = false;
|
||||
@ -681,15 +779,26 @@ NetworkManager.prototype = {
|
||||
return;
|
||||
}
|
||||
|
||||
this.tetheringSettings[SETTINGS_USB_ENABLED] = true;
|
||||
|
||||
#ifdef MOZ_B2G_RIL
|
||||
if (this.tetheringSettings[SETTINGS_DUN_REQUIRED]) {
|
||||
this.handleDunConnection(true, function(network) {
|
||||
this._tetheringInterface[TETHERING_TYPE_USB].externalInterface = network.name;
|
||||
gNetworkService.enableUsbRndis(true, this.enableUsbRndisResult.bind(this));
|
||||
}.bind(this));
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (this.active) {
|
||||
this._tetheringInterface[TETHERING_TYPE_USB].externalInterface = this.active.name
|
||||
this._tetheringInterface[TETHERING_TYPE_USB].externalInterface = this.active.name;
|
||||
} else {
|
||||
let mobile = this.getNetworkInterface(Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE);
|
||||
if (mobile) {
|
||||
this._tetheringInterface[TETHERING_TYPE_USB].externalInterface = mobile.name;
|
||||
}
|
||||
}
|
||||
this.tetheringSettings[SETTINGS_USB_ENABLED] = true;
|
||||
gNetworkService.enableUsbRndis(true, this.enableUsbRndisResult.bind(this));
|
||||
},
|
||||
|
||||
@ -753,8 +862,28 @@ NetworkManager.prototype = {
|
||||
}
|
||||
},
|
||||
|
||||
enableWifiTethering: function(enable, config, callback) {
|
||||
// Fill in config's required fields.
|
||||
config.ifname = this._tetheringInterface[TETHERING_TYPE_WIFI].internalInterface;
|
||||
config.internalIfname = this._tetheringInterface[TETHERING_TYPE_WIFI].internalInterface;
|
||||
config.externalIfname = this._tetheringInterface[TETHERING_TYPE_WIFI].externalInterface;
|
||||
|
||||
gNetworkService.setWifiTethering(enable, config, (function(error) {
|
||||
#ifdef MOZ_B2G_RIL
|
||||
// Disconnect dun on error or when wifi tethering is disabled.
|
||||
if (this.tetheringSettings[SETTINGS_DUN_REQUIRED] &&
|
||||
(!enable || error)) {
|
||||
this.handleDunConnection(false);
|
||||
}
|
||||
#endif
|
||||
let resetSettings = error;
|
||||
this.notifyError(resetSettings, callback, error);
|
||||
}).bind(this));
|
||||
},
|
||||
|
||||
// Enable/disable WiFi tethering by sending commands to netd.
|
||||
setWifiTethering: function(enable, network, config, callback) {
|
||||
debug("setWifiTethering: " + enable);
|
||||
if (!network) {
|
||||
this.notifyError(true, callback, "invalid network information");
|
||||
return;
|
||||
@ -765,22 +894,30 @@ NetworkManager.prototype = {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!enable) {
|
||||
this.enableWifiTethering(false, config, callback);
|
||||
return;
|
||||
}
|
||||
|
||||
this._tetheringInterface[TETHERING_TYPE_WIFI].internalInterface = network.name;
|
||||
|
||||
#ifdef MOZ_B2G_RIL
|
||||
if (this.tetheringSettings[SETTINGS_DUN_REQUIRED]) {
|
||||
this.handleDunConnection(true, function(config, callback, network) {
|
||||
this._tetheringInterface[TETHERING_TYPE_WIFI].externalInterface = network.name;
|
||||
this.enableWifiTethering(true, config, callback);
|
||||
}.bind(this, config, callback));
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
let mobile = this.getNetworkInterface(Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE);
|
||||
// Update the real interface name
|
||||
if (mobile) {
|
||||
this._tetheringInterface[TETHERING_TYPE_WIFI].externalInterface = mobile.name;
|
||||
}
|
||||
|
||||
config.ifname = this._tetheringInterface[TETHERING_TYPE_WIFI].internalInterface;
|
||||
config.internalIfname = this._tetheringInterface[TETHERING_TYPE_WIFI].internalInterface;
|
||||
config.externalIfname = this._tetheringInterface[TETHERING_TYPE_WIFI].externalInterface;
|
||||
|
||||
gNetworkService.setWifiTethering(enable, config, (function(error) {
|
||||
let resetSettings = error;
|
||||
this.notifyError(resetSettings, callback, error);
|
||||
}).bind(this));
|
||||
this.enableWifiTethering(true, config, callback);
|
||||
},
|
||||
|
||||
// Enable/disable USB tethering by sending commands to netd.
|
||||
@ -816,7 +953,11 @@ NetworkManager.prototype = {
|
||||
|
||||
enableUsbRndisResult: function(success, enable) {
|
||||
if (success) {
|
||||
this._tetheringInterface[TETHERING_TYPE_USB].internalInterface = this.getUsbInterface();
|
||||
// If enable is false, don't find usb interface cause it is already down,
|
||||
// just use the internal interface in settings.
|
||||
if (enable) {
|
||||
this._tetheringInterface[TETHERING_TYPE_USB].internalInterface = this.getUsbInterface();
|
||||
}
|
||||
this.setUSBTethering(enable,
|
||||
this._tetheringInterface[TETHERING_TYPE_USB],
|
||||
this.usbTetheringResultReport.bind(this));
|
||||
@ -835,8 +976,19 @@ NetworkManager.prototype = {
|
||||
this.tetheringSettings[SETTINGS_USB_ENABLED] = false;
|
||||
settingsLock.set("tethering.usb.enabled", false, null);
|
||||
// Skip others request when we found an error.
|
||||
#ifdef MOZ_B2G_RIL
|
||||
if (this.tetheringSettings[SETTINGS_DUN_REQUIRED]) {
|
||||
this.handleDunConnection(false);
|
||||
}
|
||||
#endif
|
||||
this._requestCount = 0;
|
||||
} else {
|
||||
#ifdef MOZ_B2G_RIL
|
||||
if (this.tetheringSettings[SETTINGS_DUN_REQUIRED] &&
|
||||
!this.tetheringSettings[SETTINGS_USB_ENABLED]) {
|
||||
this.handleDunConnection(false);
|
||||
}
|
||||
#endif
|
||||
this.handleLastRequest();
|
||||
}
|
||||
},
|
||||
@ -857,11 +1009,42 @@ NetworkManager.prototype = {
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef MOZ_B2G_RIL
|
||||
// We can not use network.type only to check if it's dun, cause if it is
|
||||
// shared with default, the returned type would always be default, see bug
|
||||
// 939046. In most cases, if dun is required, it should not be shared with
|
||||
// default.
|
||||
if (this.tetheringSettings[SETTINGS_DUN_REQUIRED] &&
|
||||
(network.type === Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_DUN ||
|
||||
this.mRil.getRadioInterface(this.gDataDefaultServiceId)
|
||||
.getDataCallStateByType("dun") ===
|
||||
Ci.nsINetworkInterface.NETWORK_STATE_CONNECTED)) {
|
||||
debug("DUN data call connected, process callbacks.");
|
||||
while (this._pendingTetheringRequests.length > 0) {
|
||||
let callback = this._pendingTetheringRequests.shift();
|
||||
if (typeof callback === 'function') {
|
||||
callback(network);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!this.tetheringSettings[SETTINGS_USB_ENABLED]) {
|
||||
debug("Usb tethering settings is not enabled");
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef MOZ_B2G_RIL
|
||||
if (this.tetheringSettings[SETTINGS_DUN_REQUIRED] &&
|
||||
network.type === Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_DUN &&
|
||||
this._tetheringInterface[TETHERING_TYPE_USB].externalInterface ===
|
||||
network.name) {
|
||||
debug("Dun required and dun interface is the same");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (this._tetheringInterface[TETHERING_TYPE_USB].externalInterface ===
|
||||
this.active.name) {
|
||||
debug("The active interface is the same");
|
||||
@ -973,6 +1156,15 @@ let CaptivePortalDetectionHelper = (function() {
|
||||
XPCOMUtils.defineLazyServiceGetter(NetworkManager.prototype, "mRil",
|
||||
"@mozilla.org/ril;1",
|
||||
"nsIRadioInterfaceLayer");
|
||||
|
||||
XPCOMUtils.defineLazyGetter(NetworkManager.prototype,
|
||||
"gDataDefaultServiceId", function() {
|
||||
try {
|
||||
return Services.prefs.getIntPref(PREF_DATA_DEFAULT_SERVICE_ID);
|
||||
} catch(e) {}
|
||||
|
||||
return 0;
|
||||
});
|
||||
#endif
|
||||
|
||||
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([NetworkManager]);
|
||||
|
Loading…
Reference in New Issue
Block a user