michael@0: /* Any copyright is dedicated to the Public Domain. michael@0: * http://creativecommons.org/publicdomain/zero/1.0/ */ michael@0: michael@0: MARIONETTE_TIMEOUT = 60000; michael@0: MARIONETTE_CONTEXT = "chrome"; michael@0: michael@0: Cu.import("resource://gre/modules/Promise.jsm"); michael@0: michael@0: const DATA_KEY = "ril.data.enabled"; michael@0: const APN_KEY = "ril.data.apnSettings"; michael@0: michael@0: let ril = Cc["@mozilla.org/ril;1"].getService(Ci.nsIRadioInterfaceLayer); michael@0: ok(ril, "ril.constructor is " + ril.constructor); michael@0: michael@0: let radioInterface = ril.getRadioInterface(0); michael@0: ok(radioInterface, "radioInterface.constructor is " + radioInterface.constrctor); michael@0: michael@0: function setSetting(key, value) { michael@0: log("setSetting: '" + key + "'' -> " + JSON.stringify(value)); michael@0: michael@0: let deferred = Promise.defer(); michael@0: let obj = {}; michael@0: obj[key] = value; michael@0: michael@0: let setRequest = window.navigator.mozSettings.createLock().set(obj); michael@0: setRequest.addEventListener("success", function() { michael@0: log("set '" + key + "' to " + JSON.stringify(value) + " success"); michael@0: deferred.resolve(); michael@0: }); michael@0: setRequest.addEventListener("error", function() { michael@0: ok(false, "cannot set '" + key + "' to " + JSON.stringify(value)); michael@0: deferred.reject(); michael@0: }); michael@0: michael@0: return deferred.promise; michael@0: } michael@0: michael@0: function getSetting(key) { michael@0: log("getSetting: '" + key + "'"); michael@0: michael@0: let deferred = Promise.defer(); michael@0: michael@0: let getRequest = window.navigator.mozSettings.createLock().get(key); michael@0: getRequest.addEventListener("success", function() { michael@0: let result = getRequest.result[key]; michael@0: log("setting '" + key + "': " + JSON.stringify(result)); michael@0: deferred.resolve(result); michael@0: }); michael@0: getRequest.addEventListener("error", function() { michael@0: ok(false, "cannot get '" + key + "'"); michael@0: deferred.reject(); michael@0: }); michael@0: michael@0: return deferred.promise; michael@0: } michael@0: michael@0: function setEmulatorAPN() { michael@0: let apn = [ michael@0: [{"carrier":"T-Mobile US", michael@0: "apn":"epc.tmobile.com", michael@0: "mmsc":"http://mms.msg.eng.t-mobile.com/mms/wapenc", michael@0: "types":["default","supl","mms","ims","dun"]}] michael@0: ]; michael@0: michael@0: return setSetting(APN_KEY, apn); michael@0: } michael@0: michael@0: function waitNetworkConnected(networkType) { michael@0: log("wait network " + networkType + " connected"); michael@0: michael@0: let interfaceStateChangeTopic = "network-connection-state-changed"; michael@0: let obs = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService); michael@0: let deferred = Promise.defer(); michael@0: michael@0: function observer(subject, topic, data) { michael@0: let network = subject.QueryInterface(Ci.nsINetworkInterface); michael@0: log("Network " + network.type + " state changes to " + network.state); michael@0: if (network.type == networkType && michael@0: network.state == Ci.nsINetworkInterface.NETWORK_STATE_CONNECTED) { michael@0: obs.removeObserver(observer, interfaceStateChangeTopic); michael@0: deferred.resolve(); michael@0: } michael@0: } michael@0: michael@0: obs.addObserver(observer, interfaceStateChangeTopic, false); michael@0: michael@0: return deferred.promise; michael@0: } michael@0: michael@0: function waitNetworkDisconnected(networkType) { michael@0: log("wait network " + networkType + " disconnected"); michael@0: michael@0: let interfaceStateChangeTopic = "network-connection-state-changed"; michael@0: let obs = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService); michael@0: let deferred = Promise.defer(); michael@0: michael@0: function observer(subject, topic, data) { michael@0: let network = subject.QueryInterface(Ci.nsINetworkInterface); michael@0: log("Network " + network.type + " state changes to " + network.state); michael@0: // We can not check network.type here cause network.type would return michael@0: // NETWORK_TYPE_MOBILE_SUPL (NETWORK_TYPE_MOBILE_OTHERS) when disconnecting michael@0: // and disconnected, see bug 939046. michael@0: if (network.state == Ci.nsINetworkInterface.NETWORK_STATE_DISCONNECTED || michael@0: network.state == Ci.nsINetworkInterface.NETWORK_STATE_UNKNOWN) { michael@0: obs.removeObserver(observer, interfaceStateChangeTopic); michael@0: deferred.resolve(); michael@0: } michael@0: } michael@0: michael@0: obs.addObserver(observer, interfaceStateChangeTopic, false); michael@0: michael@0: return deferred.promise; michael@0: } michael@0: michael@0: // Test initial State michael@0: function testInitialState() { michael@0: log("= testInitialState ="); michael@0: michael@0: // Data should be off before starting any test. michael@0: return Promise.resolve() michael@0: .then(() => getSetting(DATA_KEY)) michael@0: .then(value => { michael@0: is(value, false, "Data must be off"); michael@0: }) michael@0: .then(null, () => { michael@0: ok(false, "promise rejected during test"); michael@0: }) michael@0: .then(runNextTest); michael@0: } michael@0: michael@0: // Test default data Connection michael@0: function testDefaultDataConnection() { michael@0: log("= testDefaultDataConnection ="); michael@0: michael@0: return Promise.resolve() michael@0: // Enable data michael@0: .then(() => setSetting(DATA_KEY, true)) michael@0: .then(() => waitNetworkConnected(Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE)) michael@0: // Disable data michael@0: .then(() => setSetting(DATA_KEY, false)) michael@0: .then(() => waitNetworkDisconnected(Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE)) michael@0: .then(null, () => { michael@0: ok(false, "promise rejected during test"); michael@0: }) michael@0: .then(runNextTest); michael@0: } michael@0: michael@0: // Test non default data connection michael@0: function testNonDefaultDataConnection() { michael@0: log("= testNonDefaultDataConnection ="); michael@0: michael@0: function doTestNonDefaultDataConnection(type) { michael@0: log("doTestNonDefaultDataConnection: " + type); michael@0: michael@0: let typeMapping = { michael@0: "mms": Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_MMS, michael@0: "supl": Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_SUPL, michael@0: "ims": Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_IMS, michael@0: "dun": Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_DUN michael@0: }; michael@0: let networkType = typeMapping[type]; michael@0: michael@0: return Promise.resolve() michael@0: .then(() => radioInterface.setupDataCallByType(type)) michael@0: .then(() => waitNetworkConnected(networkType)) michael@0: .then(() => radioInterface.deactivateDataCallByType(type)) michael@0: .then(() => waitNetworkDisconnected(networkType)); michael@0: } michael@0: michael@0: let currentApn; michael@0: return Promise.resolve() michael@0: .then(() => getSetting(APN_KEY)) michael@0: .then(value => { michael@0: currentApn = value; michael@0: }) michael@0: .then(setEmulatorAPN) michael@0: .then(() => doTestNonDefaultDataConnection("mms")) michael@0: .then(() => doTestNonDefaultDataConnection("supl")) michael@0: .then(() => doTestNonDefaultDataConnection("ims")) michael@0: .then(() => doTestNonDefaultDataConnection("dun")) michael@0: // Restore APN settings michael@0: .then(() => setSetting(APN_KEY, currentApn)) michael@0: .then(null, () => { michael@0: ok(false, "promise rejected during test"); michael@0: }) michael@0: .then(runNextTest); michael@0: } michael@0: michael@0: let tests = [ michael@0: testInitialState, michael@0: testDefaultDataConnection, michael@0: testNonDefaultDataConnection michael@0: ]; michael@0: michael@0: function runNextTest() { michael@0: let test = tests.shift(); michael@0: if (!test) { michael@0: finish(); michael@0: return; michael@0: } michael@0: michael@0: test(); michael@0: } michael@0: michael@0: // Start Tests michael@0: runNextTest();