Commit 9c7e3c2d authored by Steven Bennetts's avatar Steven Bennetts Committed by Commit Bot

Settings: Move bluetooth dialog to a shared location

This CL is in preparation for converting the bluetooth pairing dialog
(BluetoothPairingUI) to use the MD Settings UI.

This CL:
* Eliminate Settings dependencies from the bluetooth dialog element
  and moves some dialog related error parsing into the dialog element.
* Moves some 'options' strings to settings_strings.grd in anticipation
  of removal of all options strings.
* Adds a new shared location for higher level shared chromeos
  elements: ui/webui/resources/chromeos. These elements are allowed to
  use I18nBehavior to simplify localization.
* Moves the bluetooth dialog element to the new shared location.

Bug: 748193
Cq-Include-Trybots: master.tryserver.chromium.linux:closure_compilation
Change-Id: I861730aa9cbbe5cb37a8df3d26f62d9f20429672
Reviewed-on: https://chromium-review.googlesource.com/592461
Commit-Queue: Steven Bennetts <stevenjb@chromium.org>
Reviewed-by: default avatarDirk Pranke <dpranke@chromium.org>
Reviewed-by: default avatarDemetrios Papadopoulos <dpapad@chromium.org>
Reviewed-by: default avatarTommy Li <tommycli@chromium.org>
Reviewed-by: default avatarMichael Giuffrida <michaelpg@chromium.org>
Cr-Commit-Position: refs/heads/master@{#491459}
parent 7f5284e3
......@@ -2041,8 +2041,9 @@ def _CheckForRiskyJsConstLet(input_api, line_number, line):
def _CheckForRiskyJsFeatures(input_api, output_api):
maybe_ios_js = (r"^(ios|components|ui\/webui\/resources)\/.+\.js$", )
file_filter = lambda f: input_api.FilterSourceFile(f, white_list=maybe_ios_js)
chromeos_filter = (r".*chromeos.*", )
file_filter = lambda f: input_api.FilterSourceFile(f, white_list=maybe_ios_js,
black_list=chromeos_filter)
results = []
for f in input_api.AffectedFiles(file_filter=file_filter):
arrow_error_lines = []
......
......@@ -555,6 +555,21 @@
<message name="IDS_SETTINGS_BLUETOOTH_TOGGLE_ACCESSIBILITY_LABEL" desc="Accessibility only label for Bluetooth enable/disable toggle.">
Bluetooth enable
</message>
<message name="IDS_SETTINGS_BLUETOOTH_ENTER_KEY" desc="Bluetooth pairing dialog: Text for enter key when pairing keyboard devices." >
enter
</message>
<message name="IDS_SETTINGS_BLUETOOTH_ACCEPT_PASSKEY" desc="Bluetooth pairing dialog: Text for button to accept pairing code.">
Accept
</message>
<message name="IDS_SETTINGS_BLUETOOTH_CONNECT" desc="Bluetooth pairing dialog: Text for dropdown meny item to connect to a device.">
Connect
</message>
<message name="IDS_SETTINGS_BLUETOOTH_DISCONNECT" desc="Bluetooth pairing dialog: dropdown meny item to disconnect from a device.">
Disconnect
</message>
<message name="IDS_SETTINGS_BLUETOOTH_REJECT_PASSKEY" desc="Bluetooth pairing dialog: Text for button to reject pairing a device.">
Reject
</message>
<message name="IDS_SETTINGS_BLUETOOTH_EXPAND_ACCESSIBILITY_LABEL" desc="Label for the button that toggles showing available Bluetooth devices. Only visible by screen reader software.">
Show available Bluetooth devices
</message>
......
<link rel="import" href="chrome://resources/html/polymer.html">
<link rel="import" href="chrome://resources/cr_elements/cr_scrollable_behavior.html">
<link rel="import" href="chrome://resources/chromeos/bluetooth_dialog.html">
<link rel="import" href="chrome://resources/html/i18n_behavior.html">
<link rel="import" href="chrome://resources/polymer/v1_0/iron-list/iron-list.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-spinner/paper-spinner.html">
......@@ -8,7 +9,6 @@
<link rel="import" href="../i18n_setup.html">
<link rel="import" href="../icons.html">
<link rel="import" href="../settings_shared_css.html">
<link rel="import" href="bluetooth_device_dialog.html">
<link rel="import" href="bluetooth_device_list_item.html">
<dom-module id="settings-bluetooth-subpage">
......@@ -99,14 +99,13 @@
</iron-list>
</div>
<bluetooth-device-dialog id="deviceDialog"
<bluetooth-dialog id="deviceDialog"
bluetooth="[[bluetooth]]"
bluetooth-private="[[bluetoothPrivate]]"
dialog-id="[[dialogId_]]"
error-message="[[errorMessage_]]"
title="$i18n{bluetoothPairDevicePageTitle}"
on-close="onDialogClose_"
on-device-event="onDeviceEvent_"
pairing-device="[[pairingDevice_]]">
</bluetooth-device-dialog>
</bluetooth-dialog>
</template>
<script src="bluetooth_subpage.js"></script>
......
......@@ -8,9 +8,6 @@
* properties and devices.
*/
// NOTE(dbeam): even though this behavior is only used privately, it must
// be globally accessible for Closure's --polymer_pass to compile happily.
Polymer({
is: 'settings-bluetooth-subpage',
......@@ -40,7 +37,7 @@ Polymer({
showSpinner_: {
type: Boolean,
notify: true,
computed: 'computeShowSpinner_(adapterState.*, dialogId_)',
computed: 'computeShowSpinner_(adapterState.*, dialogShown_)',
},
/**
......@@ -97,16 +94,12 @@ Polymer({
},
/**
* Set to the name of the dialog to show. This page uses a single
* dialog to host one of two dialog elements: 'pairDevice' or
* 'connectError'. This allows a seamless transition between dialogs.
* Note: This property should be set before opening the dialog and setting
* the property will not itself cause the dialog to open.
* Whether or not the dialog is shown.
* @private
*/
dialogId_: {
type: String,
value: '',
dialogShown_: {
type: Boolean,
value: false,
},
/**
......@@ -116,12 +109,6 @@ Polymer({
*/
pairingDevice_: Object,
/**
* The translated error message to show when a connect error occurs.
* @private
*/
errorMessage_: String,
/**
* Interface for bluetooth calls. Set in bluetooth-page.
* @type {Bluetooth}
......@@ -200,7 +187,7 @@ Polymer({
/** @private */
computeShowSpinner_: function() {
return !this.dialogId_ && this.get('adapterState.discovering');
return !this.dialogShown_ && this.get('adapterState.discovering');
},
/** @private */
......@@ -268,7 +255,7 @@ Polymer({
*/
onBluetoothDeviceUpdated_: function(device) {
var address = device.address;
if (this.dialogId_ && this.pairingDevice_ &&
if (this.dialogShown_ && this.pairingDevice_ &&
this.pairingDevice_.address == address) {
this.pairingDevice_ = device;
}
......@@ -382,40 +369,22 @@ Polymer({
// If the device is not paired, show the pairing dialog before connecting.
if (!device.paired) {
this.pairingDevice_ = device;
this.openDialog_('pairDevice');
this.openDialog_();
}
this.bluetoothPrivate.connect(device.address, result => {
var error;
if (chrome.runtime.lastError) {
error = chrome.runtime.lastError.message;
} else {
switch (result) {
case chrome.bluetoothPrivate.ConnectResultType.IN_PROGRESS:
return; // Do not close the dialog
case chrome.bluetoothPrivate.ConnectResultType.ALREADY_CONNECTED:
case chrome.bluetoothPrivate.ConnectResultType.AUTH_CANCELED:
case chrome.bluetoothPrivate.ConnectResultType.SUCCESS:
break;
default:
error = result;
}
}
if (!error) {
this.$.deviceDialog.close();
var address = device.address;
this.bluetoothPrivate.connect(address, result => {
// If |pairingDevice_| has changed, ignore the connect result.
if (this.pairingDevice_ && address != this.pairingDevice_.address)
return;
// Let the dialog handle any errors, otherwise close the dialog.
var dialog = this.$.deviceDialog;
if (dialog.handleError(device, chrome.runtime.lastError, result)) {
this.openDialog_();
} else if (
result != chrome.bluetoothPrivate.ConnectResultType.IN_PROGRESS) {
this.$.deviceDialog.close();
}
var name = device.name || device.address;
var id = 'bluetooth_connect_' + error;
if (this.i18nExists(id)) {
this.errorMessage_ = this.i18n(id, name);
} else {
this.errorMessage_ = error;
console.error('Unexpected error connecting to: ' + name + ': ' + error);
}
this.openDialog_('connectError');
});
},
......@@ -448,25 +417,19 @@ Polymer({
});
},
/**
* @param {string} dialogId
* @private
*/
openDialog_: function(dialogId) {
if (this.dialogId_) {
// Dialog already opened, just update the contents.
this.dialogId_ = dialogId;
/** @private */
openDialog_: function() {
if (this.dialogShown_)
return;
}
this.dialogId_ = dialogId;
// Call flush so that the dialog gets sized correctly before it is opened.
Polymer.dom.flush();
this.$.deviceDialog.open();
this.dialogShown_ = true;
},
/** @private */
onDialogClose_: function() {
this.dialogId_ = '';
this.dialogShown_ = false;
this.pairingDevice_ = undefined;
// The list is dynamic so focus the first item.
var device = this.$$('#unpairedContainer bluetooth-device-list-item');
......
......@@ -31,21 +31,6 @@
],
'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
},
{
'target_name': 'bluetooth_device_dialog',
'dependencies': [
'<(DEPTH)/ui/webui/resources/cr_elements/cr_dialog/compiled_resources2.gyp:cr_dialog',
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert',
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior',
'<(DEPTH)/third_party/polymer/v1_0/components-chromium/iron-resizable-behavior/compiled_resources2.gyp:iron-resizable-behavior-extracted',
'<(DEPTH)/third_party/polymer/v1_0/components-chromium/paper-input/compiled_resources2.gyp:paper-input-extracted',
'<(EXTERNS_GYP):bluetooth',
'<(EXTERNS_GYP):bluetooth_private',
'<(INTERFACES_GYP):bluetooth_private_interface',
],
'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
},
{
'target_name': 'bluetooth_device_list_item',
'dependencies': [
......
......@@ -1126,12 +1126,6 @@
<structure name="IDR_SETTINGS_ANDROID_SETTINGS_ELEMENT_JS"
file="android_apps_page/android_settings_element.js"
type="chrome_html" />
<structure name="IDR_SETTINGS_BLUETOOTH_DEVICE_DIALOG_HTML"
file="bluetooth_page/bluetooth_device_dialog.html"
type="chrome_html" />
<structure name="IDR_SETTINGS_BLUETOOTH_DEVICE_DIALOG_JS"
file="bluetooth_page/bluetooth_device_dialog.js"
type="chrome_html" />
<structure name="IDR_SETTINGS_BLUETOOTH_DEVICE_LIST_ITEM_HTML"
file="bluetooth_page/bluetooth_device_list_item.html"
type="chrome_html" />
......
......@@ -29,6 +29,9 @@ _RESOURCES_PATH = os.path.join(_SRC_PATH, 'ui', 'webui', 'resources')
_CR_ELEMENTS_PATH = os.path.join(_RESOURCES_PATH, 'cr_elements')
_CHROMEOS_PATH = os.path.join(_RESOURCES_PATH, 'chromeos')
_CSS_RESOURCES_PATH = os.path.join(_RESOURCES_PATH, 'css')
......@@ -64,6 +67,7 @@ _VULCANIZE_BASE_ARGS = [
_URL_MAPPINGS = [
('chrome://resources/chromeos/', _CHROMEOS_PATH),
('chrome://resources/cr_elements/', _CR_ELEMENTS_PATH),
('chrome://resources/css/', _CSS_RESOURCES_PATH),
('chrome://resources/html/', _HTML_RESOURCES_PATH),
......
......@@ -368,15 +368,14 @@ void AddAppearanceStrings(content::WebUIDataSource* html_source,
#if defined(OS_CHROMEOS)
void AddBluetoothStrings(content::WebUIDataSource* html_source) {
LocalizedString localized_strings[] = {
{"bluetoothAccept", IDS_OPTIONS_SETTINGS_BLUETOOTH_ACCEPT_PASSKEY},
{"bluetoothAccept", IDS_SETTINGS_BLUETOOTH_ACCEPT_PASSKEY},
{"bluetoothConnected", IDS_SETTINGS_BLUETOOTH_CONNECTED},
{"bluetoothConnecting", IDS_SETTINGS_BLUETOOTH_CONNECTING},
{"bluetoothDeviceListPaired", IDS_SETTINGS_BLUETOOTH_DEVICE_LIST_PAIRED},
{"bluetoothDeviceListUnpaired",
IDS_SETTINGS_BLUETOOTH_DEVICE_LIST_UNPAIRED},
{"bluetoothConnect", IDS_OPTIONS_SETTINGS_BLUETOOTH_CONNECT},
{"bluetoothDisconnect", IDS_OPTIONS_SETTINGS_BLUETOOTH_DISCONNECT},
{"bluetoothDismiss", IDS_OPTIONS_SETTINGS_BLUETOOTH_DISMISS_ERROR},
{"bluetoothConnect", IDS_SETTINGS_BLUETOOTH_CONNECT},
{"bluetoothDisconnect", IDS_SETTINGS_BLUETOOTH_DISCONNECT},
{"bluetoothToggleA11yLabel",
IDS_SETTINGS_BLUETOOTH_TOGGLE_ACCESSIBILITY_LABEL},
{"bluetoothExpandA11yLabel",
......@@ -388,11 +387,11 @@ void AddBluetoothStrings(content::WebUIDataSource* html_source) {
{"bluetoothPair", IDS_SETTINGS_BLUETOOTH_PAIR},
{"bluetoothPairDevicePageTitle",
IDS_SETTINGS_BLUETOOTH_PAIR_DEVICE_TITLE},
{"bluetoothReject", IDS_OPTIONS_SETTINGS_BLUETOOTH_REJECT_PASSKEY},
{"bluetoothReject", IDS_SETTINGS_BLUETOOTH_REJECT_PASSKEY},
{"bluetoothRemove", IDS_SETTINGS_BLUETOOTH_REMOVE},
// Device connecting and pairing.
{"bluetoothStartConnecting", IDS_SETTINGS_BLUETOOTH_START_CONNECTING},
{"bluetoothEnterKey", IDS_OPTIONS_SETTINGS_BLUETOOTH_ENTER_KEY},
{"bluetoothEnterKey", IDS_SETTINGS_BLUETOOTH_ENTER_KEY},
// These ids are generated in JS using 'bluetooth_' + a value from
// bluetoothPrivate.PairingEventType (see bluetooth_private.idl).
// 'keysEntered', and 'requestAuthorization' have no associated message.
......
......@@ -37,7 +37,11 @@ const char* const kPathAliases[][2] = {
"polymer/v1_0/web-animations-js/"},
{"../../views/resources/default_100_percent/common/", "images/apps/"},
{"../../views/resources/default_200_percent/common/", "images/2x/apps/"},
{"../../webui/resources/cr_elements/", "cr_elements/"}};
#if defined(OS_CHROMEOS)
{"../../webui/resources/chromeos/", "chromeos/"},
#endif
{"../../webui/resources/cr_elements/", "cr_elements/"},
};
const struct {
const char* const path;
......
......@@ -40,6 +40,7 @@
'<(DEPTH)/chrome/browser/resources/uber/compiled_resources2.gyp:*',
'<(DEPTH)/chrome/browser/resources/webapks/compiled_resources2.gyp:*',
'<(DEPTH)/ui/file_manager/compiled_resources2.gyp:*',
'<(DEPTH)/ui/webui/resources/chromeos/compiled_resources2.gyp:*',
'<(DEPTH)/ui/webui/resources/cr_elements/compiled_resources2.gyp:*',
'<(DEPTH)/ui/webui/resources/js/chromeos/compiled_resources2.gyp:*',
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:*',
......
......@@ -28,9 +28,11 @@ def _CheckForTranslations(input_api, output_api):
for f in input_api.AffectedFiles():
local_path = f.LocalPath()
# Allow translation in i18n_behavior.js and the chromeos/ directory.
if local_path.endswith('i18n_behavior.js'):
continue
if 'chromeos' in local_path:
continue
keywords = None
if local_path.endswith('.js'):
keywords = js_keywords
......
This directory contains shared chromeos elements for Web UI
(e.g. between Settings and a stand alone dialog).
These components are allowed to use I18nBehavior. The Web UI hosting
these elements is expected to provide loadTimeData with the necessary
strings. TODO(stevenjb/dschuyler): Add support for i18n{} substitution.
<link rel="import" href="chrome://resources/html/polymer.html">
<link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html">
<link rel="import" href="chrome://resources/cr_elements/hidden_style_css.html">
<link rel="import" href="chrome://resources/html/cr.html">
<link rel="import" href="chrome://resources/html/i18n_behavior.html">
<link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout-classes.html">
<link rel="import" href="chrome://resources/polymer/v1_0/iron-list/iron-list.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-input/paper-input.html">
<link rel="import" href="../bluetooth_page/bluetooth_device_list_item.html">
<link rel="import" href="../settings_shared_css.html">
<dom-module id="bluetooth-device-dialog">
<dom-module id="bluetooth-dialog">
<template>
<style include="settings-shared iron-flex">
<style include="cr-hidden-style iron-flex">
#pairing {
margin-bottom: 10px;
}
......@@ -68,73 +68,70 @@
margin: 0 20px;
}
</style>
<!-- TODO(stevenjb/dschuyler): Find a solution to support i18n{} here -->
<dialog is="cr-dialog" id="dialog" on-cancel="onDialogCanceled_"
close-text="$i18n{close}" on-closed="onDialogCanceled_">
<div slot="title">$i18n{bluetoothPairDevicePageTitle}</div>
close-text="[[i18n('close')]]" on-closed="onDialogCanceled_">
<div slot="title">[[title]]</div>
<div slot="body">
<div class="contents layout vertical center center-justified">
<template is="dom-if" if="[[isDialogType_(dialogId, 'pairDevice')]]">
<div id="pairing" class="settings-box first layout vertical center
center-justified">
<template is="dom-if" if="[[!errorMessage_]]">
<div id="pairing" class="layout vertical center center-justified">
<div class="dialog-message">
[[getMessage_(pairingDevice, pairingEvent_)]]
</div>
<div hidden$="[[!showEnterPincode_(pairingEvent_)]]">
<paper-input id="pincode" minlength="1" maxlength="16"
type="text" auto-validate value="{{pinOrPass}}">
type="text" auto-validate value="{{pinOrPass_}}">
</paper-input>
</div>
<div hidden$="[[!showEnterPasskey_(pairingEvent_)]]">
<paper-input id="passkey" minlength="6" maxlength="6"
type="text" auto-validate value="{{pinOrPass}}">
type="text" auto-validate value="{{pinOrPass_}}">
</paper-input>
</div>
<div id="pinDiv" class="layout horizontal center center-justified"
hidden="[[!showDisplayPassOrPin_(pairingEvent_)]]">
<template is="dom-repeat" items="[[digits]]">
<template is="dom-repeat" items="[[digits_]]">
<span class$="[[getPinClass_(index, pairingEvent_)]]">
[[getPinDigit_(index, pairingEvent_)]]
</span>
</template>
<span class$="[[getPinClass_(-1, pairingEvent_)]]"
hidden="[[showAcceptReject_(pairingEvent_)]]">
$i18n{bluetoothEnterKey}
[[i18n('bluetoothEnterKey')]]
</span>
</div>
</div>
</template>
<template is="dom-if"
if="[[isDialogType_('connectError', dialogId)]]">
<div class="settings-box first layout vertical center
center-justified">
<div class="dialog-message">[[errorMessage]]</div>
<template is="dom-if" if="[[errorMessage_]]">
<div class="layout vertical center center-justified">
<div class="dialog-message">[[errorMessage_]]</div>
</div>
</template>
</div>
</div>
<div slot="button-container">
<template is="dom-if" if="[[isDialogType_('pairDevice', dialogId)]]">
<template is="dom-if" if="[[!errorMessage_]]">
<paper-button hidden$="[[!showAcceptReject_(pairingEvent_)]]"
on-tap="onAcceptTap_">$i18n{bluetoothAccept}</paper-button>
on-tap="onAcceptTap_">[[i18n('bluetoothAccept')]]</paper-button>
<paper-button hidden$="[[!showAcceptReject_(pairingEvent_)]]"
on-tap="onRejectTap_">$i18n{bluetoothReject}</paper-button>
on-tap="onRejectTap_">[[i18n('bluetoothReject')]]</paper-button>
<paper-button hidden$="[[!showConnect_(pairingEvent_)]]"
disabled="[[!enableConnect_(pairingEvent_, pinOrPass)]]"
on-tap="onConnectTap_">$i18n{bluetoothPair}</paper-button>
disabled="[[!enableConnect_(pairingEvent_, pinOrPass_)]]"
on-tap="onConnectTap_">[[i18n('bluetoothPair')]]</paper-button>
<paper-button
hidden$="[[!showDismiss_(pairingDevice, pairingEvent_)]]"
on-tap="close">$i18n{bluetoothDismiss}</paper-button>
on-tap="close">[[i18n('ok')]]</paper-button>
<paper-button hidden$="[[showDismiss_(pairingDevice, pairingEvent_)]]"
on-tap="onCancelTap_">
$i18n{cancel}
[[i18n('cancel')]]
</paper-button>
</template>
<template is="dom-if" if="[[isDialogType_('connectError', dialogId)]]">
<paper-button on-tap="close">$i18n{bluetoothDismiss}
</paper-button>
<template is="dom-if" if="[[errorMessage_]]">
<paper-button on-tap="close">[[i18n('ok')]]</paper-button>
</template>
</div>
</dialog>
</template>
<script src="bluetooth_device_dialog.js"></script>
<script src="bluetooth_dialog.js"></script>
</dom-module>
......@@ -2,16 +2,43 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
cr.exportPath('settings');
/**
* @fileoverview
* Dialog used for pairing a provided |pairing-device|. Set |show-error| to
* show the error results from a pairing event instead of the pairing UI.
* NOTE: This module depends on I18nBehavior which depends on loadTimeData.
*/
var PairingEventType = chrome.bluetoothPrivate.PairingEventType;
// NOTE(dbeam): even though this behavior is only used privately, it must
// be globally accessible for Closure's --polymer_pass to compile happily.
Polymer({
is: 'bluetooth-dialog',
behaviors: [I18nBehavior],
/** @polymerBehavior */
settings.BluetoothPairDeviceBehavior = {
properties: {
/**
* Interface for bluetooth calls. Set in bluetooth-page.
* @type {Bluetooth}
* @private
*/
bluetooth: {
type: Object,
value: chrome.bluetooth,
},
/**
* Interface for bluetoothPrivate calls.
* @type {BluetoothPrivate}
*/
bluetoothPrivate: {
type: Object,
value: chrome.bluetoothPrivate,
},
/** Dialog title */
title: String,
/**
* Current Pairing device.
* @type {!chrome.bluetooth.Device|undefined}
......@@ -20,31 +47,31 @@ settings.BluetoothPairDeviceBehavior = {
/**
* Current Pairing event.
* @type {?chrome.bluetoothPrivate.PairingEvent}
* @private {?chrome.bluetoothPrivate.PairingEvent}
*/
pairingEvent_: {
type: Object,
value: null,
},
/** Pincode or passkey value, used to trigger connect enabled changes. */
pinOrPass: String,
/**
* May be set by the host to show a pairing error result, or may be
* set by the dialog if a pairing or connect error occured.
* @private
*/
errorMessage_: String,
/**
* Interface for bluetoothPrivate calls. Set in bluetooth-page.
* @type {BluetoothPrivate}
* Pincode or passkey value, used to trigger connect enabled changes.
* @private
*/
bluetoothPrivate: {
type: Object,
value: chrome.bluetoothPrivate,
},
pinOrPass_: String,
/**
* @const
* @type {!Array<number>}
* @const {!Array<number>}
* @private
*/
digits: {
digits_: {
type: Array,
readOnly: true,
value: [0, 1, 2, 3, 4, 5],
......@@ -52,16 +79,100 @@ settings.BluetoothPairDeviceBehavior = {
},
observers: [
'dialogUpdated_(errorMessage_, pairingEvent_)',
'pairingChanged_(pairingDevice, pairingEvent_)',
],
/**
* Listener for chrome.bluetoothPrivate.onPairing events.
* @type {?function(!chrome.bluetoothPrivate.PairingEvent)}
* @private
* @private {?function(!chrome.bluetoothPrivate.PairingEvent)}
*/
bluetoothPrivateOnPairingListener_: null,
/**
* Listener for chrome.bluetooth.onBluetoothDeviceChanged events.
* @private {?function(!chrome.bluetooth.Device)}
*/
bluetoothDeviceChangedListener_: null,
open: function() {
this.startPairing();
this.pinOrPass_ = '';
this.getDialog_().showModal();
this.itemWasFocused_ = false;
},
close: function() {
this.endPairing();
var dialog = this.getDialog_();
if (dialog.open)
dialog.close();
},
/**
* Updates the dialog after a connect attempt.
* @param {!chrome.bluetooth.Device} device The device connected to
* @param {!{message: string}} lastError chrome.runtime.lastError
* @param {chrome.bluetoothPrivate.ConnectResultType} result The connect
* result
* @return {boolean}
*/
handleError: function(device, lastError, result) {
var error;
if (lastError) {
error = lastError.message;
} else {
switch (result) {
case chrome.bluetoothPrivate.ConnectResultType.IN_PROGRESS:
case chrome.bluetoothPrivate.ConnectResultType.ALREADY_CONNECTED:
case chrome.bluetoothPrivate.ConnectResultType.AUTH_CANCELED:
case chrome.bluetoothPrivate.ConnectResultType.SUCCESS:
this.errorMessage_ = '';
return false;
default:
error = result;
}
}
var name = device.name || device.address;
var id = 'bluetooth_connect_' + error;
if (this.i18nExists(id)) {
this.errorMessage_ = this.i18n(id, name);
} else {
this.errorMessage_ = error;
console.error('Unexpected error connecting to: ' + name + ': ' + error);
}
return true;
},
/** @private */
dialogUpdated_: function() {
if (this.showEnterPincode_())
this.$$('#pincode').focus();
else if (this.showEnterPasskey_())
this.$$('#passkey').focus();
},
/**
* @return {!CrDialogElement}
* @private
*/
getDialog_: function() {
return /** @type {!CrDialogElement} */ (this.$.dialog);
},
/** @private */
onCancelTap_: function() {
this.getDialog_().cancel();
},
/** @private */
onDialogCanceled_: function() {
if (!this.errorMessage_)
this.sendResponse_(chrome.bluetoothPrivate.PairingResponse.CANCEL);
this.endPairing();
},
/** Called when the dialog is opened. Starts listening for pairing events. */
startPairing: function() {
if (!this.bluetoothPrivateOnPairingListener_) {
......@@ -70,6 +181,12 @@ settings.BluetoothPairDeviceBehavior = {
this.bluetoothPrivate.onPairing.addListener(
this.bluetoothPrivateOnPairingListener_);
}
if (!this.bluetoothDeviceChangedListener_) {
this.bluetoothDeviceChangedListener_ =
this.onBluetoothDeviceChanged_.bind(this);
this.bluetooth.onDeviceChanged.addListener(
this.bluetoothDeviceChangedListener_);
}
},
/** Called when the dialog is closed. */
......@@ -79,6 +196,11 @@ settings.BluetoothPairDeviceBehavior = {
this.bluetoothPrivateOnPairingListener_);
this.bluetoothPrivateOnPairingListener_ = null;
}
if (this.bluetoothDeviceChangedListener_) {
this.bluetooth.onDeviceChanged.removeListener(
this.bluetoothDeviceChangedListener_);
this.bluetoothDeviceChangedListener_ = null;
}
this.pairingEvent_ = null;
},
......@@ -101,6 +223,18 @@ settings.BluetoothPairDeviceBehavior = {
this.pairingEvent_ = event;
},
/**
* Process bluetooth.onDeviceChanged events. This ensures that the dialog
* updates when the connection state changes.
* @param {!chrome.bluetooth.Device} device
* @private
*/
onBluetoothDeviceChanged_: function(device) {
if (!this.pairingDevice || device.address != this.pairingDevice.address)
return;
this.pairingDevice = device;
},
/** @private */
pairingChanged_: function() {
// Auto-close the dialog when pairing completes.
......@@ -109,7 +243,8 @@ settings.BluetoothPairDeviceBehavior = {
this.close();
return;
}
this.pinOrPass = '';
this.errorMessage_ = '';
this.pinOrPass_ = '';
},
/**
......@@ -313,7 +448,7 @@ settings.BluetoothPairDeviceBehavior = {
this.pairingEvent_.pairing == PairingEventType.KEYS_ENTERED &&
this.pairingEvent_.enteredKey) {
var enteredKey = this.pairingEvent_.enteredKey; // 1-7
var lastKey = this.digits.length; // 6
var lastKey = this.digits_.length; // 6
if ((index == -1 && enteredKey > lastKey) || (index + 1 == enteredKey))
cssClass += ' next';
else if (index > enteredKey)
......@@ -321,73 +456,4 @@ settings.BluetoothPairDeviceBehavior = {
}
return cssClass;
},
};
Polymer({
is: 'bluetooth-device-dialog',
behaviors: [I18nBehavior, settings.BluetoothPairDeviceBehavior],
properties: {
/**
* The version of this dialog to show: 'pairDevice', or 'connectError'.
* Must be set before the dialog is opened.
*/
dialogId: String,
},
observers: [
'dialogUpdated_(dialogId, pairingEvent_)',
],
open: function() {
this.startPairing();
this.pinOrPass = '';
this.getDialog_().showModal();
this.itemWasFocused_ = false;
},
close: function() {
this.endPairing();
var dialog = this.getDialog_();
if (dialog.open)
dialog.close();
},
/** @private */
dialogUpdated_: function() {
if (this.showEnterPincode_())
this.$$('#pincode').focus();
else if (this.showEnterPasskey_())
this.$$('#passkey').focus();
},
/**
* @return {!CrDialogElement}
* @private
*/
getDialog_: function() {
return /** @type {!CrDialogElement} */ (this.$.dialog);
},
/**
* @param {string} desiredDialogType
* @return {boolean}
* @private
*/
isDialogType_: function(desiredDialogType, currentDialogType) {
return currentDialogType == desiredDialogType;
},
/** @private */
onCancelTap_: function() {
this.getDialog_().cancel();
},
/** @private */
onDialogCanceled_: function() {
if (this.dialogId == 'pairDevice')
this.sendResponse_(chrome.bluetoothPrivate.PairingResponse.CANCEL);
this.endPairing();
},
});
# Copyright 2017 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
{
'targets': [
{
'target_name': 'bluetooth_dialog',
'dependencies': [
'<(DEPTH)/ui/webui/resources/cr_elements/cr_dialog/compiled_resources2.gyp:cr_dialog',
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert',
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
'<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior',
'<(DEPTH)/third_party/polymer/v1_0/components-chromium/iron-resizable-behavior/compiled_resources2.gyp:iron-resizable-behavior-extracted',
'<(DEPTH)/third_party/polymer/v1_0/components-chromium/paper-input/compiled_resources2.gyp:paper-input-extracted',
'<(EXTERNS_GYP):bluetooth',
'<(EXTERNS_GYP):bluetooth_private',
'<(INTERFACES_GYP):bluetooth_interface',
'<(INTERFACES_GYP):bluetooth_private_interface',
],
'includes': ['../../../../third_party/closure_compiler/compile_js2.gypi'],
},
],
}
<?xml version="1.0" encoding="utf-8"?>
<grit-part>
<!-- Chrome OS Custom Elements -->
<structure name="IDR_WEBUI_CHROMEOS_BLUETOOTH_DIALOG_HTML"
file="chromeos/bluetooth_dialog.html"
type="chrome_html" />
<structure name="IDR_WEBUI_CHROMEOS_BLUETOOTH_DIALOG_JS"
file="chromeos/bluetooth_dialog.js"
type="chrome_html" />
</grit-part>
......@@ -511,6 +511,9 @@ without changes to the corresponding grd file. -->
<part file="cr_elements_resources.grdp" />
<part file="polymer_resources.grdp" />
</if>
<if expr="chromeos">
<part file="chromeos_elements_resources.grdp" />
</if>
</structures>
</release>
</grit>
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment