Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(152)

Side by Side Diff: chrome/browser/resources/options2/chromeos/bluetooth_list_element.js

Issue 8930012: Revert 114236 - Options2: Pull the trigger. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 9 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 cr.define('options.system.bluetooth', function() {
6 /**
7 * Bluetooth settings constants.
8 */
9 function Constants() {}
10
11 /**
12 * Enumeration of supported device types. Each device type has an
13 * associated icon and CSS style.
14 * @enum {string}
15 */
16 Constants.DEVICE_TYPE = {
17 COMPUTER: 'computer',
18 HEADSET: 'headset',
19 KEYBOARD: 'input-keyboard',
20 MOUSE: 'input-mouse',
21 PHONE: 'phone',
22 };
23
24 /**
25 * Enumeration of possible states for a bluetooth device. The value
26 * associated with each state maps to a localized string in the global
27 * variable 'templateData'.
28 * @enum {string}
29 */
30 Constants.DEVICE_STATUS = {
31 CONNECTED: 'bluetoothDeviceConnected',
32 CONNECTING: 'bluetoothDeviceConnecting',
33 FAILED_PAIRING: 'bluetoothDeviceFailedPairing',
34 NOT_PAIRED: 'bluetoothDeviceNotPaired',
35 PAIRED: 'bluetoothDevicePaired'
36 };
37
38 /**
39 * Enumeration of possible states during pairing. The value associated
40 * with each state maps to a loalized string in the global variable
41 * 'tempateData'.
42 * @enum {string}
43 */
44 Constants.PAIRING = {
45 CONFIRM_PASSKEY: 'bluetoothConfirmPasskey',
46 ENTER_PASSKEY: 'bluetoothEnterPasskey',
47 FAILED_CONNECT_INSTRUCTIONS: 'bluetoothFailedPairingInstructions',
48 REMOTE_PASSKEY: 'bluetoothRemotePasskey'
49 };
50
51 /**
52 * Creates an element for storing a list of bluetooth devices.
53 * @param {Object=} opt_propertyBag Optional properties.
54 * @constructor
55 * @extends {HTMLDivElement}
56 */
57 var BluetoothListElement = cr.ui.define('div');
58
59 BluetoothListElement.prototype = {
60 __proto__: HTMLDivElement.prototype,
61
62 /** @inheritDoc */
63 decorate: function() {
64 },
65
66 /**
67 * Loads given list of bluetooth devices. This list will comprise of
68 * devices that are currently connected. New devices are discovered
69 * via the 'Find devices' button.
70 * @param {Array} devices An array of bluetooth devices.
71 */
72 load: function(devices) {
73 this.textContent = '';
74 for (var i = 0; i < devices.length; i++) {
75 if (this.isSupported_(devices[i]))
76 this.appendChild(new BluetoothItem(devices[i]));
77 }
78 },
79
80 /**
81 * Adds a bluetooth device to the list of available devices. A check is
82 * made to see if the device is already in the list, in which case the
83 * existing device is updated.
84 * @param {Object.<string,string>} device Description of the bluetooth
85 * device.
86 * @return {boolean} True if the devies was successfully added or updated.
87 */
88 appendDevice: function(device) {
89 if (!this.isSupported_(device))
90 return false;
91 var item = new BluetoothItem(device);
92 var existing = this.findDevice(device.address);
93 if (existing)
94 this.replaceChild(item, existing);
95 else
96 this.appendChild(item);
97 return true;
98 },
99
100 /**
101 * Scans the list of elements corresponding to discovered Bluetooth
102 * devices for one with a matching address.
103 * @param {string} address The address of the device.
104 * @return {Element|undefined} Element corresponding to the device address
105 * or undefined if no corresponding element is found.
106 */
107 findDevice: function(address) {
108 var candidate = this.firstChild;
109 while (candidate) {
110 if (candidate.data.address == address)
111 return candidate;
112 candidate = candidate.nextSibling;
113 }
114 },
115
116 /**
117 * Tests if the bluetooth device is supported based on the type of device.
118 * @param {Object.<string,string>} device Desription of the device.
119 * @return {boolean} true if the device is supported.
120 * @private
121 */
122 isSupported_: function(device) {
123 var target = device.icon;
124 for (var key in Constants.DEVICE_TYPE) {
125 if (Constants.DEVICE_TYPE[key] == target)
126 return true;
127 }
128 return false;
129 }
130 };
131
132 /**
133 * Creates an element in the list of bluetooth devices.
134 * @param {{name: string,
135 * address: string,
136 * icon: Constants.DEVICE_TYPE,
137 * paired: boolean,
138 * connected: boolean,
139 * pairing: string|undefined,
140 * passkey: number|undefined,
141 * entered: number|undefined}} device
142 * Decription of the bluetooth device.
143 * @constructor
144 */
145 function BluetoothItem(device) {
146 var el = $('bluetooth-item-template').cloneNode(true);
147 el.__proto__ = BluetoothItem.prototype;
148 el.removeAttribute('id');
149 el.hidden = false;
150 el.data = {};
151 for (var key in device)
152 el.data[key] = device[key];
153 el.decorate();
154 return el;
155 }
156
157 BluetoothItem.prototype = {
158 __proto__: HTMLDivElement.prototype,
159
160 /** @inheritDoc */
161 decorate: function() {
162 this.className = 'bluetooth-item';
163 this.connected = this.data.connected;
164 // Though strictly speaking, a connected device will also be paired,
165 // we are interested in tracking paired devices that are not connected.
166 this.paired = this.data.paired && !this.data.connected;
167 this.connecting = !!this.data.pairing;
168 this.addLabels_();
169 this.addButtons_();
170 },
171
172 /**
173 * Retrieves the descendent element with the matching class name.
174 * @param {string} className The class name for the target element.
175 * @return {Element|undefined} Returns the matching element if
176 * found and unique.
177 * @private
178 */
179 getNodeByClass_:function(className) {
180 var elements = this.getElementsByClassName(className);
181 if (elements && elements.length == 1)
182 return elements[0];
183 },
184
185 /**
186 * Sets the text content for an element.
187 * @param {string} className The class name of the target element.
188 * @param {string} label Text content for the element.
189 * @private
190 */
191 setLabel_: function(className, label) {
192 var el = this.getNodeByClass_(className);
193 el.textContent = label;
194 },
195
196 /**
197 * Adds an element containing the display name, status and device pairing
198 * instructions.
199 * @private
200 */
201 addLabels_: function() {
202 this.setLabel_('network-name-label', this.data.name);
203 var status;
204 if (this.data.connected)
205 status = Constants.DEVICE_STATUS.CONNECTED;
206 else if (this.data.pairing)
207 status = Constants.DEVICE_STATUS.CONNECTING;
208 if (status) {
209 var statusMessage = templateData[status];
210 if (statusMessage)
211 this.setLabel_('network-status-label', statusMessage);
212 if (this.connecting) {
213 var spinner = this.getNodeByClass_('inline-spinner');
214 spinner.hidden = false;
215 }
216 }
217 if (this.data.pairing)
218 this.addPairingInstructions_();
219 },
220
221 /**
222 * Adds instructions on how to complete the pairing process.
223 * @param {!Element} textDiv Target element for inserting the instructions.
224 * @private
225 */
226 addPairingInstructions_: function() {
227 var instructionsEl = this.getNodeByClass_('bluetooth-instructions');
228 var message = templateData[this.data.pairing];
229 var array = this.formatInstructions_(message);
230 for (var i = 0; i < array.length; i++) {
231 instructionsEl.appendChild(array[i]);
232 }
233 if (this.data.pairing == Constants.PAIRING.ENTER_PASSKEY) {
234 var input = this.ownerDocument.createElement('input');
235 input.type = 'text';
236 input.className = 'bluetooth-passkey-field';
237 instructionsEl.appendChild(input);
238 }
239 },
240
241 /**
242 * Formats the pairing instruction, which may contain labels for
243 * substitution. The label '%1' is replaced with the passkey, and '%2'
244 * is replaced with the name of the bluetooth device. Formatting of the
245 * passkey depends on the type of validation.
246 * @param {string} instructions The source instructions to format.
247 * @return {Array.<Element>} Array of formatted elements.
248 */
249 formatInstructions_: function(instructions) {
250 var array = [];
251 var index = instructions.indexOf('%');
252 if (index >= 0) {
253 array.push(this.createTextElement_(instructions.substring(0, index)));
254 var labelPlaceholder = instructions.charAt(index + 1);
255 // ... handle the placeholder
256 switch (labelPlaceholder) {
257 case '1':
258 array.push(this.createPasskeyElement_());
259 break;
260 case '2':
261 array.push(this.createTextElement_(this.data.name));
262 }
263 array = array.concat(this.formatInstructions_(instructions.substring(
264 index + 2)));
265 } else {
266 array.push(this.createTextElement_(instructions));
267 }
268 return array;
269 },
270
271 /**
272 * Formats an element for displaying the passkey.
273 * @return {Element} Element containing the passkey.
274 */
275 createPasskeyElement_: function() {
276 var passkeyEl = document.createElement('div');
277 if (this.data.pairing == Constants.PAIRING.REMOTE_PASSKEY) {
278 passkeyEl.className = 'bluetooth-remote-passkey';
279 var key = String(this.data.passkey);
280 var progress = this.data.entered;
281 for (var i = 0; i < key.length; i++) {
282 var keyEl = document.createElement('div');
283 keyEl.textContent = key.charAt(i);
284 keyEl.className = 'bluetooth-passkey-char';
285 if (i < progress)
286 keyEl.classList.add('key-typed');
287 passkeyEl.appendChild(keyEl);
288 }
289 // Add return key symbol.
290 var keyEl = document.createElement('div');
291 keyEl.className = 'bluetooth-passkey-char';
292 keyEl.textContent = '\u23ce';
293 passkeyEl.appendChild(keyEl);
294 } else {
295 passkeyEl.className = 'bluetooth-confirm-passkey';
296 passkeyEl.textContent = this.data.passkey;
297 }
298 return passkeyEl;
299 },
300
301 /**
302 * Adds a text element.
303 * @param {string} text The text content of the new element.
304 * @param {string=} opt_style Optional parameter for the CSS class for
305 * formatting the text element.
306 * @return {Element} Element containing the text.
307 */
308 createTextElement_: function(text, array, opt_style) {
309 var el = this.ownerDocument.createElement('span');
310 el.textContent = text;
311 if (opt_style)
312 el.className = opt_style;
313 return el;
314 },
315
316 /**
317 * Adds buttons for updating the connectivity of a device.
318 * @private.
319 */
320 addButtons_: function() {
321 var buttonsDiv = this.getNodeByClass_('bluetooth-button-group');
322 var buttonLabelKey = null;
323 var callbackType = null;
324 if (this.connected) {
325 buttonLabelKey = 'bluetoothDisconnectDevice';
326 callbackType = 'disconnect';
327 } else if (this.paired) {
328 buttonLabelKey = 'bluetoothForgetDevice';
329 callbackType = 'forget';
330 } else if (this.connecting) {
331 if (this.data.pairing == Constants.PAIRING.CONFIRM_PASSKEY) {
332 buttonLabelKey = 'bluetoothRejectPasskey';
333 callbackType = 'reject';
334 } else {
335 buttonLabelKey = 'bluetoothCancel';
336 callbackType = 'cancel';
337 }
338 } else {
339 buttonLabelKey = 'bluetoothConnectDevice';
340 callbackType = 'connect';
341 }
342 if (buttonLabelKey && callbackType) {
343 var buttonEl = this.ownerDocument.createElement('button');
344 buttonEl.textContent = localStrings.getString(buttonLabelKey);
345 var self = this;
346 var callback = function(e) {
347 chrome.send('updateBluetoothDevice',
348 [self.data.address, callbackType]);
349 }
350 buttonEl.addEventListener('click', callback);
351 buttonsDiv.appendChild(buttonEl);
352 }
353 if (this.data.pairing == Constants.PAIRING.CONFIRM_PASSKEY ||
354 this.data.pairing == Constants.PAIRING.ENTER_PASSKEY) {
355 var buttonEl = this.ownerDocument.createElement('button');
356 buttonEl.className = 'accept-pairing-button';
357 var msg = this.data.pairing == Constants.PAIRING.CONFIRM_PASSKEY ?
358 'bluetoothAcceptPasskey' : 'bluetoothConnectDevice';
359 buttonEl.textContent = localStrings.getString(msg);
360 var self = this;
361 var callback = function(e) {
362 var passkey = self.data.passkey;
363 if (self.data.pairing == Constants.PAIRING.ENTER_PASSKEY) {
364 var passkeyField = self.getNodeByClass_('bluetooth-passkey-field');
365 passkey = passkeyField.value;
366 }
367 chrome.send('updateBluetoothDevice',
368 [self.data.address, 'connect', String(passkey)]);
369 }
370 buttonEl.addEventListener('click', callback);
371 buttonsDiv.insertBefore(buttonEl, buttonsDiv.firstChild);
372 }
373 this.appendChild(buttonsDiv);
374 }
375 };
376
377 cr.defineProperty(BluetoothItem, 'connected', cr.PropertyKind.BOOL_ATTR);
378
379 cr.defineProperty(BluetoothItem, 'paired', cr.PropertyKind.BOOL_ATTR);
380
381 cr.defineProperty(BluetoothItem, 'connecting', cr.PropertyKind.BOOL_ATTR);
382
383 return {
384 Constants: Constants,
385 BluetoothListElement: BluetoothListElement
386 };
387 });
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698