Commit 43116fdd authored by Nikita Podguzov's avatar Nikita Podguzov Committed by Commit Bot

Disable editing managed network config fields.

* Disable network configuration field if the field is enforced by policy.
* Add policy network indicator if the field is controlled by policy.

Bug: 877424
Change-Id: Icfdb6d7fb3deb09696b6d2edce27d3c9851043a2
Reviewed-on: https://chromium-review.googlesource.com/c/1251447
Commit-Queue: Nikita Podguzov <nikitapodguzov@google.com>
Reviewed-by: default avatarSteven Bennetts <stevenjb@chromium.org>
Reviewed-by: default avatarAlexander Hendrich <hendrich@chromium.org>
Cr-Commit-Position: refs/heads/master@{#600735}
parent be9b6eb4
......@@ -55,12 +55,12 @@
</style>
<cr-dialog id="dialog" no-cancel>
<div slot="title">[[getDialogTitle_(networkProperties_)]]</div>
<div slot="title">[[getDialogTitle_(managedProperties_)]]</div>
<div slot="body">
<network-config id="networkConfig" class="flex"
networking-private="[[networkingPrivate]]"
global-policy="[[globalPolicy_]]"
network-properties="{{networkProperties_}}"
managed-properties="{{managedProperties_}}"
enable-connect="{{enableConnect_}}"
share-allow-enable="[[shareAllowEnable_]]"
share-default="[[shareDefault_]]"
......
......@@ -55,9 +55,9 @@ Polymer({
* The current properties if an existing network is being configured, or
* a minimal subset for a new network. Note: network-config may modify
* this (specifically .name).
* @type {!chrome.networkingPrivate.NetworkProperties}
* @type {!chrome.networkingPrivate.ManagedProperties}
*/
networkProperties_: Object,
managedProperties_: Object,
/**
* Set by network-config when a configuration error occurs.
......@@ -85,9 +85,9 @@ Polymer({
this.guid_ = params.get('guid') || '';
}
this.networkProperties_ = {
this.managedProperties_ = {
GUID: this.guid_,
Name: '',
Name: {Active: ''},
Type: /** @type {chrome.networkingPrivate.NetworkType} */ (type),
};
......@@ -110,7 +110,7 @@ Polymer({
* @private
*/
getDialogTitle_: function() {
var type = this.i18n('OncType' + this.networkProperties_.Type);
var type = this.i18n('OncType' + this.managedProperties_.Type);
return this.i18n('internetJoinType', type);
},
......
......@@ -24,12 +24,12 @@
</style>
<cr-dialog id="dialog" close-text="$i18n{close}">
<div slot="title">[[getDialogTitle_(networkProperties_)]]</div>
<div slot="title">[[getDialogTitle_(managedProperties_)]]</div>
<div slot="body">
<network-config id="networkConfig" class="flex"
networking-private="[[networkingPrivate]]"
global-policy="[[globalPolicy]]"
network-properties="{{networkProperties_}}"
managed-properties="{{managedProperties_}}"
enable-connect="{{enableConnect_}}" enable-save="{{enableSave_}}"
share-allow-enable="[[shareAllowEnable_]]"
share-default="[[shareDefault_]]"
......
......@@ -69,9 +69,9 @@ Polymer({
* The current properties if an existing network is being configured, or
* a minimal subset for a new network. Note: network-config may modify
* this (specifically .name).
* @private {!chrome.networkingPrivate.NetworkProperties}
* @private {!chrome.networkingPrivate.ManagedProperties}
*/
networkProperties_: Object,
managedProperties_: Object,
/**
* Set by network-config when a configuration error occurs.
......@@ -88,12 +88,12 @@ Polymer({
if (!dialog.open)
dialog.showModal();
// Set networkProperties for new configurations and for existing
// Set managedProperties for new configurations and for existing
// configurations until the current properties are loaded.
assert(this.type && this.type != CrOnc.Type.ALL);
this.networkProperties_ = {
this.managedProperties_ = {
GUID: this.guid,
Name: this.name,
Name: {Active: this.name},
Type: this.type,
};
this.$.networkConfig.init();
......@@ -120,10 +120,11 @@ Polymer({
* @private
*/
getDialogTitle_: function() {
const name = this.networkProperties_.Name;
const name = /** @type {string} */ (
CrOnc.getActiveValue(this.managedProperties_.Name));
if (name)
return this.i18n('internetConfigName', HTMLEscape(name));
const type = this.i18n('OncType' + this.networkProperties_.Type);
const type = this.i18n('OncType' + this.managedProperties_.Type);
return this.i18n('internetJoinType', type);
},
......
......@@ -3,8 +3,12 @@
// found in the LICENSE file.
/**
* @fileoverview loadTimeData override values for ONC strings used in
* network_config.html and other network configuration UI.
* @fileoverview This file has two parts:
*
* 1. loadTimeData override values for ONC strings used in network_config.html
* and other network configuration UI.
*
* 2. Helper functions to convert and handle ONC properties for using in tests.
*/
var CrOncTest = CrOncTest || {};
......@@ -81,3 +85,30 @@ CrOncTest.overrideCrOncStrings = function() {
};
loadTimeData.overrideValues(oncKeys);
};
/**
* Converts an unmanaged ONC dictionary into a managed dictionary by
* setting properties 'Active' values to values from unmanaged dictionary.
* NOTE: Because of having not only managed variables in ManagedProperty (e.g.
* 'GUID', 'Source', 'Type', etc) this function can handle only simple
* dictionaries such as provided in network_config_test.js.
* @param {!Object|undefined} properties An unmanaged ONC dictionary
* @return {!Object|undefined} A managed version of |properties|.
*/
CrOncTest.convertToManagedProperties = function(properties) {
'use strict';
if (!properties)
return undefined;
var result = {};
var keys = Object.keys(properties);
if (typeof properties != 'object')
return {Active: properties};
for (var i = 0; i < keys.length; ++i) {
var k = keys[i];
if (['GUID', 'Source', 'Type'].includes(k))
result[k] = properties[k];
else
result[k] = this.convertToManagedProperties(properties[k]);
}
return result;
};
......@@ -116,8 +116,7 @@ cr.define('chrome', function() {
var result = this.networkStates_.find(function(state) {
return state.GUID == guid;
});
// TODO(stevenjb): Convert state to ManagedProperties.
callback(result);
callback(CrOncTest.convertToManagedProperties(result));
this.methodCalled('getManagedProperties');
},
......
......@@ -13,11 +13,12 @@ suite('network-config', function() {
CrOncTest.overrideCrOncStrings();
});
function setNetworkConfig(networkProperties) {
function setNetworkConfig(properties) {
PolymerTest.clearBody();
networkConfig = document.createElement('network-config');
networkConfig.networkingPrivate = api_;
networkConfig.networkProperties = networkProperties;
networkConfig.managedProperties =
CrOncTest.convertToManagedProperties(properties);
}
function initNetworkConfig() {
......@@ -73,8 +74,10 @@ suite('network-config', function() {
test('Default', function() {
return flushAsync().then(() => {
assertEquals('someguid', networkConfig.networkProperties.GUID);
assertEquals('somename', networkConfig.networkProperties.Name);
assertEquals('someguid', networkConfig.managedProperties.GUID);
assertEquals(
'somename',
CrOnc.getActiveValue(networkConfig.managedProperties.Name));
assertFalse(!!networkConfig.$$('#share'));
assertTrue(!!networkConfig.$$('#ssid'));
assertTrue(!!networkConfig.$$('#security'));
......@@ -225,8 +228,10 @@ suite('network-config', function() {
assertEquals('WPA-EAP', networkConfig.security_);
assertEquals(
'PEAP',
networkConfig.get(
'Ethernet.EAP.Outer', networkConfig.networkProperties));
CrOnc.getActiveValue(
/** @type {chrome.networkingPrivate.ManagedDOMString|undefined} */
(networkConfig.get(
'Ethernet.EAP.Outer', networkConfig.managedProperties))));
let outer = networkConfig.$$('#outer');
assertTrue(!!outer);
assertTrue(!outer.disabled);
......
......@@ -1391,6 +1391,7 @@ CrSettingsInternetPageTest.prototype = {
ROOT_PATH + 'ui/webui/resources/js/assert.js',
'../fake_chrome_event.js',
'../chromeos/fake_networking_private.js',
'../chromeos/cr_onc_strings.js',
'internet_page_tests.js',
]),
};
......@@ -1419,6 +1420,7 @@ CrSettingsInternetDetailPageTest.prototype = {
ROOT_PATH + 'ui/webui/resources/js/util.js',
'../fake_chrome_event.js',
'../chromeos/fake_networking_private.js',
'../chromeos/cr_onc_strings.js',
'internet_detail_page_tests.js',
]),
};
......
......@@ -9,7 +9,9 @@ js_type_check("closure_compile") {
":network_apnlist",
":network_choose_mobile",
":network_config",
":network_config_input",
":network_config_select",
":network_config_toggle",
":network_ip_config",
":network_nameservers",
":network_password_input",
......@@ -48,8 +50,25 @@ js_library("network_config") {
extra_sources = [ "$interfaces_path/networking_private_interface.js" ]
}
js_library("network_config_element_behavior") {
deps = [
"//ui/webui/resources/cr_elements/chromeos/network:cr_onc_types",
]
}
js_library("network_config_input") {
deps = [
":network_config_element_behavior",
"//ui/webui/resources/cr_elements/policy:cr_policy_network_behavior",
]
externs_list = [ "$externs_path/networking_private.js" ]
extra_sources = [ "$interfaces_path/networking_private_interface.js" ]
}
js_library("network_config_select") {
deps = [
":network_config_element_behavior",
"//ui/webui/resources/cr_elements/policy:cr_policy_network_behavior",
"//ui/webui/resources/js:assert",
"//ui/webui/resources/js:i18n_behavior",
]
......@@ -57,6 +76,15 @@ js_library("network_config_select") {
extra_sources = [ "$interfaces_path/networking_private_interface.js" ]
}
js_library("network_config_toggle") {
deps = [
":network_config_element_behavior",
"//ui/webui/resources/cr_elements/policy:cr_policy_network_behavior",
]
externs_list = [ "$externs_path/networking_private.js" ]
extra_sources = [ "$interfaces_path/networking_private_interface.js" ]
}
js_library("network_ip_config") {
deps = [
"//ui/webui/resources/cr_elements/chromeos/network:cr_onc_types",
......@@ -73,8 +101,12 @@ js_library("network_nameservers") {
js_library("network_password_input") {
deps = [
":network_config_element_behavior",
"//ui/webui/resources/cr_elements/policy:cr_policy_network_behavior",
"//ui/webui/resources/js:i18n_behavior",
]
externs_list = [ "$externs_path/networking_private.js" ]
extra_sources = [ "$interfaces_path/networking_private_interface.js" ]
}
js_library("network_property_list") {
......
......@@ -97,7 +97,7 @@ Polymer({
apn = cellular.APN;
if (apn && apn.AccessPointName) {
activeApn = /** @type {!CrOnc.APNProperties|undefined} */ (
CrOnc.getSimpleActiveProperties(apn));
CrOnc.getActiveProperties(apn));
} else if (cellular.LastGoodAPN && cellular.LastGoodAPN.AccessPointName) {
activeApn = cellular.LastGoodAPN;
}
......
<link rel="import" href="chrome://resources/cr_elements/chromeos/network/cr_onc_types.html">
<script src="network_config_element_behavior.js"></script>
// Copyright 2018 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 Behavior for network config elements.
*/
/** @polymerBehavior */
var NetworkConfigElementBehavior = {
properties: {
disabled: {
type: Boolean,
value: false,
reflectToAttribute: true,
},
/**
* Network managed property associated with the config element.
* @type {?CrOnc.ManagedProperty}
*/
property: {
type: Object,
value: null,
},
},
/**
* @param {boolean} disabled
* @param {?CrOnc.ManagedProperty} property
* @return {boolean} True if the element should be disabled.
* @private
*/
getDisabled_: function(disabled, property) {
return disabled || (!!property && this.isNetworkPolicyEnforced(property));
},
};
<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.html">
<link rel="import" href="chrome://resources/cr_elements/policy/cr_policy_network_indicator.html">
<link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
<link rel="import" href="network_config_element_behavior.html">
<link rel="import" href="network_shared_css.html">
<dom-module id="network-config-input">
<template>
<style include="network-shared">
#container {
align-items: center;
display: flex;
flex-direction: row;
}
cr-input {
width: 100%;
}
cr-policy-network-indicator {
--cr-tooltip-icon-margin-start: var(--cr-controlled-by-spacing);
}
</style>
<div id="container">
<cr-input label="[[label]]" value="{{value}}"
hidden="[[hidden]]" readonly="[[readonly]]"
disabled="[[getDisabled_(disabled, property)]]">
</cr-input>
<cr-policy-network-indicator
property="[[property]]" tooltip-position="left">
</cr-policy-network-indicator>
</div>
</template>
<script src="network_config_input.js"></script>
</dom-module>
// Copyright 2018 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 network configuration input fields.
*/
Polymer({
is: 'network-config-input',
behaviors: [CrPolicyNetworkBehavior, NetworkConfigElementBehavior],
properties: {
label: String,
hidden: {
type: Boolean,
reflectToAttribute: true,
},
readonly: {
type: Boolean,
reflectToAttribute: true,
},
value: {
type: String,
notify: true,
},
},
focus: function() {
this.$$('cr-input').focus();
},
});
<link rel="import" href="chrome://resources/html/polymer.html">
<link rel="import" href="chrome://resources/cr_elements/policy/cr_policy_network_behavior.html">
<link rel="import" href="chrome://resources/cr_elements/policy/cr_policy_network_indicator.html">
<link rel="import" href="chrome://resources/cr_elements/policy/cr_tooltip_icon.html">
<link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
<link rel="import" href="chrome://resources/html/md_select_css.html">
<link rel="import" href="network_config_element_behavior.html">
<link rel="import" href="network_shared_css.html">
<dom-module id="network-config-select">
......@@ -24,19 +28,35 @@
margin-bottom: var(--cr-form-field-bottom-spacing);
padding: 0;
}
#inner {
align-items: center;
display: flex;
flex-direction: row;
}
cr-policy-network-indicator {
--cr-tooltip-icon-margin-start: var(--cr-controlled-by-spacing);
}
</style>
<div id="outer">
<div id="label">[[label]]</div>
<select class="md-select" disabled="[[disabled]]"
value="{{value::change}}" aria-label$="[[label]]">
<template is="dom-repeat" items="[[items]]">
<option value="[[getItemValue_(item)]]"
disabled="[[!getItemEnabled_(item)]]">
[[getItemLabel_(item, oncPrefix)]]
</option>
</template>
</select>
<div id="inner">
<select class="md-select"
disabled="[[getDisabled_(disabled, property)]]"
value="{{value::change}}" aria-label$="[[label]]">
<template is="dom-repeat" items="[[items]]">
<option value="[[getItemValue_(item)]]"
disabled="[[!getItemEnabled_(item)]]">
[[getItemLabel_(item, oncPrefix)]]
</option>
</template>
</select>
<cr-policy-network-indicator
property="[[property]]" tooltip-position="left">
</cr-policy-network-indicator>
</div>
</div>
</template>
......
......@@ -8,16 +8,15 @@
Polymer({
is: 'network-config-select',
behaviors: [I18nBehavior],
behaviors: [
I18nBehavior,
CrPolicyNetworkBehavior,
NetworkConfigElementBehavior,
],
properties: {
label: String,
disabled: {
type: Boolean,
reflectToAttribute: true,
},
/** Set to true if |items| is a list of certificates. */
certList: Boolean,
......
<link rel="import" href="chrome://resources/html/polymer.html">
<link rel="import" href="chrome://resources/cr_elements/cr_toggle/cr_toggle.html">
<link rel="import" href="chrome://resources/cr_elements/policy/cr_policy_network_behavior.html">
<link rel="import" href="chrome://resources/cr_elements/policy/cr_policy_network_indicator.html">
<link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
<link rel="import" href="network_config_element_behavior.html">
<link rel="import" href="network_shared_css.html">
<dom-module id="network-config-toggle">
<template>
<style include="network-shared">
cr-policy-network-indicator {
--cr-tooltip-icon-margin-start: var(--cr-controlled-by-spacing);
}
</style>
<div class="property-box">
<div class="start">
[[label]]
</div>
<cr-toggle checked="{{checked}}"
disabled="[[getDisabled_(disabled, property)]]"
aria-label$="[[label]]">
</cr-toggle>
<cr-policy-network-indicator
property="[[property]]" tooltip-position="left">
</cr-policy-network-indicator>
</div>
</template>
<script src="network_config_toggle.js"></script>
</dom-module>
// Copyright 2018 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 network configuration toggle.
*/
Polymer({
is: 'network-config-toggle',
behaviors: [CrPolicyNetworkBehavior, NetworkConfigElementBehavior],
properties: {
label: String,
checked: {
type: Boolean,
value: false,
reflectToAttribute: true,
notify: true,
},
},
});
<link rel="import" href="chrome://resources/html/polymer.html">
<link rel="import" href="chrome://resources/cr_elements/cr_icons_css.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.html">
<link rel="import" href="chrome://resources/cr_elements/policy/cr_policy_network_indicator.html">
<link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
<link rel="import" href="chrome://resources/html/i18n_behavior.html">
<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html">
<link rel="import" href="network_config_element_behavior.html">
<link rel="import" href="network_shared_css.html">
<dom-module id="network-password-input">
<template>
<style include="network-shared">
#container {
align-items: center;
display: flex;
flex-direction: row;
}
cr-input {
width: 100%;
}
paper-icon-button-light {
margin: 0;
width: var(--network-control-margin);
cr-policy-network-indicator {
--cr-tooltip-icon-margin-start: var(--cr-controlled-by-spacing);
}
</style>
<cr-input id="input" label="[[label]]" value="{{value}}"
disabled="[[disabled]]" type="[[getInputType_(showPassword)]]"
on-keypress="onInputKeypress_">
<paper-icon-button-light id="icon" slot="suffix"
class$="[[getIconClass_(showPassword)]]">
<button on-tap="onShowPasswordTap_"
title="[[getShowPasswordTitle_(showPassword)]]">
</button>
</paper-icon-button-light>
</cr-input>
<div id="container">
<cr-input id="input" label="[[label]]" value="{{value}}"
disabled="[[getDisabled_(disabled, property)]]"
type="[[getInputType_(showPassword)]]" on-keypress="onInputKeypress_">
</cr-input>
<template is="dom-if" if="[[!getDisabled_(disabled, property)]]" restamp>
<paper-icon-button-light id="icon" slot="suffix"
class$="[[getIconClass_(showPassword)]]">
<button on-tap="onShowPasswordTap_"
title="[[getShowPasswordTitle_(showPassword)]]">
</button>
</paper-icon-button-light>
</template>
<template is="dom-if" if="[[getDisabled_(disabled, property)]]" restamp>
<cr-policy-network-indicator
property="[[property]]" tooltip-position="left">
</cr-policy-network-indicator>
</template>
</div>
</template>
<script src="network_password_input.js"></script>
</dom-module>
......@@ -8,7 +8,11 @@
Polymer({
is: 'network-password-input',
behaviors: [I18nBehavior],
behaviors: [
I18nBehavior,
CrPolicyNetworkBehavior,
NetworkConfigElementBehavior,
],
properties: {
label: {
......@@ -16,11 +20,6 @@ Polymer({
reflectToAttribute: true,
},
disabled: {
type: Boolean,
reflectToAttribute: true,
},
value: {
type: String,
notify: true,
......
......@@ -168,23 +168,22 @@ Polymer({
proxy.Type = /** @type {!CrOnc.ProxySettingsType} */ (
CrOnc.getActiveValue(proxySettings.Type));
if (proxySettings.Manual) {
proxy.Manual.HTTPProxy = /** @type {!CrOnc.ProxyLocation|undefined} */ (
CrOnc.getSimpleActiveProperties(
proxySettings.Manual.HTTPProxy)) ||
proxy.Manual.HTTPProxy =
/** @type {!CrOnc.ProxyLocation|undefined} */ (
CrOnc.getActiveProperties(proxySettings.Manual.HTTPProxy)) ||
{Host: '', Port: 80};
proxy.Manual.SecureHTTPProxy =
/** @type {!CrOnc.ProxyLocation|undefined} */ (
CrOnc.getSimpleActiveProperties(
CrOnc.getActiveProperties(
proxySettings.Manual.SecureHTTPProxy)) ||
{Host: '', Port: 80};
proxy.Manual.FTPProxy =
/** @type {!CrOnc.ProxyLocation|undefined} */ (
CrOnc.getSimpleActiveProperties(
proxySettings.Manual.FTPProxy)) ||
CrOnc.getActiveProperties(proxySettings.Manual.FTPProxy)) ||
{Host: '', Port: 80};
proxy.Manual.SOCKS =
/** @type {!CrOnc.ProxyLocation|undefined} */ (
CrOnc.getSimpleActiveProperties(proxySettings.Manual.SOCKS)) ||
CrOnc.getActiveProperties(proxySettings.Manual.SOCKS)) ||
{Host: '', Port: 80};
var jsonHttp = proxy.Manual.HTTPProxy;
this.useSameProxy_ =
......
......@@ -269,15 +269,27 @@ CrOnc.getStateOrActiveString = function(property) {
return /** @type {string} */ (CrOnc.getActiveValue(property));
};
/**
* Return if the property is simple, i.e. doesn't contain any nested
* dictionaries.
* @param property {!Object|undefined}
* @return {boolean}
*/
CrOnc.isSimpleProperty = function(property) {
for (var prop of ['Active', 'Effective', 'UserSetting', 'SharedSetting']) {
if (prop in property)
return true;
}
return false;
};
/**
* Converts a managed ONC dictionary into an unmanaged dictionary (i.e. a
* dictionary of active values).
* NOTE: This is not intended to be used with dictionaries that contain
* nested dictionaries. This will fail and return undefined in that case.
* @param {!Object|undefined} properties A managed ONC dictionary
* @return {!Object|undefined} An unmanaged version of |properties|.
*/
CrOnc.getSimpleActiveProperties = function(properties) {
CrOnc.getActiveProperties = function(properties) {
'use strict';
if (!properties)
return undefined;
......@@ -285,14 +297,24 @@ CrOnc.getSimpleActiveProperties = function(properties) {
var keys = Object.keys(properties);
for (var i = 0; i < keys.length; ++i) {
var k = keys[i];
var prop = CrOnc.getActiveValue(properties[k]);
if (prop == undefined) {
var property = properties[k];
// Skip policy properties with no effective value.
// TODO(nikitapodguzov@ / raleksandrov@): Remove this when crbug.com/888959
// providing dummy values for password fields will be fixed.
if ('Effective' in property && !(property.Effective in property))
continue;
var propertyValue;
if (CrOnc.isSimpleProperty(property))
propertyValue = CrOnc.getActiveValue(property);
else
propertyValue = CrOnc.getActiveProperties(property);
if (propertyValue == undefined) {
console.error(
'getSimpleActiveProperties called on invalid ONC object: ' +
'getActiveProperties called on invalid ONC object: ' +
JSON.stringify(properties));
return undefined;
}
result[k] = prop;
result[k] = propertyValue;
}
return result;
};
......@@ -324,7 +346,7 @@ CrOnc.getIPConfigForType = function(properties, type) {
var staticIpConfig =
/** @type {!CrOnc.IPConfigProperties|undefined} */ (
CrOnc.getSimpleActiveProperties(properties.StaticIPConfig));
CrOnc.getActiveProperties(properties.StaticIPConfig));
if (!staticIpConfig)
return ipConfig;
......
......@@ -7,9 +7,23 @@
<dom-module id="cr-policy-network-indicator">
<template>
<style include="cr-hidden-style"></style>
<style include="cr-hidden-style">
/* This field is used for controlling margin of icon outside the indicator
* element (i.e. in the element which uses indicator itself). It's useful
* when we don't want to add margin to indicator if it's hidden and also
* don't want to move/duplicate logic about showing indicator and margin
* outside of indicator element. */
:host {
--cr-tooltip-icon-margin-start: 0;
}
cr-tooltip-icon {
margin-inline-start: var(--cr-tooltip-icon-margin-start);
}
</style>
<cr-tooltip-icon hidden$="[[!indicatorVisible]]"
tooltip-text="[[indicatorTooltip_]]" icon-class="[[indicatorIcon]]">
tooltip-text="[[indicatorTooltip_]]" icon-class="[[indicatorIcon]]"
tooltip-position="[[tooltipPosition]]">
</cr-tooltip-icon>
</template>
<script src="cr_policy_network_indicator.js"></script>
......
......@@ -15,10 +15,13 @@ Polymer({
properties: {
/**
* Network property associated with the indicator.
* @type {!CrOnc.ManagedProperty|undefined}
* @type {?CrOnc.ManagedProperty|undefined}
*/
property: Object,
/** Position of tooltip popup related to the policy indicator. */
tooltipPosition: String,
/**
* Recommended value for non enforced properties.
* @private {!CrOnc.NetworkPropertyType|undefined}
......@@ -37,7 +40,7 @@ Polymer({
/** @private */
propertyChanged_: function() {
var property = this.property;
if (!this.isControlled(property)) {
if (property == null || !this.isControlled(property)) {
this.indicatorType = CrPolicyIndicatorType.NONE;
return;
}
......
......@@ -23,7 +23,7 @@
</style>
<iron-icon id="indicator" tabindex="0" aria-label$="[[iconAriaLabel]]"
aria-describedby="tooltip" icon="[[iconClass]]"></iron-icon>
<paper-tooltip id="tooltip" for="indicator" position="top"
<paper-tooltip id="tooltip" for="indicator" position="[[tooltipPosition]]"
fit-to-visible-bounds>
[[tooltipText]]
</paper-tooltip>
......
......@@ -4,10 +4,19 @@
Polymer({
is: 'cr-tooltip-icon',
properties: {
iconAriaLabel: String,
iconClass: String,
tooltipText: String,
/** Position of tooltip popup related to the icon. */
tooltipPosition: {
type: String,
value: 'top',
}
},
/** @return {!Element} */
......
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