anchor.diff:        spark.showErrorMessage(
             'Unable to deploy', message: 'No USB devices available.');
       } else {
  +       MobileDeploy deployer = new MobileDeploy(deployContainer, spark.localPrefs);
         _restoreDialog();
         _show();
       }
     }
   
  +  Future<List> _loadDevices() {
  +    Completer completer = new Completer();
  +
  +    Function cb = (result) {
  +      completer.complete(result);
  +    };
  +
  +    var context = js.context['chrome']['usb'];
  +    var options = new js.JsObject.jsify({});
  +    try {
  +      context.callMethod("getDevices", [options, cb]);
  +    } catch (e) {
  +      // user cancelled the operation.
  +    }
  +    return completer.future;
  +  }
  +
  +  void _loadUsbDevices() {
  +    _usbDevices.length = 0;
  +    _loadDevices().then((deviceInfos) {
  +      deviceInfos.forEach((info) {
  +        String option =
  +            "(productId:${info['productId']}, vendorId:${info['vendorId']}";
  +        String value = "${info['productId']}:${info['vendorId']}";
  +        _usbDevices.append(new OptionElement(data: option, value: value ));
  +      });
  +    });
  +  }
  +
     void _enableInputs([_]) {
       _pushUrlElement.disabled = !_ipElement.checked;
  +    _usbDevices.disabled = _ipElement.checked;
  +    _addDeviceButton.disabled = _ipElement.checked;
  +  }
  +
  +   /**
  +   * Opens a dialog and provides a list of active adb devices to select from.
  +   * It allows to select a single device at a time.
  +  */
  +  Future _addDevice() {
  +    Completer completer = new Completer();
  +
  +    Function cb = (result) {
  +      completer.complete();
  +      _loadUsbDevices();
  +    };
  +
  +    var context = js.context['chrome']['usb'];
  +    var options = new js.JsObject.jsify({'filters': [new js.JsObject.jsify({
  +      'interfaceClass': 0xff,
  +      'interfaceSubclass': 0x42,
  +      'interfaceProtocol': 0x01
  +    })]});
  +    try {
  +      context.callMethod("getUserSelectedDevices", [options, cb]);
  +    } catch (e) {
  +      // user cancelled the operation.
  +    }
  +    return completer.future;
     }
   
     void _toggleProgressVisible(bool visible) {
  
positive.code:       : super(spark, "deploy-app-old", "Deploy to Mobile", dialog) {
      _ipElement = getElement("#ip");
      _adbElement = getElement("#adb");
      _liveDeployCheckBox = getElement("#liveDeploy");
      _pushUrlElement = _triggerOnReturn("#pushUrl");
  
      _ipElement.onChange.listen(_enableInputs);
      _adbElement.onChange.listen(_enableInputs);
      _liveDeployCheckBox.onChange.listen((_) =>
          spark.localPrefs.setValue("live-deployment", _liveDeployCheckBox.checked));
      _enableInputs();
    }
  
  
negative.code: 
      MobileDeploy deployer = new MobileDeploy(deployContainer, spark.localPrefs);
  
      Future f;
  
      if (useAdb && SparkFlags.enableNewUsbApi == true) {
        int index = _usbDevices.selectedIndex;
         String deviceInfo =
             (_usbDevices.children[index] as OptionElement).value;
         List<String> info = deviceInfo.split(':');
         int productId = int.parse(info[0]);
         int vendorId = int.parse(info[1]);
         f = new Future(() {
           return deployer.pushAdb(_monitor, productId: productId, vendorId: vendorId);
         });
      } else {
        // Invoke the deployer methods in Futures in order to capture exceptions.
        f = new Future(() {
          return useAdb ?
              deployer.pushAdb(_monitor) : deployer.pushToHost(url, _monitor);
        });
      }
  
      _monitor.runCancellableFuture(f).then((_) {
        _hide();
  