OLD | NEW |
| (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 | |
6 // Network status constants. | |
7 const StatusConnected = 'connected'; | |
8 const StatusDisconnected = 'disconnected'; | |
9 const StatusConnecting = 'connecting'; | |
10 const StatusError = 'error'; | |
11 | |
12 const NetworkOther = 'other'; | |
13 | |
14 // Setup css canvas 'spinner-circle' | |
15 (function() { | |
16 var lineWidth = 3; | |
17 var r = 8; | |
18 var ctx = document.getCSSCanvasContext('2d', 'spinner-circle', 2 * r, 2 * r); | |
19 | |
20 ctx.lineWidth = lineWidth; | |
21 ctx.lineCap = 'round'; | |
22 ctx.lineJoin = 'round'; | |
23 | |
24 ctx.strokeStyle = '#4e73c7'; | |
25 ctx.beginPath(); | |
26 ctx.moveTo(lineWidth / 2, r - lineWidth / 2); | |
27 ctx.arc(r, r, r - lineWidth / 2, Math.PI, Math.PI * 3 / 2); | |
28 ctx.stroke(); | |
29 })(); | |
30 | |
31 /** | |
32 * Sends "connect" using the 'action' WebUI message. | |
33 */ | |
34 function sendConnect(index, passphrase, identity, auto_connect) { | |
35 chrome.send('action', | |
36 ['connect', | |
37 String(index), | |
38 passphrase, | |
39 identity, | |
40 auto_connect ? '1' : '0']); | |
41 } | |
42 | |
43 var networkMenuItemProto = (function() { | |
44 var networkMenuItem = cr.doc.createElement('div'); | |
45 networkMenuItem.innerHTML = '<div class="network-menu-item">' + | |
46 '<div class="network-label-icon">' + | |
47 '<div class="network-label"></div>' + | |
48 '<div class="network-icon hidden"></div>' + | |
49 '</div>' + | |
50 '<div class="network-status hidden"></div>' + | |
51 '<div class="hidden"></div>' + | |
52 '</div>'; | |
53 return networkMenuItem; | |
54 })(); | |
55 | |
56 var NetworkMenuItem = cr.ui.define(function() { | |
57 return networkMenuItemProto.cloneNode(true); | |
58 }); | |
59 | |
60 NetworkMenuItem.prototype = { | |
61 __proto__: MenuItem.prototype, | |
62 | |
63 ssidEdit: null, | |
64 passwordEdit: null, | |
65 autoConnectCheckbox: null, | |
66 | |
67 /** | |
68 * The label element. | |
69 * @private | |
70 */ | |
71 get label_() { | |
72 return this.firstElementChild.firstElementChild.firstElementChild; | |
73 }, | |
74 | |
75 /** | |
76 * The icon element. | |
77 * @private | |
78 */ | |
79 get icon_() { | |
80 return this.label_.nextElementSibling; | |
81 }, | |
82 | |
83 /** | |
84 * The status area element. | |
85 * @private | |
86 */ | |
87 get status_() { | |
88 return this.firstElementChild.firstElementChild.nextElementSibling; | |
89 }, | |
90 | |
91 /** | |
92 * The action area container element. | |
93 * @private | |
94 */ | |
95 get action_() { | |
96 return this.status_.nextElementSibling; | |
97 }, | |
98 | |
99 /** | |
100 * Set status message. | |
101 * @param {string} message The message to display in status area. | |
102 * @private | |
103 */ | |
104 setStatus_: function(message) { | |
105 if (message) { | |
106 this.status_.textContent = message; | |
107 this.status_.classList.remove('hidden'); | |
108 } else { | |
109 this.status_.classList.add('hidden'); | |
110 } | |
111 }, | |
112 | |
113 /** | |
114 * Set status icon. | |
115 * @param {string} icon Source url for the icon image. | |
116 * @private | |
117 */ | |
118 setIcon_: function(icon) { | |
119 if (icon) { | |
120 this.icon_.style.backgroundImage = 'url(' + icon + ')'; | |
121 this.icon_.classList.remove('hidden'); | |
122 } else { | |
123 this.icon_.classList.add('hidden'); | |
124 } | |
125 }, | |
126 | |
127 /** | |
128 * Handle reconnect. | |
129 * @private | |
130 */ | |
131 handleConnect_ : function(e) { | |
132 var index = this.menu_.getMenuItemIndexOf(this); | |
133 if (this.ssidEdit && this.passwordEdit) { | |
134 if (this.ssidEdit.value) { | |
135 sendConnect(index, | |
136 this.passwordEdit.value, | |
137 this.ssidEdit.value, | |
138 this.autoConnectCheckbox.checked); | |
139 } | |
140 } else if (this.passwordEdit) { | |
141 if (this.passwordEdit.value) { | |
142 sendConnect(index, | |
143 this.passwordEdit.value, '', this.autoConnectCheckbox.checked); | |
144 } | |
145 } else { | |
146 if (this.attrs.remembered) { | |
147 sendConnect(index, this.attrs.passphrase, '', this.attrs.auto_connect); | |
148 } else { | |
149 sendConnect(index, '', '', this.autoConnectCheckbox.checked); | |
150 } | |
151 } | |
152 }, | |
153 | |
154 /** | |
155 * Handle keydown event in ssid edit. | |
156 * @private | |
157 */ | |
158 handleSsidEditKeydown_: function(e) { | |
159 if (e.target == this.ssidEdit && | |
160 e.keyIdentifier == 'Enter') { | |
161 this.passwordEdit.focus(); | |
162 } | |
163 }, | |
164 | |
165 /** | |
166 * Handle keydown event in password edit. | |
167 * @private | |
168 */ | |
169 handlePassEditKeydown_: function(e) { | |
170 if (e.target == this.passwordEdit && | |
171 e.keyIdentifier == 'Enter') { | |
172 this.handleConnect_(); | |
173 } | |
174 }, | |
175 | |
176 /** | |
177 * Returns whether action area is visible. | |
178 * @private | |
179 */ | |
180 isActionVisible_: function() { | |
181 return !this.action_.classList.contains('hidden'); | |
182 }, | |
183 | |
184 /** | |
185 * Show/hide action area. | |
186 * @private | |
187 */ | |
188 showAction_: function(show) { | |
189 var visible = this.isActionVisible_(); | |
190 if (show && !visible) { | |
191 this.action_.classList.remove('hidden'); | |
192 } else if (!show && visible) { | |
193 this.action_.classList.add('hidden'); | |
194 } | |
195 }, | |
196 | |
197 /** | |
198 * Add network name edit to action area. | |
199 * @private | |
200 */ | |
201 addSsidEdit_: function() { | |
202 this.ssidEdit = this.ownerDocument.createElement('input'); | |
203 this.ssidEdit.type = 'text'; | |
204 this.ssidEdit.placeholder = localStrings.getString('ssid_prompt'); | |
205 this.ssidEdit.pattern = '^\\S+$'; | |
206 this.ssidEdit.addEventListener('keydown', | |
207 this.handleSsidEditKeydown_.bind(this)); | |
208 | |
209 var box = this.ownerDocument.createElement('div'); | |
210 box.appendChild(this.ssidEdit); | |
211 this.action_.appendChild(box); | |
212 }, | |
213 | |
214 /** | |
215 * Add password edit to action area. | |
216 * @private | |
217 */ | |
218 addPasswordEdit_: function() { | |
219 this.passwordEdit = this.ownerDocument.createElement('input'); | |
220 this.passwordEdit.type = 'password'; | |
221 this.passwordEdit.placeholder = localStrings.getString('pass_prompt'); | |
222 this.passwordEdit.pattern = '^\\S+$'; | |
223 this.passwordEdit.addEventListener('keydown', | |
224 this.handlePassEditKeydown_.bind(this)); | |
225 | |
226 var box = this.ownerDocument.createElement('div'); | |
227 box.appendChild(this.passwordEdit); | |
228 this.action_.appendChild(box); | |
229 }, | |
230 | |
231 /** | |
232 * Add auto-connect this network check box to action area. | |
233 * @private | |
234 */ | |
235 addAutoConnectCheckbox_: function() { | |
236 this.autoConnectCheckbox = this.ownerDocument.createElement('input'); | |
237 this.autoConnectCheckbox.type = 'checkbox'; | |
238 this.autoConnectCheckbox.checked = this.attrs.auto_connect; | |
239 | |
240 var autoConnectSpan = this.ownerDocument.createElement('span'); | |
241 autoConnectSpan.textContent = | |
242 localStrings.getString('auto_connect_this_network'); | |
243 | |
244 var autoConnectLabel = this.ownerDocument.createElement('label'); | |
245 autoConnectLabel.appendChild(this.autoConnectCheckbox); | |
246 autoConnectLabel.appendChild(autoConnectSpan); | |
247 | |
248 this.action_.appendChild(autoConnectLabel); | |
249 }, | |
250 | |
251 /** | |
252 * Internal method to initiailze the MenuItem. | |
253 * @private | |
254 */ | |
255 initMenuItem_: function() { | |
256 // *TODO: eliminate code duplication with menu.js | |
257 // MenuItem.prototype.initMenuItem_(); | |
258 var attrs = this.attrs; | |
259 this.classList.add(attrs.type); | |
260 this.menu_.addHandlers(this, this); | |
261 | |
262 //////// NetworkMenuItem specific code: | |
263 // TODO: Handle specific types of network, connecting icon. | |
264 this.label_.textContent = attrs.label; | |
265 | |
266 if (attrs.network_type == NetworkOther) { | |
267 this.addSsidEdit_(); | |
268 this.addPasswordEdit_(); | |
269 this.addAutoConnectCheckbox_(); | |
270 } else if (attrs.status && attrs.status != 'unknown') { | |
271 if (attrs.status == StatusConnected) { | |
272 this.setStatus_(attrs.ip_address); | |
273 } else if (attrs.status == StatusConnecting) { | |
274 this.setStatus_(attrs.message); | |
275 | |
276 this.icon_.classList.add('spinner'); | |
277 this.icon_.classList.remove('hidden'); | |
278 } else if (attrs.status == StatusError) { | |
279 this.setStatus_(attrs.message); | |
280 this.setIcon_('chrome://theme/IDR_WARNING'); | |
281 | |
282 var button = this.ownerDocument.createElement('button'); | |
283 button.textContent = localStrings.getString('reconnect'); | |
284 button.addEventListener('click', this.handleConnect_.bind(this)); | |
285 var box = this.ownerDocument.createElement('div'); | |
286 box.appendChild(button); | |
287 this.action_.appendChild(box); | |
288 | |
289 this.showAction_(true); | |
290 } | |
291 | |
292 if (attrs.need_passphrase) { | |
293 this.addPasswordEdit_(); | |
294 } | |
295 | |
296 this.addAutoConnectCheckbox_(); | |
297 } | |
298 //////// End NetworkMenuItem specifi code | |
299 | |
300 if (attrs.font) { | |
301 this.label_.style.font = attrs.font; | |
302 | |
303 var baseFont = attrs.font.replace(/bold/, '').replace(/italic/, ''); | |
304 this.status_.style.font = baseFont; | |
305 this.action_.style.font = baseFont; | |
306 } | |
307 }, | |
308 | |
309 /** @override */ | |
310 activate: function() { | |
311 // Close action area and connect if it is visible. | |
312 if (this.isActionVisible_()) { | |
313 this.showAction_(false); | |
314 this.handleConnect_(); | |
315 return; | |
316 } | |
317 | |
318 // Show action area for encrypted network and 'other' network. | |
319 if ((this.attrs.network_type == NetworkOther || | |
320 this.attrs.status == StatusDisconnected) && | |
321 this.attrs.need_passphrase && | |
322 !this.isActionVisible_()) { | |
323 this.showAction_(true); | |
324 return; | |
325 } | |
326 | |
327 MenuItem.prototype.activate.call(this); | |
328 } | |
329 }; | |
330 | |
331 | |
332 var NetworkMenu = cr.ui.define('div'); | |
333 | |
334 NetworkMenu.prototype = { | |
335 __proto__: Menu.prototype, | |
336 | |
337 /** @override */ | |
338 createMenuItem: function(attrs) { | |
339 if (attrs.type == 'command') { | |
340 return new NetworkMenuItem(); | |
341 } else { | |
342 return new MenuItem(); | |
343 } | |
344 }, | |
345 | |
346 /** @override */ | |
347 onClick_: function(event, item) { | |
348 // If item is a NetworkMenuItem, it must have at least one of the following. | |
349 if (item.autoConnectCheckbox || item.ssidEdit || item.passwordEdit) { | |
350 // Ignore clicks other than on the NetworkMenuItem itself. | |
351 if (event.target == item.autoConnectCheckbox || | |
352 event.target == item.autoConnectCheckbox.nextElementSibling || | |
353 event.target == item.ssidEdit || | |
354 event.target == item.passwordEdit) { | |
355 return; | |
356 } | |
357 } | |
358 | |
359 Menu.prototype.onClick_.call(this, event, item); | |
360 }, | |
361 }; | |
OLD | NEW |