blob: 42629e96f16f2579813c4896bd4b79b33c32bfa7 [file] [log] [blame]
// Copyright 2015 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.
/**
* @fileoverview Polymer element for displaying a list of network properties
* in a list. This also supports editing fields inline for fields listed in
* editFieldTypes.
*/
Polymer({
is: 'network-property-list',
behaviors: [I18nBehavior, CrPolicyNetworkBehavior],
properties: {
/**
* If true, all fields are shown as editable. Fields without an edit type
* or that are policy enforced will be shown as 'readonly'. Used for lists
* with dynamic edit types (e.g. network-ip-config).
*/
editable: {
type: Boolean,
value: false,
},
/**
* The dictionary containing the properties to display.
* @type {!Object|undefined}
*/
propertyDict: {type: Object},
/**
* Fields to display.
* @type {!Array<string>}
*/
fields: {
type: Array,
value: function() {
return [];
},
},
/**
* Edit type of editable fields. May contain a property for any field in
* |fields|. Other properties will be ignored. Property values can be:
* 'String' - A text input will be displayed.
* 'StringArray' - A text input will be displayed that expects a comma
* separated list of strings.
* 'Password' - A string with input type = password.
* TODO(stevenjb): Support types with custom validation, e.g. IPAddress.
* When a field changes, the 'property-change' event will be fired with
* the field name and the new value provided in the event detail.
*/
editFieldTypes: {
type: Object,
value: function() {
return {};
},
},
/** Prefix used to look up property key translations. */
prefix: {
type: String,
value: '',
},
},
/**
* Event triggered when an input field changes. Fires a 'property-change'
* event with the field (property) name set to the target id, and the value
* set to the target input value.
* @param {!Event} event The input change event.
* @private
*/
onValueChange_: function(event) {
if (!this.propertyDict)
return;
const key = event.target.id;
let curValue = this.get(key, this.propertyDict);
if (typeof curValue == 'object' && !Array.isArray(curValue)) {
// Extract the property from an ONC managed dictionary.
curValue = CrOnc.getActiveValue(
/** @type {!CrOnc.ManagedProperty} */ (curValue));
}
const newValue = this.getValueFromEditField_(key, event.target.value);
if (newValue == curValue)
return;
this.fire('property-change', {field: key, value: newValue});
},
/**
* @param {string} key The property key.
* @param {string} prefix
* @return {string} The text to display for the property label.
* @private
*/
getPropertyLabel_: function(key, prefix) {
let oncKey = 'Onc' + prefix + key;
oncKey = oncKey.replace(/\./g, '-');
if (this.i18nExists(oncKey))
return this.i18n(oncKey);
// We do not provide translations for every possible network property key.
// For keys specific to a type, strip the type prefix.
let result = prefix + key;
for (const entry in chrome.networkingPrivate.NetworkType) {
const type = chrome.networkingPrivate.NetworkType[entry];
if (result.startsWith(type + '.')) {
result = result.substr(type.length + 1);
break;
}
}
return result;
},
/**
* Generates a filter function dependent on propertyDict and editFieldTypes.
* @param {string} prefix
* @param {!Object} propertyDict
* @param {!Object} editFieldTypes
* @private
*/
computeFilter_: function(prefix, propertyDict, editFieldTypes) {
return key => {
if (editFieldTypes.hasOwnProperty(key))
return true;
const value = this.getPropertyValue_(key, prefix, propertyDict);
return value !== undefined && value !== '';
};
},
/**
* @param {string} key The property key.
* @param {!Object} propertyDict
* @return {boolean}
* @private
*/
isPropertyEditable_: function(key, propertyDict) {
const property = /** @type {!CrOnc.ManagedProperty|undefined} */ (
this.get(key, propertyDict));
if (property === undefined) {
// Unspecified properties in policy configurations are not user
// modifiable. https://crbug.com/819837.
const source = propertyDict.Source;
return source != 'UserPolicy' && source != 'DevicePolicy';
}
return !this.isNetworkPolicyEnforced(property);
},
/**
* @param {string} key The property key.
* @param {!Object} editFieldTypes
* @return {boolean} True if the edit type for the key is a valid type.
* @private
*/
isEditType_: function(key, editFieldTypes) {
const editType = editFieldTypes[key];
return editType == 'String' || editType == 'StringArray' ||
editType == 'Password';
},
/**
* @param {string} key The property key.
* @param {!Object} propertyDict
* @param {!Object} editFieldTypes
* @return {boolean}
* @private
*/
isEditable_: function(key, propertyDict, editFieldTypes) {
return this.isEditType_(key, editFieldTypes) &&
this.isPropertyEditable_(key, propertyDict);
},
/**
* @param {string} key The property key.
* @param {!Object} propertyDict
* @param {!Object} editFieldTypes
* @return {boolean}
* @private
*/
showEditable_: function(key, propertyDict, editFieldTypes) {
return this.isEditable_(key, propertyDict, editFieldTypes) || this.editable;
},
/**
* @param {string} key The property key.
* @param {!Object} editFieldTypes
* @return {string}
* @private
*/
getEditInputType_: function(key, editFieldTypes) {
return editFieldTypes[key] == 'Password' ? 'password' : 'text';
},
/**
* @param {string} key The property key.
* @param {!Object} propertyDict
* @return {*} The managed property dictionary associated with |key|.
* @private
*/
getProperty_: function(key, propertyDict) {
const property = this.get(key, propertyDict);
if (property === undefined && propertyDict.Source) {
// Provide an empty property object with the network policy source.
// See https://crbug.com/819837 for more info.
return {Effective: propertyDict.Source};
}
return property;
},
/**
* @param {string} key The property key.
* @param {string} prefix
* @param {!Object} propertyDict
* @return {string} The text to display for the property value.
* @private
*/
getPropertyValue_: function(key, prefix, propertyDict) {
let value = this.get(key, propertyDict);
if (value === undefined)
return '';
if (typeof value == 'object' && !Array.isArray(value)) {
// Extract the property from an ONC managed dictionary
value =
CrOnc.getActiveValue(/** @type {!CrOnc.ManagedProperty} */ (value));
}
if (Array.isArray(value))
return value.join(', ');
const customValue = this.getCustomPropertyValue_(key, value);
if (customValue)
return customValue;
if (typeof value == 'number' || typeof value == 'boolean')
return value.toString();
assert(typeof value == 'string');
const valueStr = /** @type {string} */ (value);
let oncKey = 'Onc' + prefix + key;
oncKey = oncKey.replace(/\./g, '-');
oncKey += '_' + valueStr;
if (this.i18nExists(oncKey))
return this.i18n(oncKey);
return valueStr;
},
/**
* Converts edit field values to the correct edit type.
* @param {string} key The property key.
* @param {*} fieldValue The value from the field.
* @return {*}
* @private
*/
getValueFromEditField_(key, fieldValue) {
const editType = this.editFieldTypes[key];
if (editType == 'StringArray')
return fieldValue.toString().split(/, */);
return fieldValue;
},
/**
* @param {string} key The property key.
* @param {*} value The property value.
* @return {string} The text to display for the property value. If the key
* does not correspond to a custom property, an empty string is returned.
*/
getCustomPropertyValue_: function(key, value) {
if (key == 'Tether.BatteryPercentage') {
assert(typeof value == 'number');
return this.i18n('OncTether-BatteryPercentage_Value', value.toString());
}
if (key == 'Tether.SignalStrength') {
assert(typeof value == 'number');
// Possible |signalStrength| values should be 0, 25, 50, 75, and 100. Add
// <= checks for robustness.
if (value <= 24)
return this.i18n('OncTether-SignalStrength_Weak');
if (value <= 49)
return this.i18n('OncTether-SignalStrength_Okay');
if (value <= 74)
return this.i18n('OncTether-SignalStrength_Good');
if (value <= 99)
return this.i18n('OncTether-SignalStrength_Strong');
return this.i18n('OncTether-SignalStrength_VeryStrong');
}
if (key == 'Tether.Carrier') {
assert(typeof value == 'string');
return (!value || value == 'unknown-carrier') ?
this.i18n('tetherUnknownCarrier') :
value;
}
return '';
},
});