// Copyright (c) 2011 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.
// Network status constants.
const StatusConnected = 'connected';
const StatusDisconnected = 'disconnected';
const StatusConnecting = 'connecting';
const StatusError = 'error';
const NetworkOther = 'other';
// Setup css canvas 'spinner-circle'
(function() {
var lineWidth = 3;
var r = 8;
var ctx = document.getCSSCanvasContext('2d', 'spinner-circle', 2 * r, 2 * r);
ctx.lineWidth = lineWidth;
ctx.lineCap = 'round';
ctx.lineJoin = 'round';
ctx.strokeStyle = '#4e73c7';
ctx.beginPath();
ctx.moveTo(lineWidth / 2, r - lineWidth / 2);
ctx.arc(r, r, r - lineWidth / 2, Math.PI, Math.PI * 3 / 2);
ctx.stroke();
})();
/**
* Sends "connect" using the 'action' WebUI message.
*/
function sendConnect(index, passphrase, identity, auto_connect) {
chrome.send('action',
['connect',
String(index),
passphrase,
identity,
auto_connect ? '1' : '0']);
}
var networkMenuItemProto = (function() {
var networkMenuItem = cr.doc.createElement('div');
networkMenuItem.innerHTML = '<div class="network-menu-item">' +
'<div class="network-label-icon">' +
'<div class="network-label"></div>' +
'<div class="network-icon hidden"></div>' +
'</div>' +
'<div class="network-status hidden"></div>' +
'<div class="hidden"></div>' +
'</div>';
return networkMenuItem;
})();
var NetworkMenuItem = cr.ui.define(function() {
return networkMenuItemProto.cloneNode(true);
});
NetworkMenuItem.prototype = {
__proto__: MenuItem.prototype,
ssidEdit: null,
passwordEdit: null,
autoConnectCheckbox: null,
/**
* The label element.
* @private
*/
get label_() {
return this.firstElementChild.firstElementChild.firstElementChild;
},
/**
* The icon element.
* @private
*/
get icon_() {
return this.label_.nextElementSibling;
},
/**
* The status area element.
* @private
*/
get status_() {
return this.firstElementChild.firstElementChild.nextElementSibling;
},
/**
* The action area container element.
* @private
*/
get action_() {
return this.status_.nextElementSibling;
},
/**
* Set status message.
* @param {string} message The message to display in status area.
* @private
*/
setStatus_: function(message) {
if (message) {
this.status_.textContent = message;
this.status_.classList.remove('hidden');
} else {
this.status_.classList.add('hidden');
}
},
/**
* Set status icon.
* @param {string} icon Source url for the icon image.
* @private
*/
setIcon_: function(icon) {
if (icon) {
this.icon_.style.backgroundImage = 'url(' + icon + ')';
this.icon_.classList.remove('hidden');
} else {
this.icon_.classList.add('hidden');
}
},
/**
* Handle reconnect.
* @private
*/
handleConnect_ : function(e) {
var index = this.menu_.getMenuItemIndexOf(this);
if (this.ssidEdit && this.passwordEdit) {
if (this.ssidEdit.value) {
sendConnect(index,
this.passwordEdit.value,
this.ssidEdit.value,
this.autoConnectCheckbox.checked);
}
} else if (this.passwordEdit) {
if (this.passwordEdit.value) {
sendConnect(index,
this.passwordEdit.value, '', this.autoConnectCheckbox.checked);
}
} else {
if (this.attrs.remembered) {
sendConnect(index, this.attrs.passphrase, '', this.attrs.auto_connect);
} else {
sendConnect(index, '', '', this.autoConnectCheckbox.checked);
}
}
},
/**
* Handle keydown event in ssid edit.
* @private
*/
handleSsidEditKeydown_: function(e) {
if (e.target == this.ssidEdit &&
e.keyIdentifier == 'Enter') {
this.passwordEdit.focus();
}
},
/**
* Handle keydown event in password edit.
* @private
*/
handlePassEditKeydown_: function(e) {
if (e.target == this.passwordEdit &&
e.keyIdentifier == 'Enter') {
this.handleConnect_();
}
},
/**
* Returns whether action area is visible.
* @private
*/
isActionVisible_: function() {
return !this.action_.classList.contains('hidden');
},
/**
* Show/hide action area.
* @private
*/
showAction_: function(show) {
var visible = this.isActionVisible_();
if (show && !visible) {
this.action_.classList.remove('hidden');
} else if (!show && visible) {
this.action_.classList.add('hidden');
}
},
/**
* Add network name edit to action area.
* @private
*/
addSsidEdit_: function() {
this.ssidEdit = this.ownerDocument.createElement('input');
this.ssidEdit.type = 'text';
this.ssidEdit.placeholder = localStrings.getString('ssid_prompt');
this.ssidEdit.pattern = '^\\S+$';
this.ssidEdit.addEventListener('keydown',
this.handleSsidEditKeydown_.bind(this));
var box = this.ownerDocument.createElement('div');
box.appendChild(this.ssidEdit);
this.action_.appendChild(box);
},
/**
* Add password edit to action area.
* @private
*/
addPasswordEdit_: function() {
this.passwordEdit = this.ownerDocument.createElement('input');
this.passwordEdit.type = 'password';
this.passwordEdit.placeholder = localStrings.getString('pass_prompt');
this.passwordEdit.pattern = '^\\S+$';
this.passwordEdit.addEventListener('keydown',
this.handlePassEditKeydown_.bind(this));
var box = this.ownerDocument.createElement('div');
box.appendChild(this.passwordEdit);
this.action_.appendChild(box);
},
/**
* Add auto-connect this network check box to action area.
* @private
*/
addAutoConnectCheckbox_: function() {
this.autoConnectCheckbox = this.ownerDocument.createElement('input');
this.autoConnectCheckbox.type = 'checkbox';
this.autoConnectCheckbox.checked = this.attrs.auto_connect;
var autoConnectSpan = this.ownerDocument.createElement('span');
autoConnectSpan.textContent =
localStrings.getString('auto_connect_this_network');
var autoConnectLabel = this.ownerDocument.createElement('label');
autoConnectLabel.appendChild(this.autoConnectCheckbox);
autoConnectLabel.appendChild(autoConnectSpan);
this.action_.appendChild(autoConnectLabel);
},
/**
* Internal method to initiailze the MenuItem.
* @private
*/
initMenuItem_: function() {
// *TODO: eliminate code duplication with menu.js
// MenuItem.prototype.initMenuItem_();
var attrs = this.attrs;
this.classList.add(attrs.type);
this.menu_.addHandlers(this, this);
//////// NetworkMenuItem specific code:
// TODO: Handle specific types of network, connecting icon.
this.label_.textContent = attrs.label;
if (attrs.network_type == NetworkOther) {
this.addSsidEdit_();
this.addPasswordEdit_();
this.addAutoConnectCheckbox_();
} else if (attrs.status && attrs.status != 'unknown') {
if (attrs.status == StatusConnected) {
this.setStatus_(attrs.ip_address);
} else if (attrs.status == StatusConnecting) {
this.setStatus_(attrs.message);
this.icon_.classList.add('spinner');
this.icon_.classList.remove('hidden');
} else if (attrs.status == StatusError) {
this.setStatus_(attrs.message);
this.setIcon_('chrome://theme/IDR_WARNING');
var button = this.ownerDocument.createElement('button');
button.textContent = localStrings.getString('reconnect');
button.addEventListener('click', this.handleConnect_.bind(this));
var box = this.ownerDocument.createElement('div');
box.appendChild(button);
this.action_.appendChild(box);
this.showAction_(true);
}
if (attrs.need_passphrase) {
this.addPasswordEdit_();
}
this.addAutoConnectCheckbox_();
}
//////// End NetworkMenuItem specifi code
if (attrs.font) {
this.label_.style.font = attrs.font;
var base_font = attrs.font.replace(/bold/, '').replace(/italic/, '');
this.status_.style.font = base_font;
this.action_.style.font = base_font;
}
},
/** @inheritDoc */
activate: function() {
// Close action area and connect if it is visible.
if (this.isActionVisible_()) {
this.showAction_(false);
this.handleConnect_();
return;
}
// Show action area for encrypted network and 'other' network.
if ((this.attrs.network_type == NetworkOther ||
this.attrs.status == StatusDisconnected) &&
this.attrs.need_passphrase &&
!this.isActionVisible_()) {
this.showAction_(true);
return;
}
MenuItem.prototype.activate.call(this);
}
};
var NetworkMenu = cr.ui.define('div');
NetworkMenu.prototype = {
__proto__: Menu.prototype,
/** @inheritDoc */
createMenuItem: function(attrs) {
if (attrs.type == 'command') {
return new NetworkMenuItem();
} else {
return new MenuItem();
}
},
/** @inheritDoc */
onClick_: function(event, item) {
// If item is a NetworkMenuItem, it must have at least one of the following.
if (item.autoConnectCheckbox || item.ssidEdit || item.passwordEdit) {
// Ignore clicks other than on the NetworkMenuItem itself.
if (event.target == item.autoConnectCheckbox ||
event.target == item.autoConnectCheckbox.nextElementSibling ||
event.target == item.ssidEdit ||
event.target == item.passwordEdit) {
return;
}
}
Menu.prototype.onClick_.call(this, event, item);
},
};