Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(5449)

Unified Diff: chrome/browser/resources/policy.js

Issue 12084065: Convert chrome://policy to new WebUI style (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebased. Created 7 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chrome/browser/resources/policy.html ('k') | chrome/browser/ui/webui/policy_ui.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/browser/resources/policy.js
diff --git a/chrome/browser/resources/policy.js b/chrome/browser/resources/policy.js
index 064a6c5fc774f39a5d6f218ad742fdb4aac46cc4..2c52c616df0a8bdd2f65ce6209243f31ebc0ec81 100644
--- a/chrome/browser/resources/policy.js
+++ b/chrome/browser/resources/policy.js
@@ -1,277 +1,422 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Copyright (c) 2013 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.
-/**
- * This variable structure is here to document the structure that the template
- * expects to correctly populate the page.
- */
-var policyDataFormat = {
- // Whether any of the policies in 'policies' have a value.
- 'anyPoliciesSet': true,
-
- 'policies': [
- {
- 'level': 'managed',
- 'name': 'AllowXYZ',
- 'set': true,
- 'scope': 'Machine',
- 'status': 'ok',
- 'value': true
- }
- ],
- 'status': {
- 'deviceFetchInterval': '8min',
- 'deviceId': 'D2AC39A2-3C8FC-E2C0-E45D2DC3782C',
- 'deviceLastFetchTime': '9:50 PM',
- 'devicePolicyDomain': 'google.com',
- 'deviceStatusMessage': 'OK',
- 'displayDeviceStatus': true,
- 'displayStatusSection': true,
- 'displayUserStatus': true,
- 'user': 'simo@google.com',
- 'userFetchInterval': '8min',
- 'userId': 'D2AC39A2-3C8FC-E2C0-E45D2DC3782C',
- 'userLastFetchTime': '9:50 PM',
- 'userStatusMessage': 'OK'
- }
-};
-
-cr.define('policies', function() {
+cr.define('policy', function() {
+ /**
+ * A box that shows the status of cloud policy for a device or user.
+ * @constructor
+ * @extends {HTMLFieldSetElement}
+ */
+ var StatusBox = cr.ui.define(function() {
+ var node = $('status-box-template').cloneNode(true);
+ node.removeAttribute('id');
+ return node;
+ });
- function Policy() {
- }
+ StatusBox.prototype = {
+ // Set up the prototype chain.
+ __proto__: HTMLFieldSetElement.prototype,
- cr.addSingletonGetter(Policy);
+ /**
+ * Initialization function for the cr.ui framework.
+ */
+ decorate: function() {
+ },
- Policy.prototype = {
/**
- * True if none of the received policies are actually set, false otherwise.
- * @type {boolean}
+ * Populate the box with the given cloud policy status.
+ * @param {string} scope The policy scope, either "device" or "user".
+ * @param {Object} status Dictionary with information about the status.
*/
- noActivePolicies_: false,
+ initialize: function(scope, status) {
+ if (scope == 'device') {
+ // For device policy, set the appropriate title and populate the topmost
+ // status item with the domain the device is enrolled into.
+ this.querySelector('.legend').textContent =
+ loadTimeData.getString('statusDevice');
+ var domain = this.querySelector('.domain');
+ domain.textContent = status.domain;
+ domain.parentElement.hidden = false;
+ } else {
+ // For user policy, set the appropriate title and populate the topmost
+ // status item with the username that policies apply to.
+ this.querySelector('.legend').textContent =
+ loadTimeData.getString('statusUser');
+ // Populate the topmost item with the username.
+ var username = this.querySelector('.username');
+ username.textContent = status.username;
+ username.parentElement.hidden = false;
+ }
+ // Populate all remaining items.
+ this.querySelector('.client-id').textContent = status.clientId || '';
+ this.querySelector('.time-since-last-refresh').textContent =
+ status.timeSinceLastRefresh || '';
+ this.querySelector('.refresh-interval').textContent =
+ status.refreshInterval || '';
+ this.querySelector('.status').textContent = status.status || '';
+ },
+ };
+
+ /**
+ * A single policy's entry in the policy table.
+ * @constructor
+ * @extends {HTMLTableSectionElement}
+ */
+ var Policy = cr.ui.define(function() {
+ var node = $('policy-template').cloneNode(true);
+ node.removeAttribute('id');
+ return node;
+ });
+
+ Policy.prototype = {
+ // Set up the prototype chain.
+ __proto__: HTMLTableSectionElement.prototype,
/**
- * The current search term for filtering of the policy table.
- * @type {string}
- * @private
+ * Initialization function for the cr.ui framework.
*/
- searchTerm_: '',
+ decorate: function() {
+ this.updateToggleExpandedValueText_();
+ this.querySelector('.toggle-expanded-value').addEventListener(
+ 'click', this.toggleExpandedValue_.bind(this));
+ },
/**
- * Takes the |policyData| argument and populates the page with this data. It
- * expects an object structure like the policyDataFormat above.
- * @param {Object} policyData Detailed info about policies.
+ * Populate the table columns with information about the policy name, value
+ * and status.
+ * @param {string} name The policy name.
+ * @param {Object} value Dictionary with information about the policy value.
+ * @param {boolean} unknown Whether the policy name is not recognized.
*/
- renderTemplate: function(policyData) {
- this.noActivePolicies_ = !policyData.anyPoliciesSet;
-
- if (this.noActivePolicies_)
- $('no-policies').hidden = false;
- if (policyData.status.displayStatusSection)
- $('status-section').hidden = false;
-
- // This is the javascript code that processes the template:
- var input = new JsEvalContext(policyData);
- var output = $('data-template');
- jstProcess(input, output);
-
- var toggles = document.querySelectorAll('.policy-set * .toggler');
- for (var i = 0; i < toggles.length; i++) {
- toggles[i].hidden = true;
- toggles[i].onclick = function() {
- Policy.getInstance().toggleCellExpand_(this);
- };
+ initialize: function(name, value, unknown) {
+ this.name = name;
+ this.unset = !value;
+
+ // Populate the name column.
+ this.querySelector('.name').textContent = name;
+
+ // Populate the remaining columns with policy scope, level and value if a
+ // value has been set. Otherwise, leave them blank.
+ if (value) {
+ this.querySelector('.scope').textContent =
+ loadTimeData.getString(value.scope == 'user' ?
+ 'scopeUser' : 'scopeDevice');
+ this.querySelector('.level').textContent =
+ loadTimeData.getString(value.level == 'recommended' ?
+ 'levelRecommended' : 'levelMandatory');
+ this.querySelector('.value').textContent = value.value;
+ this.querySelector('.expanded-value').textContent = value.value;
}
- var containers = document.querySelectorAll('.text-container');
- for (var i = 0; i < containers.length; i++)
- this.initTextContainer_(containers[i]);
+ // Populate the status column.
+ var status;
+ if (!value) {
+ // If the policy value has not been set, show an error message.
+ status = loadTimeData.getString('unset');
+ } else if (unknown) {
+ // If the policy name is not recognized, show an error message.
+ status = loadTimeData.getString('unknown');
+ } else if (value.error) {
+ // If an error occurred while parsing the policy value, show the error
+ // message.
+ status = value.error;
+ } else {
+ // Otherwise, indicate that the policy value was parsed correctly.
+ status = loadTimeData.getString('ok');
+ }
+ this.querySelector('.status').textContent = status;
},
/**
- * Filters the table of policies by name.
- * @param {string} term The search string.
+ * Check the table columns for overflow. Most columns are automatically
+ * elided when overflow occurs. The only action required is to add a tooltip
+ * that shows the complete content. The value column is an exception. If
+ * overflow occurs here, the contents is replaced with a link that toggles
+ * the visibility of an additional row containing the complete value.
*/
- filterTable: function(term) {
- this.searchTerm_ = term.toLowerCase();
- var table = $('policy-table');
- var showUnsent = $('toggle-unsent-policies').checked;
- for (var r = 1; r < table.rows.length; r++) {
- var row = table.rows[r];
-
- // Don't change visibility of policies that aren't set if the checkbox
- // isn't checked.
- if (!showUnsent && row.className == 'policy-unset')
- continue;
-
- var nameCell = row.querySelector('.policy-name');
- var cellContents = nameCell.textContent;
- row.hidden =
- !(cellContents.toLowerCase().indexOf(this.searchTerm_) >= 0);
+ checkOverflow: function() {
+ // Set a tooltip on all overflowed columns except the value column.
+ var divs = this.querySelectorAll('div.elide');
+ for (var i = 0; i < divs.length; i++) {
+ var div = divs[i];
+ div.title = div.offsetWidth < div.scrollWidth ? div.textContent : '';
}
+
+ // Cache the width of the value column's contents when it is first shown.
+ // This is required to be able to check whether the contents would still
+ // overflow the column once it has been hidden and replaced by a link.
+ var valueContainer = this.querySelector('.value-container');
+ if (valueContainer.valueWidth == undefined) {
+ valueContainer.valueWidth =
+ valueContainer.querySelector('.value').offsetWidth;
+ }
+
+ // Determine whether the contents of the value column overflows. The
+ // visibility of the contents, replacement link and additional row
+ // containing the complete value that depend on this are handled by CSS.
+ this.classList.toggle(
+ 'has-overflowed-value',
+ valueContainer.offsetWidth < valueContainer.valueWidth);
},
/**
- * Updates the visibility of the policies depending on the state of the
- * 'toggle-unsent-policies' checkbox.
+ * Update the text of the link that toggles the visibility of an additional
+ * row containing the complete policy value, depending on the toggle state.
+ * @private
*/
- updatePolicyVisibility: function() {
- if ($('toggle-unsent-policies').checked)
- $('policies').style.display = '';
- else if (this.noActivePolicies_)
- $('policies').style.display = 'none';
-
- var tableRows = document.getElementsByClassName('policy-unset');
- for (var i = 0; i < tableRows.length; i++)
- tableRows[i].hidden = !($('toggle-unsent-policies').checked);
-
- // Filter table again in case a search was active.
- this.filterTable(this.searchTerm_);
+ updateToggleExpandedValueText_: function(event) {
+ this.querySelector('.toggle-expanded-value').textContent =
+ loadTimeData.getString(
+ this.classList.contains('show-overflowed-value') ?
+ 'hideExpandedValue' : 'showExpandedValue');
},
/**
- * Expands or collapses a table cell that has overflowing text.
- * @param {Object} toggler The toggler that was clicked on.
+ * Toggle the visibility of an additional row containing the complete policy
+ * value.
* @private
*/
- toggleCellExpand_: function(toggler) {
- var textContainer = toggler.parentElement;
- textContainer.collapsed = !textContainer.collapsed;
-
- if (textContainer.collapsed)
- this.collapseCell_(textContainer);
- else
- this.expandCell_(textContainer);
+ toggleExpandedValue_: function() {
+ this.classList.toggle('show-overflowed-value');
+ this.updateToggleExpandedValueText_();
},
+ };
+
+ /**
+ * A table of policies and their values.
+ * @constructor
+ * @extends {HTMLTableSectionElement}
+ */
+ var PolicyTable = cr.ui.define('tbody');
+
+ PolicyTable.prototype = {
+ // Set up the prototype chain.
+ __proto__: HTMLTableSectionElement.prototype,
/**
- * Collapses all expanded table cells and updates the visibility of the
- * toggles accordingly. Should be called before the policy information in
- * the table is updated.
+ * Initialization function for the cr.ui framework.
*/
- collapseExpandedCells: function() {
- var textContainers = document.querySelectorAll('.text-expanded');
- for (var i = 0; i < textContainers.length; i++)
- this.collapseCell_(textContainers[i]);
+ decorate: function() {
+ this.policies_ = {};
+ this.filterPattern_ = '';
+ window.addEventListener('resize', this.checkOverflow_.bind(this));
},
/**
- * Expands a table cell so that all the text it contains is visible.
- * @param {Object} textContainer The cell's div element that contains the
- * text.
- * @private
+ * Initialize the list of all known policies.
+ * @param {Object} names Dictionary containing all known policy names.
*/
- expandCell_: function(textContainer) {
- textContainer.classList.remove('text-collapsed');
- textContainer.classList.add('text-expanded');
- textContainer.querySelector('.expand').hidden = true;
- textContainer.querySelector('.collapse').hidden = false;
+ setPolicyNames: function(names) {
+ this.policies_ = names;
+ this.setPolicyValues({});
},
/**
- * Collapses a table cell so that overflowing text is hidden.
- * @param {Object} textContainer The cell's div element that contains the
- * text.
- * @private
+ * Populate the table with the currently set policy values and any errors
+ * detected while parsing these.
+ * @param {Object} values Dictionary containing the current policy values.
+ */
+ setPolicyValues: function(values) {
+ // Remove all policies from the table.
+ var policies = this.getElementsByTagName('tbody');
+ while (policies.length > 0)
+ this.removeChild(policies.item(0));
+
+ // First, add known policies whose value is currently set.
+ var unset = [];
+ for (var name in this.policies_) {
+ if (name in values)
+ this.setPolicyValue_(name, values[name], false);
+ else
+ unset.push(name);
+ }
+
+ // Second, add policies whose value is currently set but whose name is not
+ // recognized.
+ for (var name in values) {
+ if (!(name in this.policies_))
+ this.setPolicyValue_(name, values[name], true);
+ }
+
+ // Finally, add known policies whose value is not currently set.
+ for (var i = 0; i < unset.length; i++)
+ this.setPolicyValue_(unset[i], undefined, false);
+
+ // Filter the policies.
+ this.filter();
+ },
+
+ /**
+ * Set the filter pattern. Only policies whose name contains |pattern| are
+ * shown in the policy table. The filter is case insensitive. It can be
+ * disabled by setting |pattern| to an empty string.
+ * @param {string} pattern The filter pattern.
+ */
+ setFilterPattern: function(pattern) {
+ this.filterPattern_ = pattern.toLowerCase();
+ this.filter();
+ },
+
+ /**
+ * Filter policies. Only policies whose name contains the filter pattern are
+ * shown in the table. Furthermore, policies whose value is not currently
+ * set are only shown if the corresponding checkbox is checked.
*/
- collapseCell_: function(textContainer) {
- textContainer.classList.remove('text-expanded');
- textContainer.classList.add('text-collapsed');
- textContainer.querySelector('.expand').hidden = false;
- textContainer.querySelector('.collapse').hidden = true;
+ filter: function() {
+ var showUnset = $('show-unset').checked;
+ var policies = this.getElementsByTagName('tbody');
+ for (var i = 0; i < policies.length; i++) {
+ var policy = policies[i];
+ policy.hidden =
+ policy.unset && !showUnset ||
+ policy.name.toLowerCase().indexOf(this.filterPattern_) == -1;
+ }
+ this.parentElement.classList.toggle(
+ 'empty', !this.querySelector('tbody:not([hidden])'));
+ setTimeout(this.checkOverflow_.bind(this), 0);
},
/**
- * Initializes a text container, showing the expand toggle if necessary.
- * @param {Object} textContainer The text container element.
+ * Check the table columns for overflow.
+ * @private
*/
- initTextContainer_: function(textContainer) {
- textContainer.collapsed = true;
- var textValue = textContainer.querySelector('.text-value');
-
- // If the text is wider than the text container, the expand toggler should
- // appear.
- if (textContainer.offsetWidth < textValue.offsetWidth ||
- textContainer.offsetHeight < textValue.offsetHeight) {
- this.collapseCell_(textContainer);
+ checkOverflow_: function() {
+ var policies = this.getElementsByTagName('tbody');
+ for (var i = 0; i < policies.length; i++) {
+ if (!policies[i].hidden)
+ policies[i].checkOverflow();
}
- }
+ },
+
+ /**
+ * Add a policy with the given |name| and |value| to the table.
+ * @param {string} name The policy name.
+ * @param {Object} value Dictionary with information about the policy value.
+ * @param {boolean} unknown Whether the policy name is not recoginzed.
+ * @private
+ */
+ setPolicyValue_: function(name, value, unknown) {
+ var policy = new Policy;
+ policy.initialize(name, value, unknown);
+ this.appendChild(policy);
+ },
};
/**
- * Asks the C++ PolicyUIHandler to get details about policies and status
- * information. The PolicyUIHandler should reply to returnData() (below).
+ * A singelton object that handles communication between browser and WebUI.
+ * @constructor
*/
- Policy.requestData = function() {
- chrome.send('requestData');
- };
+ function Page() {
+ }
+
+ // Make Page a singleton.
+ cr.addSingletonGetter(Page);
/**
- * Called by the C++ PolicyUIHandler when it has the requested data.
- * @param {Object} policyData The policy information in the format described
- * by the policyDataFormat.
+ * Provide a list of all known policies to the UI. Called by the browser on
+ * page load.
+ * @param {Object} names Dictionary containing all known policy names.
*/
- Policy.returnData = function(policyData) {
- var policy = Policy.getInstance();
- policy.collapseExpandedCells();
- policy.renderTemplate(policyData);
- policy.updatePolicyVisibility();
+ Page.setPolicyNames = function(names) {
+ this.getInstance().policyTable.setPolicyNames(names);
};
/**
- * Called by the C++ PolicyUIHandler when a requested policy refresh has
- * completed.
+ * Provide a list of the currently set policy values and any errors detected
+ * while parsing these to the UI. Called by the browser on page load and
+ * whenever policy values change.
+ * @param {Object} values Dictionary containing the current policy values.
*/
- Policy.refreshDone = function() {
- $('fetch-policies-button').disabled = false;
+ Page.setPolicyValues = function(values) {
+ this.getInstance().policyTable.setPolicyValues(values);
};
/**
- * Asks the C++ PolicyUIHandler to re-fetch policy information.
+ * Provide the current cloud policy status to the UI. Called by the browser on
+ * page load if cloud policy is present and whenever the status changes.
+ * @param {Object} status Dictionary containing the current policy status.
*/
- Policy.triggerPolicyFetch = function() {
- chrome.send('fetchPolicy');
+ Page.setStatus = function(status) {
+ this.getInstance().setStatus(status);
};
/**
- * Determines whether a policy should be visible or not.
- * @param {Object} policy An entry in the 'policies' array given by the above
- * PolicyDataFormat.
+ * Notify the UI that a request to reload policy values has completed. Called
+ * by the browser after a request to reload policy has been sent by the UI.
*/
- Policy.shouldDisplayPolicy = function(policy) {
- return $('toggle-unsent-policies').checked || policy.set;
+ Page.reloadPoliciesDone = function() {
+ this.getInstance().reloadPoliciesDone();
};
- /**
- * Initializes the page and loads the list of policies and the policy
- * status data.
- */
- Policy.initialize = function() {
- Policy.requestData();
-
- // Set HTML event handlers.
- $('fetch-policies-button').onclick = function(event) {
- this.disabled = true;
- Policy.triggerPolicyFetch();
- };
-
- $('toggle-unsent-policies').onchange = function(event) {
- Policy.getInstance().updatePolicyVisibility();
- };
-
- $('search-field').onsearch = function(event) {
- Policy.getInstance().filterTable(this.value);
- };
+ Page.prototype = {
+ /**
+ * Main initialization function. Called by the browser on page load.
+ */
+ initialize: function() {
+ uber.onContentFrameLoaded();
+ this.policyTable = $('policy-table');
+ cr.ui.decorate(this.policyTable, PolicyTable);
+
+ // Place the initial focus on the filter input field.
+ $('filter').focus();
+
+ var self = this;
+ $('filter').onsearch = function(event) {
+ self.policyTable.setFilterPattern(this.value);
+ };
+ $('reload-policies').onclick = function(event) {
+ this.disabled = true;
+ chrome.send('reloadPolicies');
+ };
+ $('show-unset').onchange = this.policyTable.filter.bind(this.policyTable);
+
+ // Notify the browser that the page has loaded, causing it to send the
+ // list of all known policies, the current policy values and the cloud
+ // policy status.
+ chrome.send('initialized');
+ },
+
+ /**
+ * Update the status section of the page to show the current cloud policy
+ * status.
+ * @param {Object} status Dictionary containing the current policy status.
+ */
+ setStatus: function(status) {
+ // Remove any existing status boxes.
+ var container = $('status-box-container');
+ while (container.firstChild)
+ container.removeChild(container.firstChild);
+ // Hide the status section.
+ var section = $('status');
+ section.hidden = true;
+
+ // Add a status box for each scope that has a cloud policy status.
+ for (var scope in status) {
+ var box = new StatusBox;
+ box.initialize(scope, status[scope]);
+ container.appendChild(box);
+ // Show the status section.
+ section.hidden = false;
+ }
+ },
+
+ /**
+ * Re-enable the reload policies button when the previous request to reload
+ * policies values has completed.
+ */
+ reloadPoliciesDone: function() {
+ $('reload-policies').disabled = false;
+ },
};
- // Export
return {
- Policy: Policy
+ Page: Page
};
});
-var Policy = policies.Policy;
-
-// Get data and have it displayed upon loading.
-document.addEventListener('DOMContentLoaded', policies.Policy.initialize);
+// Have the main initialization function be called when the page finishes
+// loading.
+document.addEventListener(
+ 'DOMContentLoaded',
+ policy.Page.getInstance().initialize.bind(policy.Page.getInstance()));
« no previous file with comments | « chrome/browser/resources/policy.html ('k') | chrome/browser/ui/webui/policy_ui.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698