dom/bluetooth/tests/marionette/head.js

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/dom/bluetooth/tests/marionette/head.js	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,588 @@
     1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
     1.5 + * vim: sw=2 ts=2 sts=2 et filetype=javascript
     1.6 + * This Source Code Form is subject to the terms of the Mozilla Public
     1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this file,
     1.8 + * You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.9 +
    1.10 +// https://github.com/mozilla-b2g/platform_external_qemu/blob/master/vl-android.c#L765
    1.11 +// static int bt_hci_parse(const char *str) {
    1.12 +//   ...
    1.13 +//   bdaddr.b[0] = 0x52;
    1.14 +//   bdaddr.b[1] = 0x54;
    1.15 +//   bdaddr.b[2] = 0x00;
    1.16 +//   bdaddr.b[3] = 0x12;
    1.17 +//   bdaddr.b[4] = 0x34;
    1.18 +//   bdaddr.b[5] = 0x56 + nb_hcis;
    1.19 +const EMULATOR_ADDRESS = "56:34:12:00:54:52";
    1.20 +
    1.21 +// $ adb shell hciconfig /dev/ttyS2 name
    1.22 +// hci0:  Type: BR/EDR  Bus: UART
    1.23 +//        BD Address: 56:34:12:00:54:52  ACL MTU: 512:1  SCO MTU: 0:0
    1.24 +//        Name: 'Full Android on Emulator'
    1.25 +const EMULATOR_NAME = "Full Android on Emulator";
    1.26 +
    1.27 +// $ adb shell hciconfig /dev/ttyS2 class
    1.28 +// hci0:  Type: BR/EDR  Bus: UART
    1.29 +//        BD Address: 56:34:12:00:54:52  ACL MTU: 512:1  SCO MTU: 0:0
    1.30 +//        Class: 0x58020c
    1.31 +//        Service Classes: Capturing, Object Transfer, Telephony
    1.32 +//        Device Class: Phone, Smart phone
    1.33 +const EMULATOR_CLASS = 0x58020c;
    1.34 +
    1.35 +// Use same definition in QEMU for special bluetooth address,
    1.36 +// which were defined at external/qemu/hw/bt.h:
    1.37 +const BDADDR_ANY   = "00:00:00:00:00:00";
    1.38 +const BDADDR_ALL   = "ff:ff:ff:ff:ff:ff";
    1.39 +const BDADDR_LOCAL = "ff:ff:ff:00:00:00";
    1.40 +
    1.41 +// A user friendly name for remote BT device.
    1.42 +const REMOTE_DEVICE_NAME = "Remote BT Device";
    1.43 +
    1.44 +let Promise =
    1.45 +  SpecialPowers.Cu.import("resource://gre/modules/Promise.jsm").Promise;
    1.46 +
    1.47 +let bluetoothManager;
    1.48 +
    1.49 +let pendingEmulatorCmdCount = 0;
    1.50 +
    1.51 +/**
    1.52 + * Send emulator command with safe guard.
    1.53 + *
    1.54 + * We should only call |finish()| after all emulator command transactions
    1.55 + * end, so here comes with the pending counter.  Resolve when the emulator
    1.56 + * gives positive response, and reject otherwise.
    1.57 + *
    1.58 + * Fulfill params:
    1.59 + *   result -- an array of emulator response lines.
    1.60 + *
    1.61 + * Reject params:
    1.62 + *   result -- an array of emulator response lines.
    1.63 + *
    1.64 + * @return A deferred promise.
    1.65 + */
    1.66 +function runEmulatorCmdSafe(aCommand) {
    1.67 +  let deferred = Promise.defer();
    1.68 +
    1.69 +  ++pendingEmulatorCmdCount;
    1.70 +  runEmulatorCmd(aCommand, function(aResult) {
    1.71 +    --pendingEmulatorCmdCount;
    1.72 +
    1.73 +    ok(true, "Emulator response: " + JSON.stringify(aResult));
    1.74 +    if (Array.isArray(aResult) && aResult[aResult.length - 1] === "OK") {
    1.75 +      deferred.resolve(aResult);
    1.76 +    } else {
    1.77 +      ok(false, "Got an abnormal response from emulator.");
    1.78 +      log("Fail to execute emulator command: [" + aCommand + "]");
    1.79 +      deferred.reject(aResult);
    1.80 +    }
    1.81 +  });
    1.82 +
    1.83 +  return deferred.promise;
    1.84 +}
    1.85 +
    1.86 +/**
    1.87 + * Add a Bluetooth remote device to scatternet and set its properties.
    1.88 + *
    1.89 + * Use QEMU command 'bt remote add' to add a virtual Bluetooth remote
    1.90 + * and set its properties by setEmulatorDeviceProperty().
    1.91 + *
    1.92 + * Fulfill params:
    1.93 + *   result -- bluetooth address of the remote device.
    1.94 + * Reject params: (none)
    1.95 + *
    1.96 + * @param aProperies
    1.97 + *        A javascript object with zero or several properties for initializing
    1.98 + *        the remote device. By now, the properies could be 'name' or
    1.99 + *        'discoverable'. It valid to put a null object or a javascript object
   1.100 + *        which don't have any properies.
   1.101 + *
   1.102 + * @return A promise object.
   1.103 + */
   1.104 +function addEmulatorRemoteDevice(aProperties) {
   1.105 +  let address;
   1.106 +  let promise = runEmulatorCmdSafe("bt remote add")
   1.107 +    .then(function(aResults) {
   1.108 +      address = aResults[0].toUpperCase();
   1.109 +    });
   1.110 +
   1.111 +  for (let key in aProperties) {
   1.112 +    let value = aProperties[key];
   1.113 +    let propertyName = key;
   1.114 +    promise = promise.then(function() {
   1.115 +      return setEmulatorDeviceProperty(address, propertyName, value);
   1.116 +    });
   1.117 +  }
   1.118 +
   1.119 +  return promise.then(function() {
   1.120 +    return address;
   1.121 +  });
   1.122 +}
   1.123 +
   1.124 +/**
   1.125 + * Remove Bluetooth remote devices in scatternet.
   1.126 + *
   1.127 + * Use QEMU command 'bt remote remove <addr>' to remove a specific virtual
   1.128 + * Bluetooth remote device in scatternet or remove them all by  QEMU command
   1.129 + * 'bt remote remove BDADDR_ALL'.
   1.130 + *
   1.131 + * @param aAddress
   1.132 + *        The string of Bluetooth address with format xx:xx:xx:xx:xx:xx.
   1.133 + *
   1.134 + * Fulfill params:
   1.135 + *   result -- an array of emulator response lines.
   1.136 + * Reject params: (none)
   1.137 + *
   1.138 + * @return A promise object.
   1.139 + */
   1.140 +function removeEmulatorRemoteDevice(aAddress) {
   1.141 +  let cmd = "bt remote remove " + aAddress;
   1.142 +  return runEmulatorCmdSafe(cmd)
   1.143 +    .then(function(aResults) {
   1.144 +      // 'bt remote remove <bd_addr>' returns a list of removed device one at a line.
   1.145 +      // The last item is "OK".
   1.146 +      return aResults.slice(0, -1);
   1.147 +    });
   1.148 +}
   1.149 +
   1.150 +/**
   1.151 + * Set a property for a Bluetooth device.
   1.152 + *
   1.153 + * Use QEMU command 'bt property <bd_addr> <prop_name> <value>' to set property.
   1.154 + *
   1.155 + * Fulfill params:
   1.156 + *   result -- an array of emulator response lines.
   1.157 + * Reject params:
   1.158 + *   result -- an array of emulator response lines.
   1.159 + *
   1.160 + * @param aAddress
   1.161 + *        The string of Bluetooth address with format xx:xx:xx:xx:xx:xx.
   1.162 + * @param aPropertyName
   1.163 + *        The property name of Bluetooth device.
   1.164 + * @param aValue
   1.165 + *        The new value of the specifc property.
   1.166 + *
   1.167 + * @return A deferred promise.
   1.168 + */
   1.169 +function setEmulatorDeviceProperty(aAddress, aPropertyName, aValue) {
   1.170 +  let cmd = "bt property " + aAddress + " " + aPropertyName + " " + aValue;
   1.171 +  return runEmulatorCmdSafe(cmd);
   1.172 +}
   1.173 +
   1.174 +/**
   1.175 + * Get a property from a Bluetooth device.
   1.176 + *
   1.177 + * Use QEMU command 'bt property <bd_addr> <prop_name>' to get properties.
   1.178 + *
   1.179 + * Fulfill params:
   1.180 + *   result -- a string with format <prop_name>: <value_of_prop>
   1.181 + * Reject params:
   1.182 + *   result -- an array of emulator response lines.
   1.183 + *
   1.184 + * @param aAddress
   1.185 + *        The string of Bluetooth address with format xx:xx:xx:xx:xx:xx.
   1.186 + * @param aPropertyName
   1.187 + *        The property name of Bluetooth device.
   1.188 + *
   1.189 + * @return A deferred promise.
   1.190 + */
   1.191 +function getEmulatorDeviceProperty(aAddress, aPropertyName) {
   1.192 +  let cmd = "bt property " + aAddress + " " + aPropertyName;
   1.193 +  return runEmulatorCmdSafe(cmd)
   1.194 +    .then(function(aResults) {
   1.195 +      return aResults[0];
   1.196 +    });
   1.197 +}
   1.198 +
   1.199 +/**
   1.200 + * Start dicovering Bluetooth devices.
   1.201 + *
   1.202 + * Allows the device's adapter to start seeking for remote devices.
   1.203 + *
   1.204 + * Fulfill params: (none)
   1.205 + * Reject params: a DOMError
   1.206 + *
   1.207 + * @param aAdapter
   1.208 + *        A BluetoothAdapter which is used to interact with local BT dev
   1.209 + *
   1.210 + * @return A deferred promise.
   1.211 + */
   1.212 +function startDiscovery(aAdapter) {
   1.213 +  let deferred = Promise.defer();
   1.214 +
   1.215 +  let request = aAdapter.startDiscovery();
   1.216 +  request.onsuccess = function () {
   1.217 +    log("  Start discovery - Success");
   1.218 +    // TODO (bug 892207): Make Bluetooth APIs available for 3rd party apps.
   1.219 +    //     Currently, discovering state wouldn't change immediately here.
   1.220 +    //     We would turn on this check when the redesigned API are landed.
   1.221 +    // is(aAdapter.discovering, true, "BluetoothAdapter.discovering");
   1.222 +    deferred.resolve();
   1.223 +  }
   1.224 +  request.onerror = function (aEvent) {
   1.225 +    ok(false, "Start discovery - Fail");
   1.226 +    deferred.reject(aEvent.target.error);
   1.227 +  }
   1.228 +
   1.229 +  return deferred.promise;
   1.230 +}
   1.231 +
   1.232 +/**
   1.233 + * Stop dicovering Bluetooth devices.
   1.234 + *
   1.235 + * Allows the device's adapter to stop seeking for remote devices.
   1.236 + *
   1.237 + * Fulfill params: (none)
   1.238 + * Reject params: a DOMError
   1.239 + *
   1.240 + * @param aAdapter
   1.241 + *        A BluetoothAdapter which is used to interact with local BT device.
   1.242 + *
   1.243 + * @return A deferred promise.
   1.244 + */
   1.245 +function stopDiscovery(aAdapter) {
   1.246 +  let deferred = Promise.defer();
   1.247 +
   1.248 +  let request = aAdapter.stopDiscovery();
   1.249 +  request.onsuccess = function () {
   1.250 +    log("  Stop discovery - Success");
   1.251 +    // TODO (bug 892207): Make Bluetooth APIs available for 3rd party apps.
   1.252 +    //     Currently, discovering state wouldn't change immediately here.
   1.253 +    //     We would turn on this check when the redesigned API are landed.
   1.254 +    // is(aAdapter.discovering, false, "BluetoothAdapter.discovering");
   1.255 +    deferred.resolve();
   1.256 +  }
   1.257 +  request.onerror = function (aEvent) {
   1.258 +    ok(false, "Stop discovery - Fail");
   1.259 +    deferred.reject(aEvent.target.error);
   1.260 +  }
   1.261 +  return deferred.promise;
   1.262 +}
   1.263 +
   1.264 +/**
   1.265 + * Get mozSettings value specified by @aKey.
   1.266 + *
   1.267 + * Resolve if that mozSettings value is retrieved successfully, reject
   1.268 + * otherwise.
   1.269 + *
   1.270 + * Fulfill params:
   1.271 + *   The corresponding mozSettings value of the key.
   1.272 + * Reject params: (none)
   1.273 + *
   1.274 + * @param aKey
   1.275 + *        A string.
   1.276 + *
   1.277 + * @return A deferred promise.
   1.278 + */
   1.279 +function getSettings(aKey) {
   1.280 +  let deferred = Promise.defer();
   1.281 +
   1.282 +  let request = navigator.mozSettings.createLock().get(aKey);
   1.283 +  request.addEventListener("success", function(aEvent) {
   1.284 +    ok(true, "getSettings(" + aKey + ")");
   1.285 +    deferred.resolve(aEvent.target.result[aKey]);
   1.286 +  });
   1.287 +  request.addEventListener("error", function() {
   1.288 +    ok(false, "getSettings(" + aKey + ")");
   1.289 +    deferred.reject();
   1.290 +  });
   1.291 +
   1.292 +  return deferred.promise;
   1.293 +}
   1.294 +
   1.295 +/**
   1.296 + * Set mozSettings values.
   1.297 + *
   1.298 + * Resolve if that mozSettings value is set successfully, reject otherwise.
   1.299 + *
   1.300 + * Fulfill params: (none)
   1.301 + * Reject params: (none)
   1.302 + *
   1.303 + * @param aSettings
   1.304 + *        An object of format |{key1: value1, key2: value2, ...}|.
   1.305 + *
   1.306 + * @return A deferred promise.
   1.307 + */
   1.308 +function setSettings(aSettings) {
   1.309 +  let deferred = Promise.defer();
   1.310 +
   1.311 +  let request = navigator.mozSettings.createLock().set(aSettings);
   1.312 +  request.addEventListener("success", function() {
   1.313 +    ok(true, "setSettings(" + JSON.stringify(aSettings) + ")");
   1.314 +    deferred.resolve();
   1.315 +  });
   1.316 +  request.addEventListener("error", function() {
   1.317 +    ok(false, "setSettings(" + JSON.stringify(aSettings) + ")");
   1.318 +    deferred.reject();
   1.319 +  });
   1.320 +
   1.321 +  return deferred.promise;
   1.322 +}
   1.323 +
   1.324 +/**
   1.325 + * Get mozSettings value of 'bluetooth.enabled'.
   1.326 + *
   1.327 + * Resolve if that mozSettings value is retrieved successfully, reject
   1.328 + * otherwise.
   1.329 + *
   1.330 + * Fulfill params:
   1.331 + *   A boolean value.
   1.332 + * Reject params: (none)
   1.333 + *
   1.334 + * @return A deferred promise.
   1.335 + */
   1.336 +function getBluetoothEnabled() {
   1.337 +  return getSettings("bluetooth.enabled");
   1.338 +}
   1.339 +
   1.340 +/**
   1.341 + * Set mozSettings value of 'bluetooth.enabled'.
   1.342 + *
   1.343 + * Resolve if that mozSettings value is set successfully, reject otherwise.
   1.344 + *
   1.345 + * Fulfill params: (none)
   1.346 + * Reject params: (none)
   1.347 + *
   1.348 + * @param aEnabled
   1.349 + *        A boolean value.
   1.350 + *
   1.351 + * @return A deferred promise.
   1.352 + */
   1.353 +function setBluetoothEnabled(aEnabled) {
   1.354 +  let obj = {};
   1.355 +  obj["bluetooth.enabled"] = aEnabled;
   1.356 +  return setSettings(obj);
   1.357 +}
   1.358 +
   1.359 +/**
   1.360 + * Push required permissions and test if |navigator.mozBluetooth| exists.
   1.361 + * Resolve if it does, reject otherwise.
   1.362 + *
   1.363 + * Fulfill params:
   1.364 + *   bluetoothManager -- an reference to navigator.mozBluetooth.
   1.365 + * Reject params: (none)
   1.366 + *
   1.367 + * @param aPermissions
   1.368 + *        Additional permissions to push before any test cases.  Could be either
   1.369 + *        a string or an array of strings.
   1.370 + *
   1.371 + * @return A deferred promise.
   1.372 + */
   1.373 +function ensureBluetoothManager(aPermissions) {
   1.374 +  let deferred = Promise.defer();
   1.375 +
   1.376 +  let permissions = ["bluetooth"];
   1.377 +  if (aPermissions) {
   1.378 +    if (Array.isArray(aPermissions)) {
   1.379 +      permissions = permissions.concat(aPermissions);
   1.380 +    } else if (typeof aPermissions == "string") {
   1.381 +      permissions.push(aPermissions);
   1.382 +    }
   1.383 +  }
   1.384 +
   1.385 +  let obj = [];
   1.386 +  for (let perm of permissions) {
   1.387 +    obj.push({
   1.388 +      "type": perm,
   1.389 +      "allow": 1,
   1.390 +      "context": document,
   1.391 +    });
   1.392 +  }
   1.393 +
   1.394 +  SpecialPowers.pushPermissions(obj, function() {
   1.395 +    ok(true, "permissions pushed: " + JSON.stringify(permissions));
   1.396 +
   1.397 +    bluetoothManager = window.navigator.mozBluetooth;
   1.398 +    log("navigator.mozBluetooth is " +
   1.399 +        (bluetoothManager ? "available" : "unavailable"));
   1.400 +
   1.401 +    if (bluetoothManager instanceof BluetoothManager) {
   1.402 +      deferred.resolve(bluetoothManager);
   1.403 +    } else {
   1.404 +      deferred.reject();
   1.405 +    }
   1.406 +  });
   1.407 +
   1.408 +  return deferred.promise;
   1.409 +}
   1.410 +
   1.411 +/**
   1.412 + * Wait for one named BluetoothManager event.
   1.413 + *
   1.414 + * Resolve if that named event occurs.  Never reject.
   1.415 + *
   1.416 + * Fulfill params: the DOMEvent passed.
   1.417 + *
   1.418 + * @param aEventName
   1.419 + *        The name of the EventHandler.
   1.420 + *
   1.421 + * @return A deferred promise.
   1.422 + */
   1.423 +function waitForManagerEvent(aEventName) {
   1.424 +  let deferred = Promise.defer();
   1.425 +
   1.426 +  bluetoothManager.addEventListener(aEventName, function onevent(aEvent) {
   1.427 +    bluetoothManager.removeEventListener(aEventName, onevent);
   1.428 +
   1.429 +    ok(true, "BluetoothManager event '" + aEventName + "' got.");
   1.430 +    deferred.resolve(aEvent);
   1.431 +  });
   1.432 +
   1.433 +  return deferred.promise;
   1.434 +}
   1.435 +
   1.436 +/**
   1.437 + * Wait for one named BluetoothAdapter event.
   1.438 + *
   1.439 + * Resolve if that named event occurs.  Never reject.
   1.440 + *
   1.441 + * Fulfill params: the DOMEvent passed.
   1.442 + *
   1.443 + * @param aAdapter
   1.444 + *        The BluetoothAdapter you want to use.
   1.445 + * @param aEventName
   1.446 + *        The name of the EventHandler.
   1.447 + *
   1.448 + * @return A deferred promise.
   1.449 + */
   1.450 +function waitForAdapterEvent(aAdapter, aEventName) {
   1.451 +  let deferred = Promise.defer();
   1.452 +
   1.453 +  aAdapter.addEventListener(aEventName, function onevent(aEvent) {
   1.454 +    aAdapter.removeEventListener(aEventName, onevent);
   1.455 +
   1.456 +    ok(true, "BluetoothAdapter event '" + aEventName + "' got.");
   1.457 +    deferred.resolve(aEvent);
   1.458 +  });
   1.459 +
   1.460 +  return deferred.promise;
   1.461 +}
   1.462 +
   1.463 +/**
   1.464 + * Convenient function for setBluetoothEnabled and waitForManagerEvent
   1.465 + * combined.
   1.466 + *
   1.467 + * Resolve if that named event occurs.  Reject if we can't set settings.
   1.468 + *
   1.469 + * Fulfill params: the DOMEvent passed.
   1.470 + * Reject params: (none)
   1.471 + *
   1.472 + * @return A deferred promise.
   1.473 + */
   1.474 +function setBluetoothEnabledAndWait(aEnabled) {
   1.475 +  let promises = [];
   1.476 +
   1.477 +  // Bug 969109 -  Intermittent test_dom_BluetoothManager_adapteradded.js
   1.478 +  //
   1.479 +  // Here we want to wait for two events coming up -- Bluetooth "settings-set"
   1.480 +  // event and one of "enabled"/"disabled" events.  Special care is taken here
   1.481 +  // to ensure that we can always receive that "enabled"/"disabled" event by
   1.482 +  // installing the event handler *before* we ever enable/disable Bluetooth. Or
   1.483 +  // we might just miss those events and get a timeout error.
   1.484 +  promises.push(waitForManagerEvent(aEnabled ? "enabled" : "disabled"));
   1.485 +  promises.push(setBluetoothEnabled(aEnabled));
   1.486 +
   1.487 +  return Promise.all(promises);
   1.488 +}
   1.489 +
   1.490 +/**
   1.491 + * Get default adapter.
   1.492 + *
   1.493 + * Resolve if that default adapter is got, reject otherwise.
   1.494 + *
   1.495 + * Fulfill params: a BluetoothAdapter instance.
   1.496 + * Reject params: a DOMError, or null if if there is no adapter ready yet.
   1.497 + *
   1.498 + * @return A deferred promise.
   1.499 + */
   1.500 +function getDefaultAdapter() {
   1.501 +  let deferred = Promise.defer();
   1.502 +
   1.503 +  let request = bluetoothManager.getDefaultAdapter();
   1.504 +  request.onsuccess = function(aEvent) {
   1.505 +    let adapter = aEvent.target.result;
   1.506 +    if (!(adapter instanceof BluetoothAdapter)) {
   1.507 +      ok(false, "no BluetoothAdapter ready yet.");
   1.508 +      deferred.reject(null);
   1.509 +      return;
   1.510 +    }
   1.511 +
   1.512 +    ok(true, "BluetoothAdapter got.");
   1.513 +    // TODO: We have an adapter instance now, but some of its attributes may
   1.514 +    // still remain unassigned/out-dated.  Here we waste a few seconds to
   1.515 +    // wait for the property changed events.
   1.516 +    //
   1.517 +    // See https://bugzilla.mozilla.org/show_bug.cgi?id=932914
   1.518 +    window.setTimeout(function() {
   1.519 +      deferred.resolve(adapter);
   1.520 +    }, 3000);
   1.521 +  };
   1.522 +  request.onerror = function(aEvent) {
   1.523 +    ok(false, "Failed to get default adapter.");
   1.524 +    deferred.reject(aEvent.target.error);
   1.525 +  };
   1.526 +
   1.527 +  return deferred.promise;
   1.528 +}
   1.529 +
   1.530 +/**
   1.531 + * Flush permission settings and call |finish()|.
   1.532 + */
   1.533 +function cleanUp() {
   1.534 +  waitFor(function() {
   1.535 +    SpecialPowers.flushPermissions(function() {
   1.536 +      // Use ok here so that we have at least one test run.
   1.537 +      ok(true, "permissions flushed");
   1.538 +
   1.539 +      finish();
   1.540 +    });
   1.541 +  }, function() {
   1.542 +    return pendingEmulatorCmdCount === 0;
   1.543 +  });
   1.544 +}
   1.545 +
   1.546 +function startBluetoothTestBase(aPermissions, aTestCaseMain) {
   1.547 +  ensureBluetoothManager(aPermissions)
   1.548 +    .then(aTestCaseMain)
   1.549 +    .then(cleanUp, function() {
   1.550 +      ok(false, "Unhandled rejected promise.");
   1.551 +      cleanUp();
   1.552 +    });
   1.553 +}
   1.554 +
   1.555 +function startBluetoothTest(aReenable, aTestCaseMain) {
   1.556 +  startBluetoothTestBase(["settings-read", "settings-write"], function() {
   1.557 +    let origEnabled, needEnable;
   1.558 +
   1.559 +    return getBluetoothEnabled()
   1.560 +      .then(function(aEnabled) {
   1.561 +        origEnabled = aEnabled;
   1.562 +        needEnable = !aEnabled;
   1.563 +        log("Original 'bluetooth.enabled' is " + origEnabled);
   1.564 +
   1.565 +        if (aEnabled && aReenable) {
   1.566 +          log("  Disable 'bluetooth.enabled' ...");
   1.567 +          needEnable = true;
   1.568 +          return setBluetoothEnabledAndWait(false);
   1.569 +        }
   1.570 +      })
   1.571 +      .then(function() {
   1.572 +        if (needEnable) {
   1.573 +          log("  Enable 'bluetooth.enabled' ...");
   1.574 +
   1.575 +          // See setBluetoothEnabledAndWait().  We must install all event
   1.576 +          // handlers *before* enabling Bluetooth.
   1.577 +          let promises = [];
   1.578 +          promises.push(waitForManagerEvent("adapteradded"));
   1.579 +          promises.push(setBluetoothEnabledAndWait(true));
   1.580 +          return Promise.all(promises);
   1.581 +        }
   1.582 +      })
   1.583 +      .then(getDefaultAdapter)
   1.584 +      .then(aTestCaseMain)
   1.585 +      .then(function() {
   1.586 +        if (!origEnabled) {
   1.587 +          return setBluetoothEnabledAndWait(false);
   1.588 +        }
   1.589 +      });
   1.590 +  });
   1.591 +}

mercurial