dom/telephony/test/marionette/head.js

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

michael@0 1 /* Any copyright is dedicated to the Public Domain.
michael@0 2 * http://creativecommons.org/publicdomain/zero/1.0/ */
michael@0 3
michael@0 4 let Promise = SpecialPowers.Cu.import("resource://gre/modules/Promise.jsm").Promise;
michael@0 5 let telephony;
michael@0 6 let conference;
michael@0 7
michael@0 8 /**
michael@0 9 * Emulator helper.
michael@0 10 */
michael@0 11 let emulator = (function() {
michael@0 12 let pendingCmdCount = 0;
michael@0 13 let originalRunEmulatorCmd = runEmulatorCmd;
michael@0 14
michael@0 15 // Overwritten it so people could not call this function directly.
michael@0 16 runEmulatorCmd = function() {
michael@0 17 throw "Use emulator.run(cmd, callback) instead of runEmulatorCmd";
michael@0 18 };
michael@0 19
michael@0 20 function run(cmd, callback) {
michael@0 21 pendingCmdCount++;
michael@0 22 originalRunEmulatorCmd(cmd, function(result) {
michael@0 23 pendingCmdCount--;
michael@0 24 if (callback && typeof callback === "function") {
michael@0 25 callback(result);
michael@0 26 }
michael@0 27 });
michael@0 28 }
michael@0 29
michael@0 30 /**
michael@0 31 * @return Promise
michael@0 32 */
michael@0 33 function waitFinish() {
michael@0 34 let deferred = Promise.defer();
michael@0 35
michael@0 36 waitFor(function() {
michael@0 37 deferred.resolve();
michael@0 38 }, function() {
michael@0 39 return pendingCmdCount === 0;
michael@0 40 });
michael@0 41
michael@0 42 return deferred.promise;
michael@0 43 }
michael@0 44
michael@0 45 return {
michael@0 46 run: run,
michael@0 47 waitFinish: waitFinish
michael@0 48 };
michael@0 49 }());
michael@0 50
michael@0 51 // Delay 1s before each telephony.dial()
michael@0 52 // The workaround here should be removed after bug 1005816.
michael@0 53
michael@0 54 let originalDial;
michael@0 55
michael@0 56 function delayTelephonyDial() {
michael@0 57 originalDial = telephony.dial;
michael@0 58 telephony.dial = function(number, serviceId) {
michael@0 59 let deferred = Promise.defer();
michael@0 60
michael@0 61 let startTime = Date.now();
michael@0 62 waitFor(function() {
michael@0 63 originalDial.call(telephony, number, serviceId).then(call => {
michael@0 64 deferred.resolve(call);
michael@0 65 }, cause => {
michael@0 66 deferred.reject(cause);
michael@0 67 });
michael@0 68 }, function() {
michael@0 69 duration = Date.now() - startTime;
michael@0 70 return (duration >= 1000);
michael@0 71 });
michael@0 72
michael@0 73 return deferred.promise;
michael@0 74 };
michael@0 75 }
michael@0 76
michael@0 77 function restoreTelephonyDial() {
michael@0 78 telephony.dial = originalDial;
michael@0 79 }
michael@0 80
michael@0 81 /**
michael@0 82 * Telephony related helper functions.
michael@0 83 */
michael@0 84 (function() {
michael@0 85 /**
michael@0 86 * @return Promise
michael@0 87 */
michael@0 88 function clearCalls() {
michael@0 89 let deferred = Promise.defer();
michael@0 90
michael@0 91 log("Clear existing calls.");
michael@0 92 emulator.run("gsm clear", function(result) {
michael@0 93 if (result[0] == "OK") {
michael@0 94 waitFor(function() {
michael@0 95 deferred.resolve();
michael@0 96 }, function() {
michael@0 97 return telephony.calls.length === 0;
michael@0 98 });
michael@0 99 } else {
michael@0 100 log("Failed to clear existing calls.");
michael@0 101 deferred.reject();
michael@0 102 }
michael@0 103 });
michael@0 104
michael@0 105 return deferred.promise;
michael@0 106 }
michael@0 107
michael@0 108 /**
michael@0 109 * Provide a string with format of the emulator call list result.
michael@0 110 *
michael@0 111 * @param prefix
michael@0 112 * Possible values are "outbound" and "inbound".
michael@0 113 * @param number
michael@0 114 * Call number.
michael@0 115 * @return A string with format of the emulator call list result.
michael@0 116 */
michael@0 117 function callStrPool(prefix, number) {
michael@0 118 let padding = " : ";
michael@0 119 let numberInfo = prefix + number + padding.substr(number.length);
michael@0 120
michael@0 121 let info = {};
michael@0 122 let states = ['ringing', 'incoming', 'active', 'held'];
michael@0 123 for (let state of states) {
michael@0 124 info[state] = numberInfo + state;
michael@0 125 }
michael@0 126
michael@0 127 return info;
michael@0 128 }
michael@0 129
michael@0 130 /**
michael@0 131 * Provide a corresponding string of an outgoing call. The string is with
michael@0 132 * format of the emulator call list result.
michael@0 133 *
michael@0 134 * @param number
michael@0 135 * Number of an outgoing call.
michael@0 136 * @return A string with format of the emulator call list result.
michael@0 137 */
michael@0 138 function outCallStrPool(number) {
michael@0 139 return callStrPool("outbound to ", number);
michael@0 140 }
michael@0 141
michael@0 142 /**
michael@0 143 * Provide a corresponding string of an incoming call. The string is with
michael@0 144 * format of the emulator call list result.
michael@0 145 *
michael@0 146 * @param number
michael@0 147 * Number of an incoming call.
michael@0 148 * @return A string with format of the emulator call list result.
michael@0 149 */
michael@0 150 function inCallStrPool(number) {
michael@0 151 return callStrPool("inbound from ", number);
michael@0 152 }
michael@0 153
michael@0 154 /**
michael@0 155 * Check utility functions.
michael@0 156 */
michael@0 157
michael@0 158 function checkInitialState() {
michael@0 159 log("Verify initial state.");
michael@0 160 ok(telephony.calls, 'telephony.call');
michael@0 161 checkTelephonyActiveAndCalls(null, []);
michael@0 162 ok(conference.calls, 'conference.calls');
michael@0 163 checkConferenceStateAndCalls('', []);
michael@0 164 }
michael@0 165
michael@0 166 /**
michael@0 167 * Convenient helper to compare a TelephonyCall and a received call event.
michael@0 168 */
michael@0 169 function checkEventCallState(event, call, state) {
michael@0 170 is(call, event.call, "event.call");
michael@0 171 is(call.state, state, "call state");
michael@0 172 }
michael@0 173
michael@0 174 /**
michael@0 175 * Convenient helper to check mozTelephony.active and mozTelephony.calls.
michael@0 176 */
michael@0 177 function checkTelephonyActiveAndCalls(active, calls) {
michael@0 178 is(telephony.active, active, "telephony.active");
michael@0 179 is(telephony.calls.length, calls.length, "telephony.calls");
michael@0 180 for (let i = 0; i < calls.length; ++i) {
michael@0 181 is(telephony.calls[i], calls[i]);
michael@0 182 }
michael@0 183 }
michael@0 184
michael@0 185 /**
michael@0 186 * Convenient helper to check mozTelephony.conferenceGroup.state and
michael@0 187 * .conferenceGroup.calls.
michael@0 188 */
michael@0 189 function checkConferenceStateAndCalls(state, calls) {
michael@0 190 is(conference.state, state, "conference.state");
michael@0 191 is(conference.calls.length, calls.length, "conference.calls");
michael@0 192 for (let i = 0; i < calls.length; i++) {
michael@0 193 is(conference.calls[i], calls[i]);
michael@0 194 }
michael@0 195 }
michael@0 196
michael@0 197 /**
michael@0 198 * Convenient helper to handle *.oncallschanged event.
michael@0 199 *
michael@0 200 * @param container
michael@0 201 * Representation of "mozTelephony" or "mozTelephony.conferenceGroup."
michael@0 202 * @param containerName
michael@0 203 * Name of container. Could be an arbitrary string, used for debug
michael@0 204 * messages only.
michael@0 205 * @param expectedCalls
michael@0 206 * An array of calls.
michael@0 207 * @param callback
michael@0 208 * A callback function.
michael@0 209 */
michael@0 210 function check_oncallschanged(container, containerName, expectedCalls,
michael@0 211 callback) {
michael@0 212 container.oncallschanged = function(event) {
michael@0 213 log("Received 'callschanged' event for the " + containerName);
michael@0 214 if (event.call) {
michael@0 215 let index = expectedCalls.indexOf(event.call);
michael@0 216 ok(index != -1);
michael@0 217 expectedCalls.splice(index, 1);
michael@0 218
michael@0 219 if (expectedCalls.length === 0) {
michael@0 220 container.oncallschanged = null;
michael@0 221 callback();
michael@0 222 }
michael@0 223 }
michael@0 224 };
michael@0 225 }
michael@0 226
michael@0 227 /**
michael@0 228 * Convenient helper to handle *.ongroupchange event.
michael@0 229 *
michael@0 230 * @param call
michael@0 231 * A TelephonyCall object.
michael@0 232 * @param callName
michael@0 233 * Name of a call. Could be an arbitrary string, used for debug messages
michael@0 234 * only.
michael@0 235 * @param group
michael@0 236 * Representation of mozTelephony.conferenceGroup.
michael@0 237 * @param callback
michael@0 238 * A callback function.
michael@0 239 */
michael@0 240 function check_ongroupchange(call, callName, group, callback) {
michael@0 241 call.ongroupchange = function(event) {
michael@0 242 log("Received 'groupchange' event for the " + callName);
michael@0 243 call.ongroupchange = null;
michael@0 244
michael@0 245 is(call.group, group);
michael@0 246 callback();
michael@0 247 };
michael@0 248 }
michael@0 249
michael@0 250 /**
michael@0 251 * Convenient helper to handle *.onstatechange event.
michael@0 252 *
michael@0 253 * @param container
michael@0 254 * Representation of a TelephonyCall or mozTelephony.conferenceGroup.
michael@0 255 * @param containerName
michael@0 256 * Name of container. Could be an arbitrary string, used for debug messages
michael@0 257 * only.
michael@0 258 * @param state
michael@0 259 * A string.
michael@0 260 * @param callback
michael@0 261 * A callback function.
michael@0 262 */
michael@0 263 function check_onstatechange(container, containerName, state, callback) {
michael@0 264 container.onstatechange = function(event) {
michael@0 265 log("Received 'statechange' event for the " + containerName);
michael@0 266 container.onstatechange = null;
michael@0 267
michael@0 268 is(container.state, state);
michael@0 269 callback();
michael@0 270 };
michael@0 271 }
michael@0 272
michael@0 273 /**
michael@0 274 * Convenient helper to check the sequence of call state and event handlers.
michael@0 275 *
michael@0 276 * @param state
michael@0 277 * A string of the expected call state.
michael@0 278 * @param previousEvent
michael@0 279 * A string of the event that should come before the expected state.
michael@0 280 */
michael@0 281 function StateEventChecker(state, previousEvent) {
michael@0 282 let event = 'on' + state;
michael@0 283
michael@0 284 return function(call, callName, callback) {
michael@0 285 call[event] = function() {
michael@0 286 log("Received '" + state + "' event for the " + callName);
michael@0 287 call[event] = null;
michael@0 288
michael@0 289 if (previousEvent) {
michael@0 290 // We always clear the event handler when the event is received.
michael@0 291 // Therefore, if the corresponding handler is not existed, the expected
michael@0 292 // previous event has been already received.
michael@0 293 ok(!call[previousEvent]);
michael@0 294 }
michael@0 295 is(call.state, state);
michael@0 296 callback();
michael@0 297 };
michael@0 298 };
michael@0 299 }
michael@0 300
michael@0 301 /**
michael@0 302 * Convenient helper to check the call list existing in the emulator.
michael@0 303 *
michael@0 304 * @param expectedCallList
michael@0 305 * An array of call info with the format of "callStrPool()[state]".
michael@0 306 * @return A deferred promise.
michael@0 307 */
michael@0 308 function checkEmulatorCallList(expectedCallList) {
michael@0 309 let deferred = Promise.defer();
michael@0 310
michael@0 311 emulator.run("gsm list", function(result) {
michael@0 312 log("Call list is now: " + result);
michael@0 313 for (let i = 0; i < expectedCallList.length; ++i) {
michael@0 314 is(result[i], expectedCallList[i], "emulator calllist");
michael@0 315 }
michael@0 316 is(result[expectedCallList.length], "OK", "emulator calllist");
michael@0 317 deferred.resolve();
michael@0 318 });
michael@0 319
michael@0 320 return deferred.promise;
michael@0 321 }
michael@0 322
michael@0 323 /**
michael@0 324 * Super convenient helper to check calls and state of mozTelephony and
michael@0 325 * mozTelephony.conferenceGroup.
michael@0 326 *
michael@0 327 * @param active
michael@0 328 * A TelephonyCall object. Should be the expected active call.
michael@0 329 * @param calls
michael@0 330 * An array of TelephonyCall objects. Should be the expected list of
michael@0 331 * mozTelephony.calls.
michael@0 332 * @param conferenceState
michael@0 333 * A string. Should be the expected conference state.
michael@0 334 * @param conferenceCalls
michael@0 335 * An array of TelephonyCall objects. Should be the expected list of
michael@0 336 * mozTelephony.conferenceGroup.calls.
michael@0 337 */
michael@0 338 function checkState(active, calls, conferenceState, conferenceCalls) {
michael@0 339 checkTelephonyActiveAndCalls(active, calls);
michael@0 340 checkConferenceStateAndCalls(conferenceState, conferenceCalls);
michael@0 341 }
michael@0 342
michael@0 343 /**
michael@0 344 * Super convenient helper to check calls and state of mozTelephony and
michael@0 345 * mozTelephony.conferenceGroup as well as the calls existing in the emulator.
michael@0 346 *
michael@0 347 * @param active
michael@0 348 * A TelephonyCall object. Should be the expected active call.
michael@0 349 * @param calls
michael@0 350 * An array of TelephonyCall objects. Should be the expected list of
michael@0 351 * mozTelephony.calls.
michael@0 352 * @param conferenceState
michael@0 353 * A string. Should be the expected conference state.
michael@0 354 * @param conferenceCalls
michael@0 355 * An array of TelephonyCall objects. Should be the expected list of
michael@0 356 * mozTelephony.conferenceGroup.calls.
michael@0 357 * @param callList
michael@0 358 * An array of call info with the format of "callStrPool()[state]".
michael@0 359 * @return A deferred promise.
michael@0 360 */
michael@0 361 function checkAll(active, calls, conferenceState, conferenceCalls, callList) {
michael@0 362 checkState(active, calls, conferenceState, conferenceCalls);
michael@0 363 return checkEmulatorCallList(callList);
michael@0 364 }
michael@0 365
michael@0 366 /**
michael@0 367 * Request utility functions.
michael@0 368 */
michael@0 369
michael@0 370 /**
michael@0 371 * Make sure there's no pending event before we jump to the next action.
michael@0 372 *
michael@0 373 * @param received
michael@0 374 * A string of the received event.
michael@0 375 * @param pending
michael@0 376 * An array of the pending events.
michael@0 377 * @param nextAction
michael@0 378 * A callback function that is called when there's no pending event.
michael@0 379 */
michael@0 380 function receivedPending(received, pending, nextAction) {
michael@0 381 let index = pending.indexOf(received);
michael@0 382 if (index != -1) {
michael@0 383 pending.splice(index, 1);
michael@0 384 }
michael@0 385 if (pending.length === 0) {
michael@0 386 nextAction();
michael@0 387 }
michael@0 388 }
michael@0 389
michael@0 390 /**
michael@0 391 * Make an outgoing call.
michael@0 392 *
michael@0 393 * @param number
michael@0 394 * A string.
michael@0 395 * @param serviceId [optional]
michael@0 396 * Identification of a service. 0 is set as default.
michael@0 397 * @return A deferred promise.
michael@0 398 */
michael@0 399 function dial(number, serviceId) {
michael@0 400 serviceId = typeof serviceId !== "undefined" ? serviceId : 0;
michael@0 401 log("Make an outgoing call: " + number + ", serviceId: " + serviceId);
michael@0 402
michael@0 403 let deferred = Promise.defer();
michael@0 404
michael@0 405 telephony.dial(number, serviceId).then(call => {
michael@0 406 ok(call);
michael@0 407 is(call.number, number);
michael@0 408 is(call.state, "dialing");
michael@0 409 is(call.serviceId, serviceId);
michael@0 410
michael@0 411 call.onalerting = function onalerting(event) {
michael@0 412 call.onalerting = null;
michael@0 413 log("Received 'onalerting' call event.");
michael@0 414 checkEventCallState(event, call, "alerting");
michael@0 415 deferred.resolve(call);
michael@0 416 };
michael@0 417 }, cause => {
michael@0 418 deferred.reject(cause);
michael@0 419 });
michael@0 420
michael@0 421 return deferred.promise;
michael@0 422 }
michael@0 423
michael@0 424 /**
michael@0 425 * Answer an incoming call.
michael@0 426 *
michael@0 427 * @param call
michael@0 428 * An incoming TelephonyCall object.
michael@0 429 * @param conferenceStateChangeCallback [optional]
michael@0 430 * A callback function which is called if answering an incoming call
michael@0 431 * triggers conference state change.
michael@0 432 * @return A deferred promise.
michael@0 433 */
michael@0 434 function answer(call, conferenceStateChangeCallback) {
michael@0 435 log("Answering the incoming call.");
michael@0 436
michael@0 437 let deferred = Promise.defer();
michael@0 438 let done = function() {
michael@0 439 deferred.resolve(call);
michael@0 440 };
michael@0 441
michael@0 442 let pending = ["call.onconnected"];
michael@0 443 let receive = function(name) {
michael@0 444 receivedPending(name, pending, done);
michael@0 445 };
michael@0 446
michael@0 447 // When there's already a connected conference call, answering a new incoming
michael@0 448 // call triggers conference state change. We should wait for
michael@0 449 // |conference.onstatechange| before checking the state of the conference call.
michael@0 450 if (conference.state === "connected") {
michael@0 451 pending.push("conference.onstatechange");
michael@0 452 check_onstatechange(conference, "conference", "held", function() {
michael@0 453 if (typeof conferenceStateChangeCallback === "function") {
michael@0 454 conferenceStateChangeCallback();
michael@0 455 }
michael@0 456 receive("conference.onstatechange");
michael@0 457 });
michael@0 458 }
michael@0 459
michael@0 460 call.onconnecting = function onconnectingIn(event) {
michael@0 461 log("Received 'connecting' call event for incoming call.");
michael@0 462 call.onconnecting = null;
michael@0 463 checkEventCallState(event, call, "connecting");
michael@0 464 };
michael@0 465
michael@0 466 call.onconnected = function onconnectedIn(event) {
michael@0 467 log("Received 'connected' call event for incoming call.");
michael@0 468 call.onconnected = null;
michael@0 469 checkEventCallState(event, call, "connected");
michael@0 470 ok(!call.onconnecting);
michael@0 471 receive("call.onconnected");
michael@0 472 };
michael@0 473 call.answer();
michael@0 474
michael@0 475 return deferred.promise;
michael@0 476 }
michael@0 477
michael@0 478 /**
michael@0 479 * Hold a call.
michael@0 480 *
michael@0 481 * @param call
michael@0 482 * A TelephonyCall object.
michael@0 483 * @return A deferred promise.
michael@0 484 */
michael@0 485 function hold(call) {
michael@0 486 log("Putting the call on hold.");
michael@0 487
michael@0 488 let deferred = Promise.defer();
michael@0 489
michael@0 490 let gotHolding = false;
michael@0 491 call.onholding = function onholding(event) {
michael@0 492 log("Received 'holding' call event");
michael@0 493 call.onholding = null;
michael@0 494 checkEventCallState(event, call, "holding");
michael@0 495 gotHolding = true;
michael@0 496 };
michael@0 497
michael@0 498 call.onheld = function onheld(event) {
michael@0 499 log("Received 'held' call event");
michael@0 500 call.onheld = null;
michael@0 501 checkEventCallState(event, call, "held");
michael@0 502 ok(gotHolding);
michael@0 503 deferred.resolve(call);
michael@0 504 };
michael@0 505 call.hold();
michael@0 506
michael@0 507 return deferred.promise;
michael@0 508 }
michael@0 509
michael@0 510 /**
michael@0 511 * Simulate an incoming call.
michael@0 512 *
michael@0 513 * @param number
michael@0 514 * A string.
michael@0 515 * @return A deferred promise.
michael@0 516 */
michael@0 517 function remoteDial(number) {
michael@0 518 log("Simulating an incoming call.");
michael@0 519
michael@0 520 let deferred = Promise.defer();
michael@0 521
michael@0 522 telephony.onincoming = function onincoming(event) {
michael@0 523 log("Received 'incoming' call event.");
michael@0 524 telephony.onincoming = null;
michael@0 525
michael@0 526 let call = event.call;
michael@0 527
michael@0 528 ok(call);
michael@0 529 is(call.number, number);
michael@0 530 is(call.state, "incoming");
michael@0 531
michael@0 532 deferred.resolve(call);
michael@0 533 };
michael@0 534 emulator.run("gsm call " + number);
michael@0 535
michael@0 536 return deferred.promise;
michael@0 537 }
michael@0 538
michael@0 539 /**
michael@0 540 * Remote party answers the call.
michael@0 541 *
michael@0 542 * @param call
michael@0 543 * A TelephonyCall object.
michael@0 544 * @return A deferred promise.
michael@0 545 */
michael@0 546 function remoteAnswer(call) {
michael@0 547 log("Remote answering the call.");
michael@0 548
michael@0 549 let deferred = Promise.defer();
michael@0 550
michael@0 551 call.onconnected = function onconnected(event) {
michael@0 552 log("Received 'connected' call event.");
michael@0 553 call.onconnected = null;
michael@0 554 checkEventCallState(event, call, "connected");
michael@0 555 deferred.resolve(call);
michael@0 556 };
michael@0 557 emulator.run("gsm accept " + call.number);
michael@0 558
michael@0 559 return deferred.promise;
michael@0 560 }
michael@0 561
michael@0 562 /**
michael@0 563 * Remote party hangs up the call.
michael@0 564 *
michael@0 565 * @param call
michael@0 566 * A TelephonyCall object.
michael@0 567 * @return A deferred promise.
michael@0 568 */
michael@0 569 function remoteHangUp(call) {
michael@0 570 log("Remote hanging up the call.");
michael@0 571
michael@0 572 let deferred = Promise.defer();
michael@0 573
michael@0 574 call.ondisconnected = function ondisconnected(event) {
michael@0 575 log("Received 'disconnected' call event.");
michael@0 576 call.ondisconnected = null;
michael@0 577 checkEventCallState(event, call, "disconnected");
michael@0 578 deferred.resolve(call);
michael@0 579 };
michael@0 580 emulator.run("gsm cancel " + call.number);
michael@0 581
michael@0 582 return deferred.promise;
michael@0 583 }
michael@0 584
michael@0 585 /**
michael@0 586 * Remote party hangs up all the calls.
michael@0 587 *
michael@0 588 * @param calls
michael@0 589 * An array of TelephonyCall objects.
michael@0 590 * @return A deferred promise.
michael@0 591 */
michael@0 592 function remoteHangUpCalls(calls) {
michael@0 593 let promise = Promise.resolve();
michael@0 594
michael@0 595 for (let call of calls) {
michael@0 596 promise = promise.then(remoteHangUp.bind(null, call));
michael@0 597 }
michael@0 598
michael@0 599 return promise;
michael@0 600 }
michael@0 601
michael@0 602 /**
michael@0 603 * Add calls to conference.
michael@0 604 *
michael@0 605 * @param callsToAdd
michael@0 606 * An array of TelephonyCall objects to be added into conference. The
michael@0 607 * length of the array should be 1 or 2.
michael@0 608 * @param connectedCallback [optional]
michael@0 609 * A callback function which is called when conference state becomes
michael@0 610 * connected.
michael@0 611 * @return A deferred promise.
michael@0 612 */
michael@0 613 function addCallsToConference(callsToAdd, connectedCallback) {
michael@0 614 log("Add " + callsToAdd.length + " calls into conference.");
michael@0 615
michael@0 616 let deferred = Promise.defer();
michael@0 617 let done = function() {
michael@0 618 deferred.resolve();
michael@0 619 };
michael@0 620
michael@0 621 let pending = ["conference.oncallschanged", "conference.onconnected"];
michael@0 622 let receive = function(name) {
michael@0 623 receivedPending(name, pending, done);
michael@0 624 };
michael@0 625
michael@0 626 let check_onconnected = StateEventChecker('connected', 'onresuming');
michael@0 627
michael@0 628 for (let call of callsToAdd) {
michael@0 629 let callName = "callToAdd (" + call.number + ')';
michael@0 630
michael@0 631 let ongroupchange = callName + ".ongroupchange";
michael@0 632 pending.push(ongroupchange);
michael@0 633 check_ongroupchange(call, callName, conference,
michael@0 634 receive.bind(null, ongroupchange));
michael@0 635
michael@0 636 let onstatechange = callName + ".onstatechange";
michael@0 637 pending.push(onstatechange);
michael@0 638 check_onstatechange(call, callName, 'connected',
michael@0 639 receive.bind(null, onstatechange));
michael@0 640 }
michael@0 641
michael@0 642 check_oncallschanged(conference, 'conference', callsToAdd,
michael@0 643 receive.bind(null, "conference.oncallschanged"));
michael@0 644
michael@0 645 check_onconnected(conference, "conference", function() {
michael@0 646 ok(!conference.oncallschanged);
michael@0 647 if (typeof connectedCallback === 'function') {
michael@0 648 connectedCallback();
michael@0 649 }
michael@0 650 receive("conference.onconnected");
michael@0 651 });
michael@0 652
michael@0 653 // Cannot use apply() through webidl, so just separate the cases to handle.
michael@0 654 if (callsToAdd.length == 2) {
michael@0 655 conference.add(callsToAdd[0], callsToAdd[1]);
michael@0 656 } else {
michael@0 657 conference.add(callsToAdd[0]);
michael@0 658 }
michael@0 659
michael@0 660 return deferred.promise;
michael@0 661 }
michael@0 662
michael@0 663 /**
michael@0 664 * Hold the conference.
michael@0 665 *
michael@0 666 * @param calls
michael@0 667 * An array of TelephonyCall objects existing in conference.
michael@0 668 * @param heldCallback [optional]
michael@0 669 * A callback function which is called when conference state becomes
michael@0 670 * held.
michael@0 671 * @return A deferred promise.
michael@0 672 */
michael@0 673 function holdConference(calls, heldCallback) {
michael@0 674 log("Holding the conference call.");
michael@0 675
michael@0 676 let deferred = Promise.defer();
michael@0 677 let done = function() {
michael@0 678 deferred.resolve();
michael@0 679 };
michael@0 680
michael@0 681 let pending = ["conference.onholding", "conference.onheld"];
michael@0 682 let receive = function(name) {
michael@0 683 receivedPending(name, pending, done);
michael@0 684 };
michael@0 685
michael@0 686 let check_onholding = StateEventChecker('holding', null);
michael@0 687 let check_onheld = StateEventChecker('held', 'onholding');
michael@0 688
michael@0 689 for (let call of calls) {
michael@0 690 let callName = "call (" + call.number + ')';
michael@0 691
michael@0 692 let onholding = callName + ".onholding";
michael@0 693 pending.push(onholding);
michael@0 694 check_onholding(call, callName, receive.bind(null, onholding));
michael@0 695
michael@0 696 let onheld = callName + ".onheld";
michael@0 697 pending.push(onheld);
michael@0 698 check_onheld(call, callName, receive.bind(null, onheld));
michael@0 699 }
michael@0 700
michael@0 701 check_onholding(conference, "conference",
michael@0 702 receive.bind(null, "conference.onholding"));
michael@0 703
michael@0 704 check_onheld(conference, "conference", function() {
michael@0 705 if (typeof heldCallback === 'function') {
michael@0 706 heldCallback();
michael@0 707 }
michael@0 708 receive("conference.onheld");
michael@0 709 });
michael@0 710
michael@0 711 conference.hold();
michael@0 712
michael@0 713 return deferred.promise;
michael@0 714 }
michael@0 715
michael@0 716 /**
michael@0 717 * Resume the conference.
michael@0 718 *
michael@0 719 * @param calls
michael@0 720 * An array of TelephonyCall objects existing in conference.
michael@0 721 * @param connectedCallback [optional]
michael@0 722 * A callback function which is called when conference state becomes
michael@0 723 * connected.
michael@0 724 * @return A deferred promise.
michael@0 725 */
michael@0 726 function resumeConference(calls, connectedCallback) {
michael@0 727 log("Resuming the held conference call.");
michael@0 728
michael@0 729 let deferred = Promise.defer();
michael@0 730 let done = function() {
michael@0 731 deferred.resolve();
michael@0 732 };
michael@0 733
michael@0 734 let pending = ["conference.onresuming", "conference.onconnected"];
michael@0 735 let receive = function(name) {
michael@0 736 receivedPending(name, pending, done);
michael@0 737 };
michael@0 738
michael@0 739 let check_onresuming = StateEventChecker('resuming', null);
michael@0 740 let check_onconnected = StateEventChecker('connected', 'onresuming');
michael@0 741
michael@0 742 for (let call of calls) {
michael@0 743 let callName = "call (" + call.number + ')';
michael@0 744
michael@0 745 let onresuming = callName + ".onresuming";
michael@0 746 pending.push(onresuming);
michael@0 747 check_onresuming(call, callName, receive.bind(null, onresuming));
michael@0 748
michael@0 749 let onconnected = callName + ".onconnected";
michael@0 750 pending.push(onconnected);
michael@0 751 check_onconnected(call, callName, receive.bind(null, onconnected));
michael@0 752 }
michael@0 753
michael@0 754 check_onresuming(conference, "conference",
michael@0 755 receive.bind(null, "conference.onresuming"));
michael@0 756
michael@0 757 check_onconnected(conference, "conference", function() {
michael@0 758 if (typeof connectedCallback === 'function') {
michael@0 759 connectedCallback();
michael@0 760 }
michael@0 761 receive("conference.onconnected");
michael@0 762 });
michael@0 763
michael@0 764 conference.resume();
michael@0 765
michael@0 766 return deferred.promise;
michael@0 767 }
michael@0 768
michael@0 769 /**
michael@0 770 * Remove a call out of conference.
michael@0 771 *
michael@0 772 * @param callToRemove
michael@0 773 * A TelephonyCall object existing in conference.
michael@0 774 * @param autoRemovedCalls
michael@0 775 * An array of TelephonyCall objects which is going to be automatically
michael@0 776 * removed. The length of the array should be 0 or 1.
michael@0 777 * @param remainedCalls
michael@0 778 * An array of TelephonyCall objects which remain in conference.
michael@0 779 * @param stateChangeCallback [optional]
michael@0 780 * A callback function which is called when conference state changes.
michael@0 781 * @return A deferred promise.
michael@0 782 */
michael@0 783 function removeCallInConference(callToRemove, autoRemovedCalls, remainedCalls,
michael@0 784 statechangeCallback) {
michael@0 785 log("Removing a participant from the conference call.");
michael@0 786
michael@0 787 is(conference.state, 'connected');
michael@0 788
michael@0 789 let deferred = Promise.defer();
michael@0 790 let done = function() {
michael@0 791 deferred.resolve();
michael@0 792 };
michael@0 793
michael@0 794 let pending = ["callToRemove.ongroupchange", "telephony.oncallschanged",
michael@0 795 "conference.oncallschanged", "conference.onstatechange"];
michael@0 796 let receive = function(name) {
michael@0 797 receivedPending(name, pending, done);
michael@0 798 };
michael@0 799
michael@0 800 // Remained call in conference will be held.
michael@0 801 for (let call of remainedCalls) {
michael@0 802 let callName = "remainedCall (" + call.number + ')';
michael@0 803
michael@0 804 let onstatechange = callName + ".onstatechange";
michael@0 805 pending.push(onstatechange);
michael@0 806 check_onstatechange(call, callName, 'held',
michael@0 807 receive.bind(null, onstatechange));
michael@0 808 }
michael@0 809
michael@0 810 // When a call is removed from conference with 2 calls, another one will be
michael@0 811 // automatically removed from group and be put on hold.
michael@0 812 for (let call of autoRemovedCalls) {
michael@0 813 let callName = "autoRemovedCall (" + call.number + ')';
michael@0 814
michael@0 815 let ongroupchange = callName + ".ongroupchange";
michael@0 816 pending.push(ongroupchange);
michael@0 817 check_ongroupchange(call, callName, null,
michael@0 818 receive.bind(null, ongroupchange));
michael@0 819
michael@0 820 let onstatechange = callName + ".onstatechange";
michael@0 821 pending.push(onstatechange);
michael@0 822 check_onstatechange(call, callName, 'held',
michael@0 823 receive.bind(null, onstatechange));
michael@0 824 }
michael@0 825
michael@0 826 check_ongroupchange(callToRemove, "callToRemove", null, function() {
michael@0 827 is(callToRemove.state, 'connected');
michael@0 828 receive("callToRemove.ongroupchange");
michael@0 829 });
michael@0 830
michael@0 831 check_oncallschanged(telephony, 'telephony',
michael@0 832 autoRemovedCalls.concat(callToRemove),
michael@0 833 receive.bind(null, "telephony.oncallschanged"));
michael@0 834
michael@0 835 check_oncallschanged(conference, 'conference',
michael@0 836 autoRemovedCalls.concat(callToRemove), function() {
michael@0 837 is(conference.calls.length, remainedCalls.length);
michael@0 838 receive("conference.oncallschanged");
michael@0 839 });
michael@0 840
michael@0 841 check_onstatechange(conference, 'conference',
michael@0 842 (remainedCalls.length ? 'held' : ''), function() {
michael@0 843 ok(!conference.oncallschanged);
michael@0 844 if (typeof statechangeCallback === 'function') {
michael@0 845 statechangeCallback();
michael@0 846 }
michael@0 847 receive("conference.onstatechange");
michael@0 848 });
michael@0 849
michael@0 850 conference.remove(callToRemove);
michael@0 851
michael@0 852 return deferred.promise;
michael@0 853 }
michael@0 854
michael@0 855 /**
michael@0 856 * Hangup a call in conference.
michael@0 857 *
michael@0 858 * @param callToHangUp
michael@0 859 * A TelephonyCall object existing in conference.
michael@0 860 * @param autoRemovedCalls
michael@0 861 * An array of TelephonyCall objects which is going to be automatically
michael@0 862 * removed. The length of the array should be 0 or 1.
michael@0 863 * @param remainedCalls
michael@0 864 * An array of TelephonyCall objects which remain in conference.
michael@0 865 * @param stateChangeCallback [optional]
michael@0 866 * A callback function which is called when conference state changes.
michael@0 867 * @return A deferred promise.
michael@0 868 */
michael@0 869 function hangUpCallInConference(callToHangUp, autoRemovedCalls, remainedCalls,
michael@0 870 statechangeCallback) {
michael@0 871 log("Release one call in conference.");
michael@0 872
michael@0 873 let deferred = Promise.defer();
michael@0 874 let done = function() {
michael@0 875 deferred.resolve();
michael@0 876 };
michael@0 877
michael@0 878 let pending = ["conference.oncallschanged", "remoteHangUp"];
michael@0 879 let receive = function(name) {
michael@0 880 receivedPending(name, pending, done);
michael@0 881 };
michael@0 882
michael@0 883 // When a call is hang up from conference with 2 calls, another one will be
michael@0 884 // automatically removed from group.
michael@0 885 for (let call of autoRemovedCalls) {
michael@0 886 let callName = "autoRemovedCall (" + call.number + ')';
michael@0 887
michael@0 888 let ongroupchange = callName + ".ongroupchange";
michael@0 889 pending.push(ongroupchange);
michael@0 890 check_ongroupchange(call, callName, null,
michael@0 891 receive.bind(null, ongroupchange));
michael@0 892 }
michael@0 893
michael@0 894 if (autoRemovedCalls.length) {
michael@0 895 pending.push("telephony.oncallschanged");
michael@0 896 check_oncallschanged(telephony, 'telephony',
michael@0 897 autoRemovedCalls,
michael@0 898 receive.bind(null, "telephony.oncallschanged"));
michael@0 899 }
michael@0 900
michael@0 901 check_oncallschanged(conference, 'conference',
michael@0 902 autoRemovedCalls.concat(callToHangUp), function() {
michael@0 903 is(conference.calls.length, remainedCalls.length);
michael@0 904 receive("conference.oncallschanged");
michael@0 905 });
michael@0 906
michael@0 907 if (remainedCalls.length === 0) {
michael@0 908 pending.push("conference.onstatechange");
michael@0 909 check_onstatechange(conference, 'conference', '', function() {
michael@0 910 ok(!conference.oncallschanged);
michael@0 911 if (typeof statechangeCallback === 'function') {
michael@0 912 statechangeCallback();
michael@0 913 }
michael@0 914 receive("conference.onstatechange");
michael@0 915 });
michael@0 916 }
michael@0 917
michael@0 918 remoteHangUp(callToHangUp)
michael@0 919 .then(receive.bind(null, "remoteHangUp"));
michael@0 920
michael@0 921 return deferred.promise;
michael@0 922 }
michael@0 923
michael@0 924 /**
michael@0 925 * Setup a conference with an outgoing call and an incoming call.
michael@0 926 *
michael@0 927 * @param outNumber
michael@0 928 * Number of an outgoing call.
michael@0 929 * @param inNumber
michael@0 930 * Number of an incoming call.
michael@0 931 * @return Promise<[outCall, inCall]>
michael@0 932 */
michael@0 933 function setupConferenceTwoCalls(outNumber, inNumber) {
michael@0 934 log('Create conference with two calls.');
michael@0 935
michael@0 936 let outCall;
michael@0 937 let inCall;
michael@0 938 let outInfo = outCallStrPool(outNumber);
michael@0 939 let inInfo = inCallStrPool(inNumber);
michael@0 940
michael@0 941 return Promise.resolve()
michael@0 942 .then(checkInitialState)
michael@0 943 .then(() => dial(outNumber))
michael@0 944 .then(call => { outCall = call; })
michael@0 945 .then(() => checkAll(outCall, [outCall], '', [], [outInfo.ringing]))
michael@0 946 .then(() => remoteAnswer(outCall))
michael@0 947 .then(() => checkAll(outCall, [outCall], '', [], [outInfo.active]))
michael@0 948 .then(() => remoteDial(inNumber))
michael@0 949 .then(call => { inCall = call; })
michael@0 950 .then(() => checkAll(outCall, [outCall, inCall], '', [],
michael@0 951 [outInfo.active, inInfo.incoming]))
michael@0 952 .then(() => answer(inCall))
michael@0 953 .then(() => checkAll(inCall, [outCall, inCall], '', [],
michael@0 954 [outInfo.held, inInfo.active]))
michael@0 955 .then(() => addCallsToConference([outCall, inCall], function() {
michael@0 956 checkState(conference, [], 'connected', [outCall, inCall]);
michael@0 957 }))
michael@0 958 .then(() => checkAll(conference, [], 'connected', [outCall, inCall],
michael@0 959 [outInfo.active, inInfo.active]))
michael@0 960 .then(() => {
michael@0 961 return [outCall, inCall];
michael@0 962 });
michael@0 963 }
michael@0 964
michael@0 965 /**
michael@0 966 * Setup a conference with an outgoing call and two incoming calls.
michael@0 967 *
michael@0 968 * @param outNumber
michael@0 969 * Number of an outgoing call.
michael@0 970 * @param inNumber
michael@0 971 * Number of an incoming call.
michael@0 972 * @param inNumber2
michael@0 973 * Number of an incoming call.
michael@0 974 * @return Promise<[outCall, inCall, inCall2]>
michael@0 975 */
michael@0 976 function setupConferenceThreeCalls(outNumber, inNumber, inNumber2) {
michael@0 977 log('Create conference with three calls.');
michael@0 978
michael@0 979 let outCall;
michael@0 980 let inCall;
michael@0 981 let inCall2;
michael@0 982 let outInfo = outCallStrPool(outNumber);
michael@0 983 let inInfo = inCallStrPool(inNumber);
michael@0 984 let inInfo2 = inCallStrPool(inNumber2);
michael@0 985
michael@0 986 return Promise.resolve()
michael@0 987 .then(() => setupConferenceTwoCalls(outNumber, inNumber))
michael@0 988 .then(calls => {
michael@0 989 outCall = calls[0];
michael@0 990 inCall = calls[1];
michael@0 991 })
michael@0 992 .then(() => remoteDial(inNumber2))
michael@0 993 .then(call => { inCall2 = call; })
michael@0 994 .then(() => checkAll(conference, [inCall2], 'connected', [outCall, inCall],
michael@0 995 [outInfo.active, inInfo.active, inInfo2.incoming]))
michael@0 996 .then(() => answer(inCall2, function() {
michael@0 997 checkState(inCall2, [inCall2], 'held', [outCall, inCall]);
michael@0 998 }))
michael@0 999 .then(() => checkAll(inCall2, [inCall2], 'held', [outCall, inCall],
michael@0 1000 [outInfo.held, inInfo.held, inInfo2.active]))
michael@0 1001 .then(() => addCallsToConference([inCall2], function() {
michael@0 1002 checkState(conference, [], 'connected', [outCall, inCall, inCall2]);
michael@0 1003 }))
michael@0 1004 .then(() => checkAll(conference, [],
michael@0 1005 'connected', [outCall, inCall, inCall2],
michael@0 1006 [outInfo.active, inInfo.active, inInfo2.active]))
michael@0 1007 .then(() => {
michael@0 1008 return [outCall, inCall, inCall2];
michael@0 1009 });
michael@0 1010 }
michael@0 1011
michael@0 1012 /**
michael@0 1013 * Setup a conference with an outgoing call and four incoming calls.
michael@0 1014 *
michael@0 1015 * @param outNumber
michael@0 1016 * Number of an outgoing call.
michael@0 1017 * @param inNumber
michael@0 1018 * Number of an incoming call.
michael@0 1019 * @param inNumber2
michael@0 1020 * Number of an incoming call.
michael@0 1021 * @param inNumber3
michael@0 1022 * Number of an incoming call.
michael@0 1023 * @param inNumber4
michael@0 1024 * Number of an incoming call.
michael@0 1025 * @return Promise<[outCall, inCall, inCall2, inCall3, inCall4]>
michael@0 1026 */
michael@0 1027 function setupConferenceFiveCalls(outNumber, inNumber, inNumber2, inNumber3,
michael@0 1028 inNumber4) {
michael@0 1029 log('Create conference with five calls.');
michael@0 1030
michael@0 1031 let outCall;
michael@0 1032 let inCall;
michael@0 1033 let inCall2;
michael@0 1034 let inCall3;
michael@0 1035 let inCall4;
michael@0 1036 let outInfo = outCallStrPool(outNumber);
michael@0 1037 let inInfo = inCallStrPool(inNumber);
michael@0 1038 let inInfo2 = inCallStrPool(inNumber2);
michael@0 1039 let inInfo3 = inCallStrPool(inNumber3);
michael@0 1040 let inInfo4 = inCallStrPool(inNumber4);
michael@0 1041
michael@0 1042 return Promise.resolve()
michael@0 1043 .then(() => setupConferenceThreeCalls(outNumber, inNumber, inNumber2))
michael@0 1044 .then(calls => {
michael@0 1045 [outCall, inCall, inCall2] = calls;
michael@0 1046 })
michael@0 1047 .then(() => remoteDial(inNumber3))
michael@0 1048 .then(call => {inCall3 = call;})
michael@0 1049 .then(() => checkAll(conference, [inCall3], 'connected',
michael@0 1050 [outCall, inCall, inCall2],
michael@0 1051 [outInfo.active, inInfo.active, inInfo2.active,
michael@0 1052 inInfo3.incoming]))
michael@0 1053 .then(() => answer(inCall3, function() {
michael@0 1054 checkState(inCall3, [inCall3], 'held', [outCall, inCall, inCall2]);
michael@0 1055 }))
michael@0 1056 .then(() => checkAll(inCall3, [inCall3], 'held',
michael@0 1057 [outCall, inCall, inCall2],
michael@0 1058 [outInfo.held, inInfo.held, inInfo2.held,
michael@0 1059 inInfo3.active]))
michael@0 1060 .then(() => addCallsToConference([inCall3], function() {
michael@0 1061 checkState(conference, [], 'connected', [outCall, inCall, inCall2, inCall3]);
michael@0 1062 }))
michael@0 1063 .then(() => checkAll(conference, [], 'connected',
michael@0 1064 [outCall, inCall, inCall2, inCall3],
michael@0 1065 [outInfo.active, inInfo.active, inInfo2.active,
michael@0 1066 inInfo3.active]))
michael@0 1067 .then(() => remoteDial(inNumber4))
michael@0 1068 .then(call => {inCall4 = call;})
michael@0 1069 .then(() => checkAll(conference, [inCall4], 'connected',
michael@0 1070 [outCall, inCall, inCall2, inCall3],
michael@0 1071 [outInfo.active, inInfo.active, inInfo2.active,
michael@0 1072 inInfo3.active, inInfo4.incoming]))
michael@0 1073 .then(() => answer(inCall4, function() {
michael@0 1074 checkState(inCall4, [inCall4], 'held', [outCall, inCall, inCall2, inCall3]);
michael@0 1075 }))
michael@0 1076 .then(() => checkAll(inCall4, [inCall4], 'held',
michael@0 1077 [outCall, inCall, inCall2, inCall3],
michael@0 1078 [outInfo.held, inInfo.held, inInfo2.held,
michael@0 1079 inInfo3.held, inInfo4.active]))
michael@0 1080 .then(() => addCallsToConference([inCall4], function() {
michael@0 1081 checkState(conference, [], 'connected', [outCall, inCall, inCall2,
michael@0 1082 inCall3, inCall4]);
michael@0 1083 }))
michael@0 1084 .then(() => checkAll(conference, [], 'connected',
michael@0 1085 [outCall, inCall, inCall2, inCall3, inCall4],
michael@0 1086 [outInfo.active, inInfo.active, inInfo2.active,
michael@0 1087 inInfo3.active, inInfo4.active]))
michael@0 1088 .then(() => {
michael@0 1089 return [outCall, inCall, inCall2, inCall3, inCall4];
michael@0 1090 });
michael@0 1091 }
michael@0 1092
michael@0 1093 /**
michael@0 1094 * Public members.
michael@0 1095 */
michael@0 1096
michael@0 1097 this.gCheckInitialState = checkInitialState;
michael@0 1098 this.gClearCalls = clearCalls;
michael@0 1099 this.gOutCallStrPool = outCallStrPool;
michael@0 1100 this.gInCallStrPool = inCallStrPool;
michael@0 1101 this.gCheckState = checkState;
michael@0 1102 this.gCheckAll = checkAll;
michael@0 1103 this.gDial = dial;
michael@0 1104 this.gAnswer = answer;
michael@0 1105 this.gHold = hold;
michael@0 1106 this.gRemoteDial = remoteDial;
michael@0 1107 this.gRemoteAnswer = remoteAnswer;
michael@0 1108 this.gRemoteHangUp = remoteHangUp;
michael@0 1109 this.gRemoteHangUpCalls = remoteHangUpCalls;
michael@0 1110 this.gAddCallsToConference = addCallsToConference;
michael@0 1111 this.gHoldConference = holdConference;
michael@0 1112 this.gResumeConference = resumeConference;
michael@0 1113 this.gRemoveCallInConference = removeCallInConference;
michael@0 1114 this.gHangUpCallInConference = hangUpCallInConference;
michael@0 1115 this.gSetupConferenceTwoCalls = setupConferenceTwoCalls;
michael@0 1116 this.gSetupConferenceThreeCalls = setupConferenceThreeCalls;
michael@0 1117 this.gSetupConferenceFiveCalls = setupConferenceFiveCalls;
michael@0 1118 this.gReceivedPending = receivedPending;
michael@0 1119 }());
michael@0 1120
michael@0 1121 function _startTest(permissions, test) {
michael@0 1122 function permissionSetUp() {
michael@0 1123 SpecialPowers.setBoolPref("dom.mozSettings.enabled", true);
michael@0 1124 for (let per of permissions) {
michael@0 1125 SpecialPowers.addPermission(per, true, document);
michael@0 1126 }
michael@0 1127 }
michael@0 1128
michael@0 1129 function permissionTearDown() {
michael@0 1130 SpecialPowers.clearUserPref("dom.mozSettings.enabled");
michael@0 1131 for (let per of permissions) {
michael@0 1132 SpecialPowers.removePermission(per, document);
michael@0 1133 }
michael@0 1134 }
michael@0 1135
michael@0 1136 function setUp() {
michael@0 1137 log("== Test SetUp ==");
michael@0 1138 permissionSetUp();
michael@0 1139 // Make sure that we get the telephony after adding permission.
michael@0 1140 telephony = window.navigator.mozTelephony;
michael@0 1141 ok(telephony);
michael@0 1142 delayTelephonyDial();
michael@0 1143 conference = telephony.conferenceGroup;
michael@0 1144 ok(conference);
michael@0 1145 return gClearCalls().then(gCheckInitialState);
michael@0 1146 }
michael@0 1147
michael@0 1148 // Extend finish() with tear down.
michael@0 1149 finish = (function() {
michael@0 1150 let originalFinish = finish;
michael@0 1151
michael@0 1152 function tearDown() {
michael@0 1153 log("== Test TearDown ==");
michael@0 1154 restoreTelephonyDial();
michael@0 1155 emulator.waitFinish()
michael@0 1156 .then(permissionTearDown)
michael@0 1157 .then(function() {
michael@0 1158 originalFinish.apply(this, arguments);
michael@0 1159 });
michael@0 1160 }
michael@0 1161
michael@0 1162 return tearDown.bind(this);
michael@0 1163 }());
michael@0 1164
michael@0 1165 function mainTest() {
michael@0 1166 setUp()
michael@0 1167 .then(function onSuccess() {
michael@0 1168 log("== Test Start ==");
michael@0 1169 test();
michael@0 1170 }, function onError(error) {
michael@0 1171 SpecialPowers.Cu.reportError(error);
michael@0 1172 ok(false, "SetUp error");
michael@0 1173 });
michael@0 1174 }
michael@0 1175
michael@0 1176 mainTest();
michael@0 1177 }
michael@0 1178
michael@0 1179 function startTest(test) {
michael@0 1180 _startTest(["telephony"], test);
michael@0 1181 }
michael@0 1182
michael@0 1183 function startTestWithPermissions(permissions, test) {
michael@0 1184 _startTest(permissions.concat("telephony"), test);
michael@0 1185 }
michael@0 1186
michael@0 1187 function startDSDSTest(test) {
michael@0 1188 let numRIL;
michael@0 1189 try {
michael@0 1190 numRIL = SpecialPowers.getIntPref("ril.numRadioInterfaces");
michael@0 1191 } catch (ex) {
michael@0 1192 numRIL = 1; // Pref not set.
michael@0 1193 }
michael@0 1194
michael@0 1195 if (numRIL > 1) {
michael@0 1196 startTest(test);
michael@0 1197 } else {
michael@0 1198 log("Not a DSDS environment. Test is skipped.");
michael@0 1199 ok(true); // We should run at least one test.
michael@0 1200 finish();
michael@0 1201 }
michael@0 1202 }

mercurial