Commit 29d52914 authored by Steven Bennetts's avatar Steven Bennetts Committed by Commit Bot

Use mojo in network-apnlist

This CL:
* Introduces <network-property-list-mojo>
* Uses the mojo element and mojo properties in <network-apnlist>

Follow-up CLs will use <network-property-list-mojo> more broadly.

Bug: 853953
Change-Id: I25ed760ecb8bfaa88936cbf88271c6c74525f41f
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1758490
Commit-Queue: Steven Bennetts <stevenjb@chromium.org>
Reviewed-by: default avatarKyle Horimoto <khorimoto@chromium.org>
Cr-Commit-Position: refs/heads/master@{#690238}
parent ea8f8edd
......@@ -118,8 +118,8 @@
<!-- APN (Cellular only) -->
<template is="dom-if" if="[[isCellular_(managedProperties_)]]">
<div class="section single-column">
<network-apnlist editable on-apn-change="onNetworkPropertyChange_"
network-properties="[[networkProperties]]">
<network-apnlist editable on-apn-change="onApnChange_"
managed-properties="[[managedProperties_]]">
</network-apnlist>
</div>
</template>
......@@ -163,8 +163,7 @@
<div class="section single-column indented">
<network-property-list
fields="[[getInfoFields_(networkProperties)]]"
property-dict="[[networkProperties]]"
on-property-change="onNetworkPropertyChange_">
property-dict="[[networkProperties]]">
</network-property-list>
</div>
</template>
......
......@@ -272,6 +272,24 @@ Polymer({
});
},
/**
* @param {!mojom.ConfigProperties} config
* @private
*/
setMojoNetworkProperties_: function(config) {
if (!this.networkPropertiesReceived_ || !this.guid) {
return;
}
this.networkConfig_.setProperties(this.guid, config).then(response => {
if (!response.success) {
console.error('Unable to set properties: ' + JSON.stringify(config));
// An error typically indicates invalid input; request the properties
// to update any invalid fields.
this.getNetworkDetails_();
}
});
},
/**
* @return {!chrome.networkingPrivate.NetworkConfigProperties} An ONC
* dictionary with just the Type property set. Used for passing properties
......@@ -469,24 +487,16 @@ Polymer({
},
/**
* Event triggered for elements associated with network properties.
* @param {!CustomEvent<!{field: string, value: (string|!Object)}>} event
* @param {!CustomEvent<!mojom.ApnProperties>} event
* @private
*/
onNetworkPropertyChange_: function(event) {
if (!this.networkProperties) {
return;
}
const field = event.detail.field;
const value = event.detail.value;
const onc = this.getEmptyNetworkProperties_();
if (field == 'APN') {
CrOnc.setTypeProperty(onc, 'APN', value);
} else {
console.error('Unexpected property change event: ' + field);
onApnChange_: function(event) {
if (!this.networkPropertiesReceived_) {
return;
}
this.setNetworkProperties_(onc);
const apn = event.detail;
const config = {cellular: {apn: apn}};
this.setMojoNetworkProperties_(config);
},
/**
......
......@@ -303,8 +303,8 @@
<!-- APN -->
<template is="dom-if" if="[[isCellular_(managedProperties_)]]">
<network-apnlist on-apn-change="onNetworkPropertyChange_"
network-properties="[[networkProperties_]]">
<network-apnlist on-apn-change="onApnChange_"
managed-properties="[[managedProperties_]]">
</network-apnlist>
</template>
......
......@@ -1160,30 +1160,38 @@ Polymer({
const field = e.detail.field;
const value = e.detail.value;
const onc = this.getEmptyNetworkProperties_();
if (field == 'APN') {
CrOnc.setTypeProperty(onc, 'APN', value);
} else {
const valueType = typeof value;
if (valueType == 'string' || valueType == 'number' ||
valueType == 'boolean' || Array.isArray(value)) {
CrOnc.setProperty(onc, field, value);
// Ensure any required configuration properties are also set.
if (field.match(/^VPN/)) {
const vpnType =
CrOnc.getActiveValue(this.networkProperties_.VPN.Type);
assert(vpnType);
CrOnc.setProperty(onc, 'VPN.Type', vpnType);
}
} else {
console.error(
'Unexpected property change event, Key: ' + field +
' Value: ' + JSON.stringify(value));
return;
}
const valueType = typeof value;
if (valueType != 'string' && valueType != 'number' &&
valueType != 'boolean' && !Array.isArray(value)) {
console.error(
'Unexpected property change event, Key: ' + field +
' Value: ' + JSON.stringify(value));
return;
}
CrOnc.setProperty(onc, field, value);
// Ensure any required configuration properties are also set.
if (field.match(/^VPN/)) {
const vpnType = CrOnc.getActiveValue(this.networkProperties_.VPN.Type);
assert(vpnType);
CrOnc.setProperty(onc, 'VPN.Type', vpnType);
}
this.setNetworkProperties_(onc);
},
/**
* @param {!CustomEvent<!mojom.ApnProperties>} event
* @private
*/
onApnChange_: function(event) {
if (!this.networkPropertiesReceived_) {
return;
}
const apn = event.detail;
const config = {cellular: {apn: apn}};
this.setMojoNetworkProperties_(config);
},
/**
* Event triggered when the IP Config or NameServers element changes.
* @param {!CustomEvent<!{
......
......@@ -19,6 +19,7 @@ js_type_check("closure_compile") {
":network_nameservers",
":network_password_input",
":network_property_list",
":network_property_list_mojo",
":network_proxy",
":network_proxy_exclusions",
":network_proxy_input",
......@@ -35,7 +36,7 @@ js_library("mojo_interface_provider") {
js_library("network_apnlist") {
deps = [
"//ui/webui/resources/cr_elements/chromeos/network:cr_onc_types",
"//ui/webui/resources/cr_components/chromeos/network:network_config",
"//ui/webui/resources/js:i18n_behavior",
]
}
......@@ -126,6 +127,15 @@ js_library("network_property_list") {
]
}
js_library("network_property_list_mojo") {
deps = [
"//ui/webui/resources/cr_elements/policy:cr_policy_network_behavior_mojo",
"//ui/webui/resources/js:assert",
"//ui/webui/resources/js:i18n_behavior",
"//ui/webui/resources/js/chromeos:onc_mojo",
]
}
js_library("network_proxy") {
deps = [
"//ui/webui/resources/cr_elements/chromeos/network:cr_onc_types",
......
<link rel="import" href="chrome://resources/html/polymer.html">
<link rel="import" href="chrome://resources/cr_elements/chromeos/network/cr_onc_types.html">
<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
<link rel="import" href="chrome://resources/html/i18n_behavior.html">
<link rel="import" href="chrome://resources/cr_elements/md_select_css.html">
<link rel="import" href="network_property_list.html">
<link rel="import" href="network_property_list_mojo.html">
<link rel="import" href="network_shared_css.html">
<dom-module id="network-apnlist">
......@@ -20,17 +19,17 @@
value="[[selectedApn_]]"
aria-label="[[i18n('networkAccessPoint')]]">
<template is="dom-repeat" items="[[apnSelectList_]]">
<option value="[[item.AccessPointName]]">[[apnDesc_(item)]]</option>
<option value="[[item.accessPointName]]">[[apnDesc_(item)]]</option>
</template>
</select>
</div>
<div class="property-box single-column indented"
hidden$="[[!isOtherSelected_(selectedApn_, networkProperties)]]">
<network-property-list on-property-change="onOtherApnChange_"
hidden$="[[!isOtherSelected_(selectedApn_, managedProperties)]]">
<network-property-list-mojo on-property-change="onOtherApnChange_"
fields="[[otherApnFields_]]" property-dict="[[otherApn_]]"
edit-field-types="[[otherApnEditTypes_]]" prefix="Cellular.APN.">
</network-property-list>
edit-field-types="[[otherApnEditTypes_]]" prefix="cellular.apn.">
</network-property-list-mojo>
<cr-button class="action-button" on-click="onSaveOtherTap_">
[[i18n('save')]]
</cr-button>
......
......@@ -6,23 +6,26 @@
* @fileoverview Polymer element for displaying and modifying a list of cellular
* access points.
*/
(function() {
'use strict';
const kDefaultAccessPointName = 'NONE';
const kOtherAccessPointName = 'Other';
Polymer({
is: 'network-apnlist',
behaviors: [I18nBehavior],
properties: {
/**
* The current set of properties for the network matching |guid|.
* @type {!CrOnc.NetworkProperties|undefined}
*/
networkProperties: {
/** @private {!chromeos.networkConfig.mojom.ManagedProperties|undefined} */
managedProperties: {
type: Object,
observer: 'networkPropertiesChanged_',
observer: 'managedPropertiesChanged_',
},
/**
* The CrOnc.APNProperties.AccessPointName value of the selected APN.
* accessPointName value of the selected APN.
* @private
*/
selectedApn_: {
......@@ -33,7 +36,7 @@ Polymer({
/**
* Selectable list of APN dictionaries for the UI. Includes an entry
* corresponding to |otherApn| (see below).
* @private {!Array<!CrOnc.APNProperties>}
* @private {!Array<!chromeos.networkConfig.mojom.ApnProperties>}
*/
apnSelectList_: {
type: Array,
......@@ -44,9 +47,9 @@ Polymer({
/**
* The user settable properties for a new ('other') APN. The values for
* AccessPointName, Username, and Password will be set to the currently
* accessPointName, username, and password will be set to the currently
* active APN if it does not match an existing list entry.
* @private {CrOnc.APNProperties|undefined}
* @private {chromeos.networkConfig.mojom.ApnProperties|undefined}
*/
otherApn_: {
type: Object,
......@@ -59,7 +62,7 @@ Polymer({
otherApnFields_: {
type: Array,
value: function() {
return ['AccessPointName', 'Username', 'Password'];
return ['accessPointName', 'username', 'password'];
},
readOnly: true
},
......@@ -72,35 +75,41 @@ Polymer({
type: Object,
value: function() {
return {
'AccessPointName': 'String',
'Username': 'String',
'Password': 'Password'
'accessPointName': 'String',
'username': 'String',
'password': 'Password'
};
},
readOnly: true
},
},
/** @const */
DefaultAccessPointName: 'NONE',
/**
* Polymer networkProperties changed method.
* @param {!chromeos.networkConfig.mojom.ManagedApnProperties} apn
* @return {!chromeos.networkConfig.mojom.ApnProperties}
* @private
*/
networkPropertiesChanged_: function() {
if (!this.networkProperties || !this.networkProperties.Cellular) {
return;
}
getApnFromManaged_: function(apn) {
return {
accessPointName: OncMojo.getActiveString(apn.accessPointName),
authentication: OncMojo.getActiveString(apn.authentication),
language: OncMojo.getActiveString(apn.language),
localizedName: OncMojo.getActiveString(apn.localizedName),
name: OncMojo.getActiveString(apn.name),
password: OncMojo.getActiveString(apn.password),
username: OncMojo.getActiveString(apn.username),
};
},
/** @type {!CrOnc.APNProperties|undefined} */ let activeApn;
const cellular = this.networkProperties.Cellular;
/** @type {!chrome.networkingPrivate.ManagedAPNProperties|undefined} */
const apn = cellular.APN;
if (apn && apn.AccessPointName) {
activeApn = /** @type {!CrOnc.APNProperties|undefined} */ (
CrOnc.getActiveProperties(apn));
} else if (cellular.LastGoodAPN && cellular.LastGoodAPN.AccessPointName) {
activeApn = cellular.LastGoodAPN;
/** @private*/
managedPropertiesChanged_: function() {
const cellular = this.managedProperties.cellular;
/** @type {!chromeos.networkConfig.mojom.ApnProperties|undefined} */ let
activeApn;
if (cellular.apn) {
activeApn = this.getApnFromManaged_(cellular.apn);
} else if (cellular.lastGoodApn && cellular.lastGoodApn.accessPointName) {
activeApn = cellular.lastGoodApn;
}
this.setApnSelectList_(activeApn);
},
......@@ -108,17 +117,17 @@ Polymer({
/**
* Sets the list of selectable APNs for the UI. Appends an 'Other' entry
* (see comments for |otherApn_| above).
* @param {CrOnc.APNProperties|undefined} activeApn The currently active APN
* properties.
* @param {chromeos.networkConfig.mojom.ApnProperties|undefined} activeApn The
* currently active APN properties.
* @private
*/
setApnSelectList_: function(activeApn) {
// Copy the list of APNs from this.networkProperties.
const result = this.getApnList_().slice();
// Copy the list of APNs from this.managedProperties.
const apnList = this.getApnList_().slice();
// Test whether |activeApn| is in the current APN list in networkProperties.
const activeApnInList = activeApn && result.some(function(a) {
return a.AccessPointName == activeApn.AccessPointName;
// Test whether |activeApn| is in the current APN list in managedProperties.
const activeApnInList = activeApn && apnList.some(function(a) {
return a.accessPointName == activeApn.accessPointName;
});
// If |activeApn| is specified and not in the list, use the active
......@@ -129,34 +138,36 @@ Polymer({
// Always use 'Other' for the name of custom APN entries (the name does
// not get saved).
otherApn.Name = 'Other';
otherApn.name = kOtherAccessPointName;
// If no 'active' or 'other' AccessPointName was provided, use the default.
otherApn.AccessPointName =
otherApn.AccessPointName || this.DefaultAccessPointName;
otherApn.accessPointName =
otherApn.accessPointName || kDefaultAccessPointName;
// Save the 'other' properties.
this.otherApn_ = otherApn;
// Append 'other' to the end of the list of APNs.
result.push(otherApn);
apnList.push(otherApn);
this.apnSelectList_ = apnList;
this.apnSelectList_ = result;
// Set selectedApn_ after dom-repeat has been stamped.
this.async(() => {
this.selectedApn_ =
(activeApn && activeApn.AccessPointName) || otherApn.AccessPointName;
(activeApn && activeApn.accessPointName) || otherApn.accessPointName;
});
},
/**
* @param {!CrOnc.APNProperties|undefined=} apnProperties
* @return {!CrOnc.APNProperties} A new APN object with properties from
* |apnProperties| if provided.
* @param {!chromeos.networkConfig.mojom.ApnProperties|undefined=}
* apnProperties
* @return {!chromeos.networkConfig.mojom.ApnProperties} A new APN object with
* properties from |apnProperties| if provided.
* @private
*/
createApnObject_: function(apnProperties) {
const newApn = {AccessPointName: ''};
const newApn = {accessPointName: ''};
if (apnProperties) {
Object.assign(newApn, apnProperties);
}
......@@ -164,21 +175,20 @@ Polymer({
},
/**
* @return {!Array<!CrOnc.APNProperties>} The list of APN properties in
* |networkProperties| or an empty list if the property is not set.
* @return {!Array<!chromeos.networkConfig.mojom.ApnProperties>} The list of
* APN properties in |managedProperties| or an empty list if the property
* is not set.
* @private
*/
getApnList_: function() {
if (!this.networkProperties || !this.networkProperties.Cellular) {
if (!this.managedProperties) {
return [];
}
/** @type {!chrome.networkingPrivate.ManagedAPNList|undefined} */
const apnlist = this.networkProperties.Cellular.APNList;
if (!apnlist) {
const apnList = this.managedProperties.cellular.apnList;
if (!apnList) {
return [];
}
return /** @type {!Array<!CrOnc.APNProperties>} */ (
CrOnc.getActiveValue(apnlist));
return apnList.activeValue;
},
/**
......@@ -192,8 +202,8 @@ Polymer({
// When selecting 'Other', don't set a change event unless a valid
// non-default value has been set for Other.
if (this.isOtherSelected_(accessPointName) &&
(!this.otherApn_ || !this.otherApn_.AccessPointName ||
this.otherApn_.AccessPointName == this.DefaultAccessPointName)) {
(!this.otherApn_ || !this.otherApn_.accessPointName ||
this.otherApn_.accessPointName == kDefaultAccessPointName)) {
this.selectedApn_ = accessPointName;
return;
}
......@@ -206,9 +216,9 @@ Polymer({
* @private
*/
onOtherApnChange_: function(event) {
// TODO(benchan/stevenjb): Move this to shill or
// TODO(benchan/stevenjb): Move the toUpperCase logic to shill or
// onc_translator_onc_to_shill.cc.
const value = (event.detail.field == 'AccessPointName') ?
const value = (event.detail.field == 'accessPointName') ?
event.detail.value.toUpperCase() :
event.detail.value;
this.set('otherApn_.' + event.detail.field, value);
......@@ -231,16 +241,16 @@ Polymer({
*/
sendApnChange_: function(accessPointName) {
const apnList = this.getApnList_();
let apn = this.findApnInList(apnList, accessPointName);
let apn = this.findApnInList_(apnList, accessPointName);
if (apn == undefined) {
apn = this.createApnObject_();
if (this.otherApn_) {
apn.AccessPointName = this.otherApn_.AccessPointName;
apn.Username = this.otherApn_.Username;
apn.Password = this.otherApn_.Password;
apn.accessPointName = this.otherApn_.accessPointName;
apn.username = this.otherApn_.username;
apn.password = this.otherApn_.password;
}
}
this.fire('apn-change', {field: 'APN', value: apn});
this.fire('apn-change', apn);
},
/**
......@@ -249,33 +259,34 @@ Polymer({
* @private
*/
isOtherSelected_: function(accessPointName) {
if (!this.networkProperties || !this.networkProperties.Cellular) {
if (!this.managedProperties) {
return false;
}
const apnList = this.getApnList_();
const apn = this.findApnInList(apnList, accessPointName);
const apn = this.findApnInList_(apnList, accessPointName);
return apn == undefined;
},
/**
* @param {!CrOnc.APNProperties} apn
* @param {!chromeos.networkConfig.mojom.ApnProperties} apn
* @return {string} The most descriptive name for the access point.
* @private
*/
apnDesc_: function(apn) {
return apn.LocalizedName || apn.Name || apn.AccessPointName;
return apn.localizedName || apn.name || apn.accessPointName;
},
/**
* @param {!Array<!CrOnc.APNProperties>} apnList
* @param {!Array<!chromeos.networkConfig.mojom.ApnProperties>} apnList
* @param {string} accessPointName
* @return {CrOnc.APNProperties|undefined} The entry in |apnList| matching
* |accessPointName| if it exists, or undefined.
* @return {chromeos.networkConfig.mojom.ApnProperties|undefined} The entry in
* |apnList| matching |accessPointName| if it exists, or undefined.
* @private
*/
findApnInList: function(apnList, accessPointName) {
findApnInList_: function(apnList, accessPointName) {
return apnList.find(function(a) {
return a.AccessPointName == accessPointName;
return a.accessPointName == accessPointName;
});
}
});
})();
<link rel="import" href="chrome://resources/html/polymer.html">
<link rel="import" href="chrome://resources/cr_elements/cr_input/cr_input.html">
<link rel="import" href="chrome://resources/cr_elements/policy/cr_policy_network_behavior_mojo.html">
<link rel="import" href="chrome://resources/cr_elements/policy/cr_policy_network_indicator_mojo.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="network_shared_css.html">
<dom-module id="network-property-list-mojo">
<template>
<style include="network-shared iron-flex">
/* Property lists are embedded; remove the padding. */
.property-box {
padding: 0;
}
cr-input[readonly] {
--cr-input-background-color: transparent;
}
cr-policy-network-indicator {
margin-inline-start: var(--settings-controlled-by-spacing);
}
</style>
<template is="dom-repeat" items="[[fields]]"
filter="[[computeFilter_(prefix, propertyDict, editFieldTypes)]]">
<div class="property-box single-column two-line stretch">
<!-- Property label -->
<div class="layout horizontal center">
<div>[[getPropertyLabel_(item, prefix)]]</div>
<template is="dom-if" restamp
if="[[isEditType_(item, editFieldTypes)]]">
<cr-policy-network-indicator-mojo
property="[[getProperty_(item, propertyDict)]]">
</cr-policy-network-indicator-mojo>
</template>
</div>
<!-- Uneditable property value -->
<template is="dom-if" restamp
if="[[!showEditable_(item, propertyDict, editFieldTypes)]]">
<div class="secondary">
[[getPropertyValue_(item, prefix, propertyDict)]]
</div>
</template>
<!-- Editable property value -->
<template is="dom-if" restamp
if="[[showEditable_(item, propertyDict, editFieldTypes)]]">
<cr-input id="[[item]]"
readonly="[[!isEditable_(item, propertyDict, editFieldTypes)]]"
value="[[getPropertyValue_(item, prefix, propertyDict)]]"
on-change="onValueChange_"
type="[[getEditInputType_(item, editFieldTypes)]]">
</cr-input>
</template>
</div>
</template>
</template>
<script src="network_property_list_mojo.js"></script>
</dom-module>
// Copyright 2019 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.
*/
(function() {
'use strict';
Polymer({
is: 'network-property-list-mojo',
behaviors: [I18nBehavior, CrPolicyNetworkBehaviorMojo],
properties: {
/**
* 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.
* When a field changes, the 'property-change' event will be fired with
* the field name and the new value provided in the event detail.
* @type {!Object<string>}
*/
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 = OncMojo.getActiveValue(
/** @type{OncMojo.ManagedProperty} */ (curValue));
}
const newValue = this.getValueFromEditField_(key, event.target.value);
if (newValue == curValue) {
return;
}
this.fire('property-change', {field: key, value: newValue});
},
/**
* Converts mojo keys to ONC keys. TODO(stevenjb): Remove this and update
* string ids once everything is converted to mojo.
* @param {string} key
* @param {string=} opt_prefix
* @return {string}
* @private
*/
getOncKey_: function(key, opt_prefix) {
if (opt_prefix) {
key = opt_prefix + key.charAt(0).toUpperCase() + key.slice(1);
}
let result = '';
const subKeys = key.split('.');
subKeys.forEach(subKey => {
// Check for exceptions to CamelCase vs camelCase naming conventions.
if (subKey == 'apn') {
result += 'APN-';
} else {
result += subKey.charAt(0).toUpperCase() + subKey.slice(1) + '-';
}
});
return 'Onc' + result.slice(0, result.length - 1);
},
/**
* @param {string} key The property key.
* @param {string} prefix
* @return {string} The text to display for the property label.
* @private
*/
getPropertyLabel_: function(key, prefix) {
const oncKey = this.getOncKey_(key, prefix);
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.
const result = prefix + key;
for (const type of ['cellular', 'ethernet', 'tether', 'vpn', 'wifi']) {
if (result.startsWith(type + '.')) {
return result.substr(type.length + 1);
}
}
return result;
},
/**
* Generates a filter function dependent on propertyDict and editFieldTypes.
* @param {string} prefix
* @param {!Object} propertyDict
* @param {!Object} editFieldTypes
* @return {!Object} A filter used by dom-repeat.
* @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) {
if (!propertyDict) {
return false;
}
const property =
/** @type{OncMojo.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 != chromeos.networkConfig.mojom.OncSource.kUserPolicy &&
source != chromeos.networkConfig.mojom.OncSource.kDevicePolicy;
}
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 propertyDict && 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);
},
/**
* @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, this.propertyDict);
if (property === undefined) {
// If the dictionary is policy controlled, provide an empty property
// object with the network policy source. See https://crbug.com/819837 for
// more info.
const source = propertyDict.source;
if (source == chromeos.networkConfig.mojom.OncSource.kUserPolicy) {
return /** @type{!OncMojo.ManagedProperty} */ ({
activeValue: '',
policySource:
chromeos.networkConfig.mojom.PolicySource.kUserPolicyEnforced,
});
}
if (source == chromeos.networkConfig.mojom.OncSource.kDevicePolicy) {
return /** @type{!OncMojo.ManagedProperty} */ ({
activeValue: '',
policySource:
chromeos.networkConfig.mojom.PolicySource.kDevicePolicyEnforced,
});
}
// Otherwise just return undefined.
}
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 = OncMojo.getActiveValue(
/** @type {!OncMojo.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);
const oncKey = this.getOncKey_(key, prefix) + '_' + 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 '';
},
});
})();
......@@ -195,6 +195,14 @@
file="cr_components/chromeos/network/network_property_list.js"
type="chrome_html"
compress="gzip" />
<structure name="IDR_WEBUI_CHROMEOS_NETWORK_PROPERTY_LIST_MOJO_HTML"
file="cr_components/chromeos/network/network_property_list_mojo.html"
type="chrome_html"
compress="gzip" />
<structure name="IDR_WEBUI_CHROMEOS_NETWORK_PROPERTY_LIST_MOJO_JS"
file="cr_components/chromeos/network/network_property_list_mojo.js"
type="chrome_html"
compress="gzip" />
<structure name="IDR_WEBUI_CHROMEOS_NETWORK_PROXY_HTML"
file="cr_components/chromeos/network/network_proxy.html"
type="chrome_html"
......
......@@ -9,8 +9,6 @@
(function() {
'use strict';
const mojom = chromeos.networkConfig.mojom;
Polymer({
is: 'cr-policy-network-indicator-mojo',
......@@ -21,8 +19,9 @@ Polymer({
* Network property associated with the indicator. Note: |property| may
* be null or undefined, depending on how the properties dictionary is
* generated.
* @type {?mojom.ManagedBoolean|?mojom.ManagedInt32|?mojom.ManagedString|
* undefined}
* @type {?chromeos.networkConfig.mojom.ManagedBoolean|
* ?chromeos.networkConfig.mojom.ManagedInt32|
* ?chromeos.networkConfig.mojom.ManagedString|undefined}
*/
property: Object,
......@@ -46,21 +45,22 @@ Polymer({
this.indicatorType = CrPolicyIndicatorType.NONE;
return;
}
const PolicySource = chromeos.networkConfig.mojom.PolicySource;
switch (property.policySource) {
case mojom.PolicySource.kNone:
case PolicySource.kNone:
this.indicatorType = CrPolicyIndicatorType.NONE;
break;
case mojom.PolicySource.kUserPolicyEnforced:
case PolicySource.kUserPolicyEnforced:
this.indicatorType = CrPolicyIndicatorType.USER_POLICY;
break;
case mojom.PolicySource.kDevicePolicyEnforced:
case PolicySource.kDevicePolicyEnforced:
this.indicatorType = CrPolicyIndicatorType.DEVICE_POLICY;
break;
case mojom.PolicySource.kUserPolicyRecommended:
case mojom.PolicySource.kDevicePolicyRecommended:
case PolicySource.kUserPolicyRecommended:
case PolicySource.kDevicePolicyRecommended:
this.indicatorType = CrPolicyIndicatorType.RECOMMENDED;
break;
case mojom.PolicySource.kActiveExtension:
case PolicySource.kActiveExtension:
this.indicatorType = CrPolicyIndicatorType.EXTENSION;
break;
}
......
......@@ -662,8 +662,11 @@ class OncMojo {
/**
* @param {!chromeos.networkConfig.mojom.ManagedBoolean|
* !chromeos.networkConfig.mojom.ManagedInt32|
* !chromeos.networkConfig.mojom.ManagedString|undefined} property
* @return {boolean|number|string|undefined}
* !chromeos.networkConfig.mojom.ManagedString|
* !chromeos.networkConfig.mojom.ManagedStringList|
* !chromeos.networkConfig.mojom.ManagedApnList|undefined} property
* @return {boolean|number|string|!Array<string>|
* !Array<!chromeos.networkConfig.mojom.ApnProperties>|undefined}
*/
static getActiveValue(property) {
if (!property) {
......
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