1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/dom/mobileconnection/tests/marionette/head.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,720 @@ 1.4 +/* Any copyright is dedicated to the Public Domain. 1.5 + * http://creativecommons.org/publicdomain/zero/1.0/ */ 1.6 + 1.7 +const {Cc: Cc, Ci: Ci, Cr: Cr, Cu: Cu} = SpecialPowers; 1.8 + 1.9 +const SETTINGS_KEY_DATA_ENABLED = "ril.data.enabled"; 1.10 +const SETTINGS_KEY_DATA_ROAMING_ENABLED = "ril.data.roaming_enabled"; 1.11 +const SETTINGS_KEY_DATA_APN_SETTINGS = "ril.data.apnSettings"; 1.12 + 1.13 +let Promise = Cu.import("resource://gre/modules/Promise.jsm").Promise; 1.14 + 1.15 +let _pendingEmulatorCmdCount = 0; 1.16 + 1.17 +/** 1.18 + * Send emulator command with safe guard. 1.19 + * 1.20 + * We should only call |finish()| after all emulator command transactions 1.21 + * end, so here comes with the pending counter. Resolve when the emulator 1.22 + * gives positive response, and reject otherwise. 1.23 + * 1.24 + * Fulfill params: 1.25 + * result -- an array of emulator response lines. 1.26 + * Reject params: 1.27 + * result -- an array of emulator response lines. 1.28 + * 1.29 + * @param aCommand 1.30 + * A string command to be passed to emulator through its telnet console. 1.31 + * 1.32 + * @return A deferred promise. 1.33 + */ 1.34 +function runEmulatorCmdSafe(aCommand) { 1.35 + let deferred = Promise.defer(); 1.36 + 1.37 + ++_pendingEmulatorCmdCount; 1.38 + runEmulatorCmd(aCommand, function(aResult) { 1.39 + --_pendingEmulatorCmdCount; 1.40 + 1.41 + ok(true, "Emulator response: " + JSON.stringify(aResult)); 1.42 + if (Array.isArray(aResult) && 1.43 + aResult[aResult.length - 1] === "OK") { 1.44 + deferred.resolve(aResult); 1.45 + } else { 1.46 + deferred.reject(aResult); 1.47 + } 1.48 + }); 1.49 + 1.50 + return deferred.promise; 1.51 +} 1.52 + 1.53 +/** 1.54 + * Wrap DOMRequest onsuccess/onerror events to Promise resolve/reject. 1.55 + * 1.56 + * Fulfill params: A DOMEvent. 1.57 + * Reject params: A DOMEvent. 1.58 + * 1.59 + * @param aRequest 1.60 + * A DOMRequest instance. 1.61 + * 1.62 + * @return A deferred promise. 1.63 + */ 1.64 +function wrapDomRequestAsPromise(aRequest) { 1.65 + let deferred = Promise.defer(); 1.66 + 1.67 + ok(aRequest instanceof DOMRequest, 1.68 + "aRequest is instanceof " + aRequest.constructor); 1.69 + 1.70 + aRequest.addEventListener("success", function(aEvent) { 1.71 + deferred.resolve(aEvent); 1.72 + }); 1.73 + aRequest.addEventListener("error", function(aEvent) { 1.74 + deferred.reject(aEvent); 1.75 + }); 1.76 + 1.77 + return deferred.promise; 1.78 +} 1.79 + 1.80 +let workingFrame; 1.81 + 1.82 +/** 1.83 + * Get mozSettings value specified by @aKey. 1.84 + * 1.85 + * Resolve if that mozSettings value is retrieved successfully, reject 1.86 + * otherwise. 1.87 + * 1.88 + * Fulfill params: 1.89 + * The corresponding mozSettings value of the key. 1.90 + * Reject params: (none) 1.91 + * 1.92 + * @param aKey 1.93 + * A string. 1.94 + * @param aAllowError [optional] 1.95 + * A boolean value. If set to true, an error response won't be treated 1.96 + * as test failure. Default: false. 1.97 + * 1.98 + * @return A deferred promise. 1.99 + */ 1.100 +function getSettings(aKey, aAllowError) { 1.101 + let request = 1.102 + workingFrame.contentWindow.navigator.mozSettings.createLock().get(aKey); 1.103 + return wrapDomRequestAsPromise(request) 1.104 + .then(function resolve(aEvent) { 1.105 + ok(true, "getSettings(" + aKey + ") - success"); 1.106 + return aEvent.target.result[aKey]; 1.107 + }, function reject(aEvent) { 1.108 + ok(aAllowError, "getSettings(" + aKey + ") - error"); 1.109 + }); 1.110 +} 1.111 + 1.112 +/** 1.113 + * Set mozSettings values. 1.114 + * 1.115 + * Resolve if that mozSettings value is set successfully, reject otherwise. 1.116 + * 1.117 + * Fulfill params: (none) 1.118 + * Reject params: (none) 1.119 + * 1.120 + * @param aSettings 1.121 + * An object of format |{key1: value1, key2: value2, ...}|. 1.122 + * @param aAllowError [optional] 1.123 + * A boolean value. If set to true, an error response won't be treated 1.124 + * as test failure. Default: false. 1.125 + * 1.126 + * @return A deferred promise. 1.127 + */ 1.128 +function setSettings(aSettings, aAllowError) { 1.129 + let request = 1.130 + workingFrame.contentWindow.navigator.mozSettings.createLock().set(aSettings); 1.131 + return wrapDomRequestAsPromise(request) 1.132 + .then(function resolve() { 1.133 + ok(true, "setSettings(" + JSON.stringify(aSettings) + ")"); 1.134 + }, function reject() { 1.135 + ok(aAllowError, "setSettings(" + JSON.stringify(aSettings) + ")"); 1.136 + }); 1.137 +} 1.138 + 1.139 +/** 1.140 + * Set mozSettings value with only one key. 1.141 + * 1.142 + * Resolve if that mozSettings value is set successfully, reject otherwise. 1.143 + * 1.144 + * Fulfill params: (none) 1.145 + * Reject params: (none) 1.146 + * 1.147 + * @param aKey 1.148 + * A string key. 1.149 + * @param aValue 1.150 + * An object value. 1.151 + * @param aAllowError [optional] 1.152 + * A boolean value. If set to true, an error response won't be treated 1.153 + * as test failure. Default: false. 1.154 + * 1.155 + * @return A deferred promise. 1.156 + */ 1.157 +function setSettings1(aKey, aValue, aAllowError) { 1.158 + let settings = {}; 1.159 + settings[aKey] = aValue; 1.160 + return setSettings(settings, aAllowError); 1.161 +} 1.162 + 1.163 +/** 1.164 + * Convenient MozSettings getter for SETTINGS_KEY_DATA_ENABLED. 1.165 + */ 1.166 +function getDataEnabled(aAllowError) { 1.167 + return getSettings(SETTINGS_KEY_DATA_ENABLED, aAllowError); 1.168 +} 1.169 + 1.170 +/** 1.171 + * Convenient MozSettings setter for SETTINGS_KEY_DATA_ENABLED. 1.172 + */ 1.173 +function setDataEnabled(aEnabled, aAllowError) { 1.174 + return setSettings1(SETTINGS_KEY_DATA_ENABLED, aEnabled, aAllowError); 1.175 +} 1.176 + 1.177 +/** 1.178 + * Convenient MozSettings getter for SETTINGS_KEY_DATA_ROAMING_ENABLED. 1.179 + */ 1.180 +function getDataRoamingEnabled(aAllowError) { 1.181 + return getSettings(SETTINGS_KEY_DATA_ROAMING_ENABLED, aAllowError); 1.182 +} 1.183 + 1.184 +/** 1.185 + * Convenient MozSettings setter for SETTINGS_KEY_DATA_ROAMING_ENABLED. 1.186 + */ 1.187 +function setDataRoamingEnabled(aEnabled, aAllowError) { 1.188 + return setSettings1(SETTINGS_KEY_DATA_ROAMING_ENABLED, aEnabled, aAllowError); 1.189 +} 1.190 + 1.191 +/** 1.192 + * Convenient MozSettings getter for SETTINGS_KEY_DATA_APN_SETTINGS. 1.193 + */ 1.194 +function getDataApnSettings(aAllowError) { 1.195 + return getSettings(SETTINGS_KEY_DATA_APN_SETTINGS, aAllowError); 1.196 +} 1.197 + 1.198 +/** 1.199 + * Convenient MozSettings setter for SETTINGS_KEY_DATA_APN_SETTINGS. 1.200 + */ 1.201 +function setDataApnSettings(aApnSettings, aAllowError) { 1.202 + return setSettings1(SETTINGS_KEY_DATA_APN_SETTINGS, aApnSettings, aAllowError); 1.203 +} 1.204 + 1.205 +let mobileConnection; 1.206 + 1.207 +/** 1.208 + * Push required permissions and test if 1.209 + * |navigator.mozMobileConnections[<aServiceId>]| exists. Resolve if it does, 1.210 + * reject otherwise. 1.211 + * 1.212 + * Fulfill params: 1.213 + * mobileConnection -- an reference to navigator.mozMobileMessage. 1.214 + * 1.215 + * Reject params: (none) 1.216 + * 1.217 + * @param aAdditonalPermissions [optional] 1.218 + * An array of permission strings other than "mobileconnection" to be 1.219 + * pushed. Default: empty string. 1.220 + * @param aServiceId [optional] 1.221 + * A numeric DSDS service id. Default: 0. 1.222 + * 1.223 + * @return A deferred promise. 1.224 + */ 1.225 +function ensureMobileConnection(aAdditionalPermissions, aServiceId) { 1.226 + let deferred = Promise.defer(); 1.227 + 1.228 + aAdditionalPermissions = aAdditionalPermissions || []; 1.229 + aServiceId = aServiceId || 0; 1.230 + 1.231 + if (aAdditionalPermissions.indexOf("mobileconnection") < 0) { 1.232 + aAdditionalPermissions.push("mobileconnection"); 1.233 + } 1.234 + let permissions = []; 1.235 + for (let perm of aAdditionalPermissions) { 1.236 + permissions.push({ "type": perm, "allow": 1, "context": document }); 1.237 + } 1.238 + 1.239 + SpecialPowers.pushPermissions(permissions, function() { 1.240 + ok(true, "permissions pushed: " + JSON.stringify(permissions)); 1.241 + 1.242 + // Permission changes can't change existing Navigator.prototype 1.243 + // objects, so grab our objects from a new Navigator. 1.244 + workingFrame = document.createElement("iframe"); 1.245 + workingFrame.addEventListener("load", function load() { 1.246 + workingFrame.removeEventListener("load", load); 1.247 + 1.248 + mobileConnection = 1.249 + workingFrame.contentWindow.navigator.mozMobileConnections[aServiceId]; 1.250 + 1.251 + if (mobileConnection) { 1.252 + log("navigator.mozMobileConnections[" + aServiceId + "] is instance of " + 1.253 + mobileConnection.constructor); 1.254 + } else { 1.255 + log("navigator.mozMobileConnections[" + aServiceId + "] is undefined"); 1.256 + } 1.257 + 1.258 + if (mobileConnection instanceof MozMobileConnection) { 1.259 + deferred.resolve(mobileConnection); 1.260 + } else { 1.261 + deferred.reject(); 1.262 + } 1.263 + }); 1.264 + 1.265 + document.body.appendChild(workingFrame); 1.266 + }); 1.267 + 1.268 + return deferred.promise; 1.269 +} 1.270 + 1.271 +/** 1.272 + * Wait for one named MobileConnection event. 1.273 + * 1.274 + * Resolve if that named event occurs. Never reject. 1.275 + * 1.276 + * Fulfill params: the DOMEvent passed. 1.277 + * 1.278 + * @param aEventName 1.279 + * A string event name. 1.280 + * @param aServiceId [optional] 1.281 + * A numeric DSDS service id. Default: the one indicated in 1.282 + * start*TestCommon() or 0 if not indicated. 1.283 + * 1.284 + * @return A deferred promise. 1.285 + */ 1.286 +function waitForManagerEvent(aEventName, aServiceId) { 1.287 + let deferred = Promise.defer(); 1.288 + 1.289 + let mobileConn = mobileConnection; 1.290 + if (aServiceId !== undefined) { 1.291 + mobileConn = 1.292 + workingFrame.contentWindow.navigator.mozMobileConnections[aServiceId]; 1.293 + } 1.294 + 1.295 + mobileConn.addEventListener(aEventName, function onevent(aEvent) { 1.296 + mobileConn.removeEventListener(aEventName, onevent); 1.297 + 1.298 + ok(true, "MobileConnection event '" + aEventName + "' got."); 1.299 + deferred.resolve(aEvent); 1.300 + }); 1.301 + 1.302 + return deferred.promise; 1.303 +} 1.304 + 1.305 +/** 1.306 + * Get available networks. 1.307 + * 1.308 + * Fulfill params: 1.309 + * An array of nsIDOMMozMobileNetworkInfo. 1.310 + * Reject params: 1.311 + * A DOMEvent. 1.312 + * 1.313 + * @return A deferred promise. 1.314 + */ 1.315 +function getNetworks() { 1.316 + let request = mobileConnection.getNetworks(); 1.317 + return wrapDomRequestAsPromise(request) 1.318 + .then(() => request.result); 1.319 +} 1.320 + 1.321 +/** 1.322 + * Manually select a network. 1.323 + * 1.324 + * Fulfill params: (none) 1.325 + * Reject params: 1.326 + * 'RadioNotAvailable', 'RequestNotSupported', or 'GenericFailure' 1.327 + * 1.328 + * @param aNetwork 1.329 + * A nsIDOMMozMobileNetworkInfo. 1.330 + * 1.331 + * @return A deferred promise. 1.332 + */ 1.333 +function selectNetwork(aNetwork) { 1.334 + let request = mobileConnection.selectNetwork(aNetwork); 1.335 + return wrapDomRequestAsPromise(request) 1.336 + .then(null, () => { throw request.error }); 1.337 +} 1.338 + 1.339 +/** 1.340 + * Manually select a network and wait for a 'voicechange' event. 1.341 + * 1.342 + * Fulfill params: (none) 1.343 + * Reject params: 1.344 + * 'RadioNotAvailable', 'RequestNotSupported', or 'GenericFailure' 1.345 + * 1.346 + * @param aNetwork 1.347 + * A nsIDOMMozMobileNetworkInfo. 1.348 + * 1.349 + * @return A deferred promise. 1.350 + */ 1.351 +function selectNetworkAndWait(aNetwork) { 1.352 + let promises = []; 1.353 + 1.354 + promises.push(waitForManagerEvent("voicechange")); 1.355 + promises.push(selectNetwork(aNetwork)); 1.356 + 1.357 + return Promise.all(promises); 1.358 +} 1.359 + 1.360 +/** 1.361 + * Automatically select a network. 1.362 + * 1.363 + * Fulfill params: (none) 1.364 + * Reject params: 1.365 + * 'RadioNotAvailable', 'RequestNotSupported', or 'GenericFailure' 1.366 + * 1.367 + * @return A deferred promise. 1.368 + */ 1.369 +function selectNetworkAutomatically() { 1.370 + let request = mobileConnection.selectNetworkAutomatically(); 1.371 + return wrapDomRequestAsPromise(request) 1.372 + .then(null, () => { throw request.error }); 1.373 +} 1.374 + 1.375 +/** 1.376 + * Automatically select a network and wait for a 'voicechange' event. 1.377 + * 1.378 + * Fulfill params: (none) 1.379 + * Reject params: 1.380 + * 'RadioNotAvailable', 'RequestNotSupported', or 'GenericFailure' 1.381 + * 1.382 + * @return A deferred promise. 1.383 + */ 1.384 +function selectNetworkAutomaticallyAndWait() { 1.385 + let promises = []; 1.386 + 1.387 + promises.push(waitForManagerEvent("voicechange")); 1.388 + promises.push(selectNetworkAutomatically()); 1.389 + 1.390 + return Promise.all(promises); 1.391 +} 1.392 + 1.393 +/** 1.394 + * Set data connection enabling state and wait for "datachange" event. 1.395 + * 1.396 + * Resolve if data connection state changed to the expected one. Never reject. 1.397 + * 1.398 + * Fulfill params: (none) 1.399 + * 1.400 + * @param aEnabled 1.401 + * A boolean state. 1.402 + * @param aServiceId [optional] 1.403 + * A numeric DSDS service id. Default: the one indicated in 1.404 + * start*TestCommon() or 0 if not indicated. 1.405 + * 1.406 + * @return A deferred promise. 1.407 + */ 1.408 +function setDataEnabledAndWait(aEnabled, aServiceId) { 1.409 + let deferred = Promise.defer(); 1.410 + 1.411 + let promises = []; 1.412 + promises.push(waitForManagerEvent("datachange", aServiceId)); 1.413 + promises.push(setDataEnabled(aEnabled)); 1.414 + Promise.all(promises).then(function keepWaiting() { 1.415 + let mobileConn = mobileConnection; 1.416 + if (aServiceId !== undefined) { 1.417 + mobileConn = 1.418 + workingFrame.contentWindow.navigator.mozMobileConnections[aServiceId]; 1.419 + } 1.420 + // To ignore some transient states, we only resolve that deferred promise 1.421 + // when the |connected| state equals to the expected one and never rejects. 1.422 + let connected = mobileConn.data.connected; 1.423 + if (connected == aEnabled) { 1.424 + deferred.resolve(); 1.425 + return; 1.426 + } 1.427 + 1.428 + return waitForManagerEvent("datachange", aServiceId).then(keepWaiting); 1.429 + }); 1.430 + 1.431 + return deferred.promise; 1.432 +} 1.433 + 1.434 +/** 1.435 + * Set voice/data state and wait for state change. 1.436 + * 1.437 + * Fulfill params: (none) 1.438 + * 1.439 + * @param aWhich 1.440 + * "voice" or "data". 1.441 + * @param aState 1.442 + * "unregistered", "searching", "denied", "roaming", or "home". 1.443 + * @param aServiceId [optional] 1.444 + * A numeric DSDS service id. Default: the one indicated in 1.445 + * start*TestCommon() or 0 if not indicated. 1.446 + * 1.447 + * @return A deferred promise. 1.448 + */ 1.449 +function setEmulatorVoiceDataStateAndWait(aWhich, aState, aServiceId) { 1.450 + let promises = []; 1.451 + promises.push(waitForManagerEvent(aWhich + "change", aServiceId)); 1.452 + 1.453 + let cmd = "gsm " + aWhich + " " + aState; 1.454 + promises.push(runEmulatorCmdSafe(cmd)); 1.455 + return Promise.all(promises); 1.456 +} 1.457 + 1.458 +/** 1.459 + * Set voice and data roaming emulation and wait for state change. 1.460 + * 1.461 + * Fulfill params: (none) 1.462 + * 1.463 + * @param aRoaming 1.464 + * A boolean state. 1.465 + * @param aServiceId [optional] 1.466 + * A numeric DSDS service id. Default: the one indicated in 1.467 + * start*TestCommon() or 0 if not indicated. 1.468 + * 1.469 + * @return A deferred promise. 1.470 + */ 1.471 +function setEmulatorRoamingAndWait(aRoaming, aServiceId) { 1.472 + function doSetAndWait(aWhich, aRoaming, aServiceId) { 1.473 + let state = (aRoaming ? "roaming" : "home"); 1.474 + return setEmulatorVoiceDataStateAndWait(aWhich, state, aServiceId) 1.475 + .then(() => { 1.476 + let mobileConn = mobileConnection; 1.477 + if (aServiceId !== undefined) { 1.478 + mobileConn = 1.479 + workingFrame.contentWindow.navigator.mozMobileConnections[aServiceId]; 1.480 + } 1.481 + is(mobileConn[aWhich].roaming, aRoaming, 1.482 + aWhich + ".roaming") 1.483 + }); 1.484 + } 1.485 + 1.486 + // Set voice registration state first and then data registration state. 1.487 + return doSetAndWait("voice", aRoaming, aServiceId) 1.488 + .then(() => doSetAndWait("data", aRoaming, aServiceId)); 1.489 +} 1.490 + 1.491 +/** 1.492 + * Get GSM location emulation. 1.493 + * 1.494 + * Fulfill params: 1.495 + * { lac: <lac>, cid: <cid> } 1.496 + * Reject params: 1.497 + * result -- an array of emulator response lines. 1.498 + * 1.499 + * @return A deferred promise. 1.500 + */ 1.501 +function getEmulatorGsmLocation() { 1.502 + let cmd = "gsm location"; 1.503 + return runEmulatorCmdSafe(cmd) 1.504 + .then(function(aResults) { 1.505 + // lac: <lac> 1.506 + // ci: <cid> 1.507 + // OK 1.508 + is(aResults[0].substring(0,3), "lac", "lac output"); 1.509 + is(aResults[1].substring(0,2), "ci", "ci output"); 1.510 + 1.511 + let lac = parseInt(aResults[0].substring(5)); 1.512 + lac = (lac < 0 ? 65535 : lac); 1.513 + let cid = parseInt(aResults[1].substring(4)); 1.514 + cid = (cid < 0 ? 268435455 : cid); 1.515 + 1.516 + return { lac: lac, cid: cid }; 1.517 + }); 1.518 +} 1.519 + 1.520 +/** 1.521 + * Set GSM location emulation. 1.522 + * 1.523 + * Fulfill params: (none) 1.524 + * Reject params: (none) 1.525 + * 1.526 + * @param aLac 1.527 + * @param aCid 1.528 + * 1.529 + * @return A deferred promise. 1.530 + */ 1.531 +function setEmulatorGsmLocation(aLac, aCid) { 1.532 + let cmd = "gsm location " + aLac + " " + aCid; 1.533 + return runEmulatorCmdSafe(cmd); 1.534 +} 1.535 + 1.536 +/** 1.537 + * Get emulator operators info. 1.538 + * 1.539 + * Fulfill params: 1.540 + * An array of { longName: <string>, shortName: <string>, mccMnc: <string> }. 1.541 + * Reject params: 1.542 + * result -- an array of emulator response lines. 1.543 + * 1.544 + * @return A deferred promise. 1.545 + */ 1.546 +function getEmulatorOperatorNames() { 1.547 + let cmd = "operator dumpall"; 1.548 + return runEmulatorCmdSafe(cmd) 1.549 + .then(function(aResults) { 1.550 + let operators = []; 1.551 + 1.552 + for (let i = 0; i < aResults.length - 1; i++) { 1.553 + let names = aResults[i].split(','); 1.554 + operators.push({ 1.555 + longName: names[0], 1.556 + shortName: names[1], 1.557 + mccMnc: names[2], 1.558 + }); 1.559 + } 1.560 + 1.561 + ok(true, "emulator operators list: " + JSON.stringify(operators)); 1.562 + return operators; 1.563 + }); 1.564 +} 1.565 + 1.566 +/** 1.567 + * Set emulator operators info. 1.568 + * 1.569 + * Fulfill params: (none) 1.570 + * Reject params: 1.571 + * result -- an array of emulator response lines. 1.572 + * 1.573 + * @param aOperator 1.574 + * "home" or "roaming". 1.575 + * @param aLongName 1.576 + * A string. 1.577 + * @param aShortName 1.578 + * A string. 1.579 + * @param aMcc [optional] 1.580 + * A string. 1.581 + * @param aMnc [optional] 1.582 + * A string. 1.583 + * 1.584 + * @return A deferred promise. 1.585 + */ 1.586 +function setEmulatorOperatorNames(aOperator, aLongName, aShortName, aMcc, aMnc) { 1.587 + const EMULATOR_OPERATORS = [ "home", "roaming" ]; 1.588 + 1.589 + let index = EMULATOR_OPERATORS.indexOf(aOperator); 1.590 + if (index < 0) { 1.591 + throw "invalid operator"; 1.592 + } 1.593 + 1.594 + let cmd = "operator set " + index + " " + aLongName + "," + aShortName; 1.595 + if (aMcc && aMnc) { 1.596 + cmd = cmd + "," + aMcc + aMnc; 1.597 + } 1.598 + return runEmulatorCmdSafe(cmd) 1.599 + .then(function(aResults) { 1.600 + let exp = "^" + aLongName + "," + aShortName + ","; 1.601 + if (aMcc && aMnc) { 1.602 + cmd = cmd + aMcc + aMnc; 1.603 + } 1.604 + 1.605 + let re = new RegExp(exp); 1.606 + ok(aResults[index].match(new RegExp(exp)), 1.607 + "Long/short name and/or mcc/mnc should be changed."); 1.608 + }); 1.609 +} 1.610 + 1.611 +let _networkManager; 1.612 + 1.613 +/** 1.614 + * Get internal NetworkManager service. 1.615 + */ 1.616 +function getNetworkManager() { 1.617 + if (!_networkManager) { 1.618 + _networkManager = Cc["@mozilla.org/network/manager;1"] 1.619 + .getService(Ci.nsINetworkManager); 1.620 + ok(_networkManager, "NetworkManager"); 1.621 + } 1.622 + 1.623 + return _networkManager; 1.624 +} 1.625 + 1.626 +let _numOfRadioInterfaces; 1.627 + 1.628 +/* 1.629 + * Get number of radio interfaces. Default is 1 if preference is not set. 1.630 + */ 1.631 +function getNumOfRadioInterfaces() { 1.632 + if (!_numOfRadioInterfaces) { 1.633 + try { 1.634 + _numOfRadioInterfaces = SpecialPowers.getIntPref("ril.numRadioInterfaces"); 1.635 + } catch (ex) { 1.636 + _numOfRadioInterfaces = 1; // Pref not set. 1.637 + } 1.638 + } 1.639 + 1.640 + return _numOfRadioInterfaces; 1.641 +} 1.642 + 1.643 +/** 1.644 + * Flush permission settings and call |finish()|. 1.645 + */ 1.646 +function cleanUp() { 1.647 + waitFor(function() { 1.648 + SpecialPowers.flushPermissions(function() { 1.649 + // Use ok here so that we have at least one test run. 1.650 + ok(true, "permissions flushed"); 1.651 + 1.652 + finish(); 1.653 + }); 1.654 + }, function() { 1.655 + return _pendingEmulatorCmdCount === 0; 1.656 + }); 1.657 +} 1.658 + 1.659 +/** 1.660 + * Basic test routine helper for mobile connection tests. 1.661 + * 1.662 + * This helper does nothing but clean-ups. 1.663 + * 1.664 + * @param aTestCaseMain 1.665 + * A function that takes no parameter. 1.666 + */ 1.667 +function startTestBase(aTestCaseMain) { 1.668 + Promise.resolve() 1.669 + .then(aTestCaseMain) 1.670 + .then(cleanUp, function() { 1.671 + ok(false, 'promise rejects during test.'); 1.672 + cleanUp(); 1.673 + }); 1.674 +} 1.675 + 1.676 +/** 1.677 + * Common test routine helper for mobile connection tests. 1.678 + * 1.679 + * This function ensures global |mobileConnection| variable is available during 1.680 + * the process and performs clean-ups as well. 1.681 + * 1.682 + * @param aTestCaseMain 1.683 + * A function that takes one parameter -- mobileConnection. 1.684 + * @param aAdditonalPermissions [optional] 1.685 + * An array of permission strings other than "mobileconnection" to be 1.686 + * pushed. Default: empty string. 1.687 + * @param aServiceId [optional] 1.688 + * A numeric DSDS service id. Default: 0. 1.689 + */ 1.690 +function startTestCommon(aTestCaseMain, aAdditionalPermissions, aServiceId) { 1.691 + startTestBase(function() { 1.692 + return ensureMobileConnection(aAdditionalPermissions, aServiceId) 1.693 + .then(aTestCaseMain); 1.694 + }); 1.695 +} 1.696 + 1.697 +/** 1.698 + * Common test routine helper for multi-sim mobile connection tests. The test 1.699 + * ends immediately if the device tested is not multi-sim. 1.700 + * 1.701 + * This function ensures global |mobileConnection| variable is available during 1.702 + * the process and performs clean-ups as well. 1.703 + * 1.704 + * @param aTestCaseMain 1.705 + * A function that takes one parameter -- mobileConnection. 1.706 + * @param aAdditonalPermissions [optional] 1.707 + * An array of permission strings other than "mobileconnection" to be 1.708 + * pushed. Default: empty string. 1.709 + * @param aServiceId [optional] 1.710 + * A numeric DSDS service id. Default: 0. 1.711 + */ 1.712 +function startDSDSTestCommon(aTestCaseMain, aAdditionalPermissions, aServiceId) { 1.713 + if (getNumOfRadioInterfaces() > 1) { 1.714 + startTestBase(function() { 1.715 + return ensureMobileConnection(aAdditionalPermissions, aServiceId) 1.716 + .then(aTestCaseMain); 1.717 + }); 1.718 + } else { 1.719 + log("Skipping DSDS tests on single SIM device.") 1.720 + ok(true); // We should run at least one test. 1.721 + cleanUp(); 1.722 + } 1.723 +}