summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsimo@google.com <simo@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2011-09-14 11:43:08 +0000
committersimo@google.com <simo@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2011-09-14 11:43:08 +0000
commit78774d7afbc951c4cc3fd67a08b33bebbb861375 (patch)
treedf96d62a9a675cf1c152902b27ce096f1018ce96
parentbf11c1c58d3afb075f67d6996e97ebbd225c6856 (diff)
downloadchromium_src-78774d7afbc951c4cc3fd67a08b33bebbb861375.zip
chromium_src-78774d7afbc951c4cc3fd67a08b33bebbb861375.tar.gz
chromium_src-78774d7afbc951c4cc3fd67a08b33bebbb861375.tar.bz2
Implemented status section functionality for about:policy.
Displaying status information Fetching of policies on click Refresh of policy information when it changes BUG= TEST= Review URL: http://codereview.chromium.org/7828042 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@101061 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/app/generated_resources.grd15
-rw-r--r--chrome/browser/policy/configuration_policy_reader.cc30
-rw-r--r--chrome/browser/policy/configuration_policy_reader.h45
-rw-r--r--chrome/browser/resources/policy.css15
-rw-r--r--chrome/browser/resources/policy.html130
-rw-r--r--chrome/browser/resources/policy.js175
-rw-r--r--chrome/browser/ui/webui/policy_ui.cc171
-rw-r--r--chrome/browser/ui/webui/policy_ui.h47
8 files changed, 531 insertions, 97 deletions
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index c1a3199..98d4421 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -4232,9 +4232,15 @@ Keep your key file in a safe place. You will need it to create new versions of y
<message name="IDS_POLICY_USER_POLICIES" desc="The title for the user policies status box.">
User policies
</message>
- <message name="IDS_POLICY_ENROLLMENT_DOMAIN" desc="The label for the enrollment domain in the status boxes.">
+ <message name="IDS_POLICY_ENROLLMENT_DOMAIN" desc="The label for the enrollment domain in the device policies status box.">
Enrollment domain:
</message>
+ <message name="IDS_POLICY_CLIENT_ID" desc="The label for the client ids in the status boxes.">
+ Client Id:
+ </message>
+ <message name="IDS_POLICY_USERNAME" desc="The label for the username in the user policies status box.">
+ User:
+ </message>
<message name="IDS_POLICY_LAST_FETCHED" desc="The label for the last fetched time in the status boxes.">
Last fetched:
</message>
@@ -4269,7 +4275,12 @@ Keep your key file in a safe place. You will need it to create new versions of y
<message name="IDS_POLICY_ENTRY_STATUS" desc="The table header for the column in policy table that contains the status of the policy.">
Status
</message>
-
+ <message name="IDS_POLICY_SHOW_MORE" desc="The text for the link that expands a policy value or policy status table cell.">
+ [Show more]
+ </message>
+ <message name="IDS_POLICY_HIDE" desc="The text for the link that hides overflowing text in a policy value or policy status table cell.">
+ [Hide]
+ </message>
<!-- about:flags -->
<message name="IDS_FLAGS_LONG_TITLE" desc="Long version of the title for the about:flags page.">
Careful, these experiments may bite
diff --git a/chrome/browser/policy/configuration_policy_reader.cc b/chrome/browser/policy/configuration_policy_reader.cc
index c8bf7e1..f9e39b8 100644
--- a/chrome/browser/policy/configuration_policy_reader.cc
+++ b/chrome/browser/policy/configuration_policy_reader.cc
@@ -120,6 +120,14 @@ void ConfigurationPolicyReader::OnProviderGoingAway() {
provider_ = NULL;
}
+void ConfigurationPolicyReader::AddObserver(Observer* observer) {
+ observers_.AddObserver(observer);
+}
+
+void ConfigurationPolicyReader::RemoveObserver(Observer* observer) {
+ observers_.RemoveObserver(observer);
+}
+
// static
ConfigurationPolicyReader*
ConfigurationPolicyReader::CreateManagedPlatformPolicyReader() {
@@ -176,6 +184,8 @@ void ConfigurationPolicyReader::Refresh() {
scoped_ptr<ConfigurationPolicyStatusKeeper> new_keeper(
new ConfigurationPolicyStatusKeeper(provider_, policy_level_));
policy_keeper_.reset(new_keeper.release());
+
+ FOR_EACH_OBSERVER(Observer, observers_, OnPolicyValuesChanged());
}
// PolicyStatus
@@ -192,11 +202,25 @@ PolicyStatus::PolicyStatus(ConfigurationPolicyReader* managed_platform,
PolicyStatus::~PolicyStatus() {
}
-ListValue* PolicyStatus::GetPolicyStatusList(bool* any_policies_sent) const {
+void PolicyStatus::AddObserver(Observer* observer) const {
+ managed_platform_->AddObserver(observer);
+ managed_cloud_->AddObserver(observer);
+ recommended_platform_->AddObserver(observer);
+ recommended_cloud_->AddObserver(observer);
+}
+
+void PolicyStatus::RemoveObserver(Observer* observer) const {
+ managed_platform_->RemoveObserver(observer);
+ managed_cloud_->RemoveObserver(observer);
+ recommended_platform_->RemoveObserver(observer);
+ recommended_cloud_->RemoveObserver(observer);
+}
+
+ListValue* PolicyStatus::GetPolicyStatusList(bool* any_policies_set) const {
ListValue* result = new ListValue();
std::vector<DictionaryValue*> unsent_policies;
- *any_policies_sent = false;
+ *any_policies_set = false;
const PolicyDefinitionList* supported_policies =
ConfigurationPolicyPrefStore::GetChromePolicyDefinitionList();
const PolicyDefinitionList::Entry* policy = supported_policies->begin;
@@ -210,7 +234,7 @@ ListValue* PolicyStatus::GetPolicyStatusList(bool* any_policies_sent) const {
string16());
unsent_policies.push_back(info.GetDictionaryValue());
} else {
- *any_policies_sent = true;
+ *any_policies_set = true;
}
}
diff --git a/chrome/browser/policy/configuration_policy_reader.h b/chrome/browser/policy/configuration_policy_reader.h
index 372ff28..25b9c8a 100644
--- a/chrome/browser/policy/configuration_policy_reader.h
+++ b/chrome/browser/policy/configuration_policy_reader.h
@@ -6,6 +6,7 @@
#define CHROME_BROWSER_POLICY_CONFIGURATION_POLICY_READER_H_
#pragma once
+#include "base/observer_list.h"
#include "base/scoped_ptr.h"
#include "base/values.h"
#include "chrome/browser/policy/configuration_policy_provider.h"
@@ -21,6 +22,18 @@ class ConfigurationPolicyStatusKeeper;
// about:policy UI.
class ConfigurationPolicyReader : public ConfigurationPolicyProvider::Observer {
public:
+
+ // Observer class for the ConfigurationPolicyReader. Observer objects are
+ // notified when policy values have changed.
+ class Observer {
+ public:
+ // Called on an observer when the policy values have changed.
+ virtual void OnPolicyValuesChanged() = 0;
+
+ protected:
+ virtual ~Observer() {}
+ };
+
ConfigurationPolicyReader(ConfigurationPolicyProvider* provider,
PolicyStatusInfo::PolicyLevel policy_level);
virtual ~ConfigurationPolicyReader();
@@ -29,21 +42,21 @@ class ConfigurationPolicyReader : public ConfigurationPolicyProvider::Observer {
virtual void OnUpdatePolicy();
virtual void OnProviderGoingAway();
+ // Methods to handle Observers. |observer| must be non-NULL.
+ void AddObserver(Observer* observer);
+ void RemoveObserver(Observer* observer);
+
// Creates a ConfigurationPolicyReader that reads managed platform policy.
- static ConfigurationPolicyReader*
- CreateManagedPlatformPolicyReader();
+ static ConfigurationPolicyReader* CreateManagedPlatformPolicyReader();
// Creates a ConfigurationPolicyReader that reads managed cloud policy.
- static ConfigurationPolicyReader*
- CreateManagedCloudPolicyReader();
+ static ConfigurationPolicyReader* CreateManagedCloudPolicyReader();
// Creates a ConfigurationPolicyReader that reads recommended platform policy.
- static ConfigurationPolicyReader*
- CreateRecommendedPlatformPolicyReader();
+ static ConfigurationPolicyReader* CreateRecommendedPlatformPolicyReader();
// Creates a ConfigurationPolicyReader that reads recommended cloud policy.
- static ConfigurationPolicyReader*
- CreateRecommendedCloudPolicyReader();
+ static ConfigurationPolicyReader* CreateRecommendedCloudPolicyReader();
// Returns a pointer to a DictionaryValue object containing policy status
// information for the UI. Ownership of the return value is acquired by the
@@ -70,6 +83,9 @@ class ConfigurationPolicyReader : public ConfigurationPolicyProvider::Observer {
// Current policy status.
scoped_ptr<ConfigurationPolicyStatusKeeper> policy_keeper_;
+ // The list of observers for this ConfigurationPolicyReader.
+ ObserverList<Observer, true> observers_;
+
ConfigurationPolicyObserverRegistrar registrar_;
DISALLOW_COPY_AND_ASSIGN(ConfigurationPolicyReader);
@@ -80,17 +96,24 @@ class ConfigurationPolicyReader : public ConfigurationPolicyProvider::Observer {
// about:policy UI can display.
class PolicyStatus {
public:
+ typedef ConfigurationPolicyReader::Observer Observer;
PolicyStatus(ConfigurationPolicyReader* managed_platform,
ConfigurationPolicyReader* managed_cloud,
ConfigurationPolicyReader* recommended_platform,
ConfigurationPolicyReader* recommended_cloud);
~PolicyStatus();
+ // Adds an observer to each one of the ConfigurationPolicyReaders.
+ void AddObserver(Observer* observer) const;
+
+ // Removes an observer from each one of the ConfigurationPolicyReaders.
+ void RemoveObserver(Observer* observer) const;
+
// Returns a ListValue pointer containing the status information of all
- // policies supported by the client. |any_policies_sent| is set to true if
+ // policies supported by the client. |any_policies_set| is set to true if
// there are policies in the list that were sent by a provider, otherwise
// it is set to false. This is for the about:policy UI to display.
- ListValue* GetPolicyStatusList(bool* any_policies_sent) const;
+ ListValue* GetPolicyStatusList(bool* any_policies_set) const;
// Returns a string16 containing the actual name of the policy corresponding
// to |policy_type|. Returns an empty string if there is no such policy_type
@@ -105,7 +128,7 @@ class PolicyStatus {
// |list| as it is returned by the different ConfigurationPolicyReader
// objects. Returns true if a policy was added and false otherwise.
bool AddPolicyFromReaders(ConfigurationPolicyType policy,
- ListValue* list) const;
+ ListValue* list) const;
scoped_ptr<ConfigurationPolicyReader> managed_platform_;
scoped_ptr<ConfigurationPolicyReader> managed_cloud_;
diff --git a/chrome/browser/resources/policy.css b/chrome/browser/resources/policy.css
index 2fa9a1b..e572247 100644
--- a/chrome/browser/resources/policy.css
+++ b/chrome/browser/resources/policy.css
@@ -141,3 +141,18 @@ legend {
text-overflow: ellipsis;
width: 20%;
}
+
+.toggler {
+ color: #808080;
+}
+
+.collapsed {
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
+
+.expanded {
+ overflow: visible;
+ word-wrap: break-word;
+}
diff --git a/chrome/browser/resources/policy.html b/chrome/browser/resources/policy.html
index db547b4..05d38a9 100644
--- a/chrome/browser/resources/policy.html
+++ b/chrome/browser/resources/policy.html
@@ -5,52 +5,85 @@
<title i18n-content="policyTitle"></title>
<link rel="stylesheet" href="chrome://resources/css/button.css">
<link rel="stylesheet" href="policy.css">
+<link rel="stylesheet" href="webui.css">
<script src="chrome://policy/strings.js"></script>
<script src="chrome://resources/js/cr.js"></script>
<script src="chrome://resources/js/cr/ui.js"></script>
-<script src="chrome://resources/js/local_strings.js"></script>
<script src="chrome://resources/js/i18n_template.js"></script>
<script src="chrome://resources/js/i18n_process.js"></script>
<script src="chrome://resources/js/jstemplate_compiled.js"></script>
<script src="chrome://resources/js/util.js"></script>
<script src="policy.js"></script>
</head>
-<body i18n-values=".style.fontFamily:fontfamily;">
+<body i18n-values=".style.fontFamily:fontfamily; .style.fontSize:fontsize">
<div class="header">
<h1 id="about-policy-title" i18n-content="policyTitle"></h1>
</div>
<div id="main-content">
- <section id="status-section">
- <div class="separator">
- <span id="status-title" i18n-content="statusPaneTitle"></span>
- <div id="fetch-policies">
- <button id="fetch-policies-button" i18n-content="fetchPoliciesText">
- </button>
+ <div id="data-template">
+ <section id="status-section" jsselect="status" hidden
+ jsdisplay="displayStatusSection">
+ <div class="separator">
+ <span id="status-title" i18n-content="statusPaneTitle"></span>
+ <div id="fetch-policies">
+ <button id="fetch-policies-button" i18n-content="fetchPoliciesText">
+ </button>
+ </div>
</div>
- </div>
- <div id="status-pane">
- <fieldset class="status-box">
- <legend i18n-content="devicePoliciesBoxTitle"></legend>
- <ul>
- <li i18n-content="enrollmentDomainText"></li>
- <li i18n-content="lastFetchedText"></li>
- <li i18n-content="fetchIntervalText"></li>
- <li i18n-content="serverStatusText"></li>
- </ul>
- </fieldset>
- <fieldset class="status-box">
- <legend i18n-content="userPoliciesBoxTitle"></legend>
- <ul>
- <li i18n-content="enrollmentDomainText"></li>
- <li i18n-content="lastFetchedText"></li>
- <li i18n-content="fetchIntervalText"></li>
- <li i18n-content="serverStatusText"></li>
- </ul>
- </fielset>
- </div>
- </section>
- <section id="policies-section">
- <div id="policiesTemplate">
+ <div id="status-pane">
+ <fieldset class="status-box">
+ <legend i18n-content="devicePoliciesBoxTitle"></legend>
+ <ul>
+ <li>
+ <span i18n-content="enrollmentDomainText"></span>
+ <span jscontent="devicePolicyDomain"></span>
+ </li>
+ <li>
+ <span i18n-content="clientIdText"></span>
+ <span jscontent="deviceId"></span>
+ </li>
+ <li>
+ <span i18n-content="lastFetchedText"></span>
+ <span jscontent="deviceLastFetchTime"></span>
+ </li>
+ <li>
+ <span i18n-content="fetchIntervalText"></span>
+ <span jscontent="deviceFetchInterval"></span>
+ </li>
+ <li>
+ <span i18n-content="serverStatusText"></span>
+ <span jscontent="deviceStatusMessage"></span>
+ </li>
+ </ul>
+ </fieldset>
+ <fieldset class="status-box">
+ <legend i18n-content="userPoliciesBoxTitle"></legend>
+ <ul>
+ <li>
+ <span i18n-content="usernameText"></span>
+ <span jscontent="user"></span>
+ </li>
+ <li>
+ <span i18n-content="clientIdText"></span>
+ <span jscontent="userId"></span>
+ </li>
+ <li>
+ <span i18n-content="lastFetchedText"></span>
+ <span jscontent="userLastFetchTime"></span>
+ </li>
+ <li>
+ <span i18n-content="fetchIntervalText"></span>
+ <span jscontent="userFetchInterval"></span>
+ </li>
+ <li>
+ <span i18n-content="serverStatusText"></span>
+ <span jscontent="userStatusMessage"></span>
+ </li>
+ </ul>
+ </fielset>
+ </div>
+ </section>
+ <section id="policies-section">
<div class="separator">
<span id="policies-title" i18n-content="policyTitle"></span>
<div id="unsent-policies-control">
@@ -66,11 +99,10 @@
</div>
</div>
<div>
- <div id="no-policies" jsdisplay="!anyPoliciesSet">
+ <div id="no-policies" hidden jsdisplay="!anyPoliciesSet">
<div id="no-policies-text" i18n-content="noPoliciesSet"></div>
</div>
- <div id="policies"
- jsvalues=".style.display: anyPoliciesSet ?
+ <div id="policies" jsvalues=".style.display: anyPoliciesSet ?
'': 'none'">
<table id="policy-table">
<tr>
@@ -83,29 +115,43 @@
<tr jsselect="policies"
jsvalues=".className: $this.set ?
'policy-set': 'policy-unset';
- .style.display: Policy.shouldDisplayPolicy($this) ?
- '': 'none'">
+ .style.visibility: Policy.shouldDisplayPolicy($this) ?
+ 'visible': 'hidden'">
<td>
<span class="policy-type" jscontent="sourceType"></span>
</td>
<td>
<span class="policy-level" jscontent="level"></span>
</td>
- <td>
+ <td class="collapsed">
<span class="policy-name" jscontent="name"></span>
</td>
<td>
- <span class="policy-value" jscontent="value"></span>
+ <div class="text-container collapsed">
+ <span class="cell-text" jscontent="value"></span>
+ </div>
+ <a class="toggler expand" style="display: none"
+ jsdisplay="Policy.shouldShowExpand(this)"
+ i18n-content="showMoreText"></a>
+ <a class="toggler collapse" style="display: none"
+ i18n-content="hideText"></a>
</td>
<td>
- <span class="policy-status" jscontent="status"></span>
+ <div class="text-container collapsed">
+ <span class="cell-text" jscontent="status"></span>
+ </div>
+ <a class="toggler expand" style="display: none"
+ jsdisplay="Policy.shouldShowExpand(this)"
+ i18n-content="showMoreText"></a>
+ <a class="toggler collapse" style="display: none"
+ i18n-content="hideText"></a>
</td>
</tr>
</table>
</div>
</div>
- </div>
- </section>
+ </section>
+ </div>
</div>
</body>
</html>
diff --git a/chrome/browser/resources/policy.js b/chrome/browser/resources/policy.js
index db4f404..c86611d 100644
--- a/chrome/browser/resources/policy.js
+++ b/chrome/browser/resources/policy.js
@@ -2,13 +2,17 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-var localStrings = new LocalStrings();
-
/**
* This variable structure is here to document the structure that the template
* expects to correctly populate the page.
*/
-var policyDataformat = {
+var policyDataFormat = {
+ // Whether any of the policies in 'policies' have a value.
+ 'anyPoliciesSet': true,
+
+ // False if the policy information is being sent due to an initial page load
+ // and true if it is being sent due to a change of policy values.
+ 'isPolicyUpdate': false,
'policies': [
{
'level': 'managed',
@@ -16,10 +20,22 @@ var policyDataformat = {
'set': true,
'sourceType': 'Device',
'status': 'ok',
- 'value': true,
- },
+ 'value': true
+ }
],
- 'anyPoliciesSet': true
+ 'status': {
+ 'deviceFetchInterval': '8min',
+ 'deviceId': 'D2AC39A2-3C8FC-E2C0-E45D2DC3782C',
+ 'deviceLastFetchTime': '9:50 PM',
+ 'devicePolicyDomain': 'google.com',
+ 'deviceStatusMessage': 'OK',
+ 'displayStatusSection': true,
+ 'user': 'simo@google.com',
+ 'userFetchInterval': '8min',
+ 'userId': 'D2AC39A2-3C8FC-E2C0-E45D2DC3782C',
+ 'userLastFetchTime': '9:50 PM',
+ 'userStatusMessage': 'OK'
+ }
};
cr.define('policies', function() {
@@ -45,23 +61,28 @@ cr.define('policies', function() {
searchTerm_: '',
/**
- * Takes the |policyData| input argument which represents data about the
- * policies supported by the device/client and populates the html jstemplate
- * with that data. It expects an object structure like the above.
- * @param {Object} policyData Detailed info about policies
+ * 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.
*/
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 = $('policiesTemplate');
+ var output = $('data-template');
jstProcess(input, output);
+ this.setToggleEventHandlers_();
},
/**
* Filters the table of policies by name.
- * @param {string} term The search string
+ * @param {string} term The search string.
*/
filterTable: function(term) {
this.searchTerm_ = term.toLowerCase();
@@ -104,41 +125,149 @@ cr.define('policies', function() {
// Filter table again in case a search was active.
this.filterTable(this.searchTerm_);
+ },
+
+ /**
+ * Set event handlers for the "Show more"/"Hide" links generated by
+ * jstemplate.
+ * @private
+ */
+ setToggleEventHandlers_: function() {
+ var toggles = document.querySelectorAll('.policy-set * .toggler');
+ for (var i = 0; i < toggles.length; i++) {
+ toggles[i].onclick = function() {
+ Policy.getInstance().toggleCellExpand_(this);
+ };
+ }
+ },
+
+ /**
+ * Expands or collapses a table cell that has overflowing text.
+ * @param {Object} toggler The toggler that was clicked on.
+ * @private
+ */
+ toggleCellExpand_: function(toggler) {
+ var tableCell = toggler.parentElement;
+ var textContainer = tableCell.querySelector('.text-container');
+
+ if (textContainer.collapsed)
+ this.expandCell_(textContainer);
+ else
+ this.collapseCell_(textContainer);
+
+ textContainer.collapsed = !textContainer.collapsed;
+ var expand = tableCell.querySelector('.expand');
+ var collapse = tableCell.querySelector('.collapse');
+ expand.style.display = textContainer.collapsed ? '' : 'none';
+ collapse.style.display = textContainer.collapsed ? 'none' : '';
+ },
+
+ /**
+ * 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.
+ */
+ collapseExpandedCells: function() {
+ var toggles = document.querySelectorAll('.policy-set * .toggler');
+ for (var i = 0; i < toggles.length; i++)
+ toggles[i].style.display = 'none';
+
+ var textContainers = document.querySelectorAll('.expanded');
+ for (var i = 0; i < textContainers.length; i++)
+ this.collapseCell_(textContainers[i]);
+ },
+
+ /**
+ * 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
+ */
+ expandCell_: function(textContainer) {
+ textContainer.classList.remove('collapsed');
+ textContainer.classList.add('expanded');
+ },
+
+ /**
+ * Collapses a table cell so that overflowing text is hidden.
+ * @param {Object} textContainer The cell's div element that contains the
+ * text.
+ * @private
+ */
+ collapseCell_: function(textContainer) {
+ textContainer.classList.remove('expanded');
+ textContainer.classList.add('collapsed');
}
};
/**
- * Asks the C++ PolicyUIHandler to get details about policies. The
- * PolicyDOMHandler should reply to returnPolicyData() (below).
+ * Asks the C++ PolicyUIHandler to get details about policies and status
+ * information. The PolicyUIHandler should reply to returnData() (below).
*/
- Policy.requestPolicyData = function() {
- chrome.send('requestPolicyData');
+ Policy.requestData = function() {
+ chrome.send('requestData');
};
/**
- * Called by the C++ PolicyUIHandler when it has the requested policy data.
+ * Called by the C++ PolicyUIHandler when it has the requested data.
+ * @param {Object} policyData The policy information in the format described
+ * by the policyDataFormat.
*/
- Policy.returnPolicyData = function(policyData) {
- Policy.getInstance().renderTemplate(policyData);
+ Policy.returnData = function(policyData) {
+ if (policyData.isPolicyUpdate) {
+ Policy.getInstance().collapseExpandedCells();
+ Policy.getInstance().renderTemplate(policyData);
+ Policy.getInstance().updatePolicyVisibility();
+ } else {
+ Policy.getInstance().renderTemplate(policyData);
+ }
+ };
+
+ /**
+ * Asks the C++ PolicyUIHandler to re-fetch policy information.
+ */
+ Policy.triggerPolicyFetch = function() {
+ chrome.send('fetchPolicy');
};
/**
* Determines whether a policy should be visible or not.
- * @param {policy} policy information in the format given by above the
- * PolicyDataFormat
+ * @param {Object} policy An entry in the 'policies' array given by the above
+ * PolicyDataFormat.
*/
Policy.shouldDisplayPolicy = function(policy) {
return $('toggle-unsent-policies').checked || policy.set;
};
/**
- * Initializes the page and loads the list of policies.
+ * Returns true if the "Show more" toggle should appear in a table cell and
+ * false if not.
+ * @param {Object} expandToggle The "Show more" DOM element.
+ */
+ Policy.shouldShowExpand = function(expandToggle) {
+ var textContainer =
+ expandToggle.parentNode.querySelector('.text-container');
+ textContainer.collapsed = true;
+ var cellText = textContainer.querySelector('.cell-text');
+
+ // If the text is wider than the text container, the expand toggler should
+ // appear.
+ return textContainer.offsetWidth < cellText.offsetWidth;
+ };
+
+ /**
+ * Initializes the page and loads the list of policies and the policy
+ * status data.
*/
Policy.initialize = function() {
i18nTemplate.process(document, templateData);
- Policy.requestPolicyData();
+ Policy.requestData();
// Set HTML event handlers.
+ $('fetch-policies-button').onclick = function(event) {
+ Policy.triggerPolicyFetch();
+ }
+
$('toggle-unsent-policies').onchange = function(event) {
Policy.getInstance().updatePolicyVisibility();
};
diff --git a/chrome/browser/ui/webui/policy_ui.cc b/chrome/browser/ui/webui/policy_ui.cc
index 99ebb3e..b412d6f 100644
--- a/chrome/browser/ui/webui/policy_ui.cc
+++ b/chrome/browser/ui/webui/policy_ui.cc
@@ -4,9 +4,17 @@
#include "chrome/browser/ui/webui/policy_ui.h"
-#include "chrome/browser/policy/policy_status_info.h"
+#include "base/i18n/time_formatting.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/chromeos/login/user_manager.h"
+#include "chrome/browser/policy/browser_policy_connector.h"
+#include "chrome/browser/policy/cloud_policy_cache_base.h"
+#include "chrome/browser/prefs/pref_service.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/webui/chrome_web_ui_data_source.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/common/time_format.h"
#include "chrome/common/url_constants.h"
#include "content/browser/tab_contents/tab_contents.h"
#include "grit/browser_resources.h"
@@ -26,6 +34,8 @@ ChromeWebUIDataSource* CreatePolicyUIHTMLSource() {
IDS_POLICY_USER_POLICIES);
source->AddLocalizedString("enrollmentDomainText",
IDS_POLICY_ENROLLMENT_DOMAIN);
+ source->AddLocalizedString("clientIdText", IDS_POLICY_CLIENT_ID);
+ source->AddLocalizedString("usernameText", IDS_POLICY_USERNAME);
source->AddLocalizedString("lastFetchedText", IDS_POLICY_LAST_FETCHED);
source->AddLocalizedString("fetchIntervalText", IDS_POLICY_FETCH_INTERVAL);
source->AddLocalizedString("serverStatusText", IDS_POLICY_SERVER_STATUS);
@@ -39,6 +49,8 @@ ChromeWebUIDataSource* CreatePolicyUIHTMLSource() {
source->AddLocalizedString("policyValueTableHeader", IDS_POLICY_ENTRY_VALUE);
source->AddLocalizedString("policyStatusTableHeader",
IDS_POLICY_ENTRY_STATUS);
+ source->AddLocalizedString("showMoreText", IDS_POLICY_SHOW_MORE);
+ source->AddLocalizedString("hideText", IDS_POLICY_HIDE);
source->set_json_path("strings.js");
// Add required resources.
@@ -57,20 +69,23 @@ ChromeWebUIDataSource* CreatePolicyUIHTMLSource() {
PolicyUIHandler::PolicyUIHandler() {
policy::ConfigurationPolicyReader* managed_platform =
- ConfigurationPolicyReader::CreateManagedPlatformPolicyReader();
+ policy::ConfigurationPolicyReader::CreateManagedPlatformPolicyReader();
policy::ConfigurationPolicyReader* managed_cloud =
- ConfigurationPolicyReader::CreateManagedCloudPolicyReader();
+ policy::ConfigurationPolicyReader::CreateManagedCloudPolicyReader();
policy::ConfigurationPolicyReader* recommended_platform =
- ConfigurationPolicyReader::CreateRecommendedPlatformPolicyReader();
+ policy::ConfigurationPolicyReader::
+ CreateRecommendedPlatformPolicyReader();
policy::ConfigurationPolicyReader* recommended_cloud =
- ConfigurationPolicyReader::CreateRecommendedCloudPolicyReader();
+ policy::ConfigurationPolicyReader::CreateRecommendedCloudPolicyReader();
policy_status_.reset(new policy::PolicyStatus(managed_platform,
managed_cloud,
recommended_platform,
recommended_cloud));
+ policy_status_->AddObserver(this);
}
PolicyUIHandler::~PolicyUIHandler() {
+ policy_status_->RemoveObserver(this);
}
WebUIMessageHandler* PolicyUIHandler::Attach(WebUI* web_ui) {
@@ -78,17 +93,149 @@ WebUIMessageHandler* PolicyUIHandler::Attach(WebUI* web_ui) {
}
void PolicyUIHandler::RegisterMessages() {
- web_ui_->RegisterMessageCallback("requestPolicyData",
- NewCallback(this, &PolicyUIHandler::HandleRequestPolicyData));
+ web_ui_->RegisterMessageCallback("requestData",
+ NewCallback(this, &PolicyUIHandler::HandleRequestData));
+ web_ui_->RegisterMessageCallback("fetchPolicy",
+ NewCallback(this, &PolicyUIHandler::HandleFetchPolicy));
}
-void PolicyUIHandler::HandleRequestPolicyData(const ListValue* args) {
- bool any_policies_sent;
- ListValue* list = policy_status_->GetPolicyStatusList(&any_policies_sent);
+void PolicyUIHandler::OnPolicyValuesChanged() {
+ SendDataToUI(true);
+}
+
+void PolicyUIHandler::HandleRequestData(const ListValue* args) {
+ SendDataToUI(false);
+}
+
+void PolicyUIHandler::HandleFetchPolicy(const ListValue* args) {
+ if (FetchPolicyIfTokensAvailable())
+ SendDataToUI(true);
+}
+
+void PolicyUIHandler::SendDataToUI(bool is_policy_update) {
DictionaryValue results;
+ bool any_policies_set;
+ ListValue* list = policy_status_->GetPolicyStatusList(&any_policies_set);
results.Set("policies", list);
- results.SetBoolean("anyPoliciesSet", any_policies_sent);
- web_ui_->CallJavascriptFunction("Policy.returnPolicyData", results);
+ results.SetBoolean("anyPoliciesSet", any_policies_set);
+ DictionaryValue* dict = GetStatusData();
+ results.Set("status", dict);
+ results.SetBoolean("isPolicyUpdate", is_policy_update);
+
+ web_ui_->CallJavascriptFunction("Policy.returnData", results);
+}
+
+DictionaryValue* PolicyUIHandler::GetStatusData() {
+ DictionaryValue* results = new DictionaryValue();
+ policy::BrowserPolicyConnector* connector =
+ g_browser_process->browser_policy_connector();
+
+ policy::CloudPolicySubsystem* device_subsystem =
+ connector->device_cloud_policy_subsystem();
+ policy::CloudPolicySubsystem* user_subsystem =
+ connector->user_cloud_policy_subsystem();
+
+ // If no CloudPolicySubsystem is available, the status section is not
+ // displayed and we can return here.
+ if (!device_subsystem || !user_subsystem) {
+ results->SetBoolean("displayStatusSection", false);
+ return results;
+ } else {
+ results->SetBoolean("displayStatusSection", true);
+ }
+
+ // Get the server status message and the time at which policy was last fetched
+ // for both user and device policy from the appropriate CloudPolicySubsystem.
+ results->SetString("deviceStatusMessage",
+ CreateStatusMessageString(device_subsystem->error_details()));
+ results->SetString("deviceLastFetchTime", GetLastFetchTime(device_subsystem));
+ results->SetString("userStatusMessage",
+ CreateStatusMessageString(user_subsystem->error_details()));
+ results->SetString("userLastFetchTime", GetLastFetchTime(user_subsystem));
+
+ // Get enterprise domain and username (only on ChromeOS).
+#if defined (OS_CHROMEOS)
+ chromeos::UserManager::User user =
+ chromeos::UserManager::Get()->logged_in_user();
+ results->SetString("devicePolicyDomain",
+ ASCIIToUTF16(connector->GetEnterpriseDomain()));
+ results->SetString("user", ASCIIToUTF16(user.email()));
+#else
+ results->SetString("devicePolicyDomain", string16());
+ results->SetString("user", string16());
+#endif
+
+ // Get the device ids for both user and device policy from the appropriate
+ // CloudPolicyDataStore.
+ results->SetString("deviceId",
+ GetDeviceId(connector->GetDeviceCloudPolicyDataStore()));
+ results->SetString("userId",
+ GetDeviceId(connector->GetUserCloudPolicyDataStore()));
+
+ // Get the policy refresh rate for both user and device policy from the
+ // appropriate preference.
+ results->SetString("deviceFetchInterval",
+ GetPolicyFetchInterval(prefs::kDevicePolicyRefreshRate));
+ results->SetString("userFetchInterval",
+ GetPolicyFetchInterval(prefs::kUserPolicyRefreshRate));
+
+ return results;
+}
+
+bool PolicyUIHandler::FetchPolicyIfTokensAvailable() {
+ policy::BrowserPolicyConnector* connector =
+ g_browser_process->browser_policy_connector();
+ const policy::CloudPolicyDataStore* device_data_store =
+ connector->GetDeviceCloudPolicyDataStore();
+ const policy::CloudPolicyDataStore* user_data_store =
+ connector->GetUserCloudPolicyDataStore();
+
+ bool fetch_device_policy =
+ device_data_store && !device_data_store->device_token().empty();
+ bool fetch_user_policy =
+ user_data_store && !user_data_store->device_token().empty();
+
+ if (fetch_device_policy)
+ connector->FetchDevicePolicy();
+
+ if (fetch_user_policy)
+ connector->FetchUserPolicy();
+
+ return fetch_device_policy || fetch_user_policy;
+}
+
+string16 PolicyUIHandler::GetLastFetchTime(
+ policy::CloudPolicySubsystem* subsystem) {
+ policy::CloudPolicyCacheBase* cache_base =
+ subsystem->GetCloudPolicyCacheBase();
+ base::TimeDelta time_delta =
+ base::Time::NowFromSystemTime() - cache_base->last_policy_refresh_time();
+
+ return TimeFormat::TimeElapsed(time_delta);
+}
+
+string16 PolicyUIHandler::GetDeviceId(
+ const policy::CloudPolicyDataStore* data_store) {
+ return data_store ? ASCIIToUTF16(data_store->device_id()) : string16();
+}
+
+string16 PolicyUIHandler::GetPolicyFetchInterval(const char* refresh_pref) {
+ PrefService* prefs = g_browser_process->local_state();
+ return TimeFormat::TimeRemainingShort(
+ base::TimeDelta::FromMilliseconds(prefs->GetInteger(refresh_pref)));
+}
+
+// static
+string16 PolicyUIHandler::CreateStatusMessageString(
+ policy::CloudPolicySubsystem::ErrorDetails error_details) {
+ static string16 error_to_string[] = { ASCIIToUTF16("OK."),
+ ASCIIToUTF16("Network error."),
+ ASCIIToUTF16("Network error."),
+ ASCIIToUTF16("Bad DMToken."),
+ ASCIIToUTF16("Local error."),
+ ASCIIToUTF16("Signature mismatch.") };
+ DCHECK(static_cast<size_t>(error_details) < arraysize(error_to_string));
+ return error_to_string[error_details];
}
////////////////////////////////////////////////////////////////////////////////
diff --git a/chrome/browser/ui/webui/policy_ui.h b/chrome/browser/ui/webui/policy_ui.h
index f773a4b..52e0ad2 100644
--- a/chrome/browser/ui/webui/policy_ui.h
+++ b/chrome/browser/ui/webui/policy_ui.h
@@ -7,13 +7,17 @@
#pragma once
#include "base/scoped_ptr.h"
+#include "base/time.h"
#include "base/values.h"
+#include "chrome/browser/policy/cloud_policy_data_store.h"
+#include "chrome/browser/policy/cloud_policy_subsystem.h"
#include "chrome/browser/policy/configuration_policy_reader.h"
#include "chrome/browser/ui/webui/chrome_web_ui.h"
#include "content/common/notification_observer.h"
// The base class handler of Javascript messages of the about:policy page.
-class PolicyUIHandler : public WebUIMessageHandler {
+class PolicyUIHandler : public WebUIMessageHandler,
+ public policy::PolicyStatus::Observer {
public:
PolicyUIHandler();
virtual ~PolicyUIHandler();
@@ -22,11 +26,46 @@ class PolicyUIHandler : public WebUIMessageHandler {
virtual WebUIMessageHandler* Attach(WebUI* web_ui) OVERRIDE;
virtual void RegisterMessages() OVERRIDE;
+ // policy::ConfigurationPolicyReader::Observer implementation.
+ virtual void OnPolicyValuesChanged() OVERRIDE;
+
private:
- typedef policy::ConfigurationPolicyReader ConfigurationPolicyReader;
- // Callback for the "requestPolicyData" message.
- void HandleRequestPolicyData(const ListValue* args);
+ // Callback for the "requestData" message. The parameter |args| is unused.
+ void HandleRequestData(const ListValue* args);
+
+ // Callback for the "fetchPolicy" message. The parameter |args| is unused.
+ void HandleFetchPolicy(const ListValue* args);
+
+ // Send requested data to UI. |is_policy_update| should be set to true when
+ // policy data is pushed to the UI without having been requested by a
+ // javascript message and to false otherwise.
+ void SendDataToUI(bool is_policy_update);
+
+ // Returns a DictionaryValue pointer containing information about the status
+ // of the policy system. The caller acquires ownership of the returned
+ // DictionaryValue pointer.
+ DictionaryValue* GetStatusData();
+
+ // Fetches policy if the appropriate device tokens are available. Returns
+ // true, if any policy was fetched (device or user). Returns false otherwise.
+ bool FetchPolicyIfTokensAvailable();
+
+ // Returns the time at which policy was last fetched by the
+ // CloudPolicySubsystem |subsystem| in string form.
+ string16 GetLastFetchTime(policy::CloudPolicySubsystem* subsystem);
+
+ // Reads the device id from |data_store| and returns it as a string16.
+ string16 GetDeviceId(const policy::CloudPolicyDataStore* data_store);
+
+ // Reads the policy fetch interval from the preferences specified by
+ // |refresh_pref| and returns it as a string16.
+ string16 GetPolicyFetchInterval(const char* refresh_pref);
+
+ // Returns the string corresponding to the CloudPolicySubsystem::ErrorDetails
+ // enum value |error_details|.
+ static string16 CreateStatusMessageString(
+ policy::CloudPolicySubsystem::ErrorDetails error_details);
scoped_ptr<policy::PolicyStatus> policy_status_;