summaryrefslogtreecommitdiffstats
path: root/chrome/browser
diff options
context:
space:
mode:
authorsimo@google.com <simo@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2011-08-31 16:10:04 +0000
committersimo@google.com <simo@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2011-08-31 16:10:04 +0000
commita8171203aadbc0d452ec3b46eb16d6b5b5e8427b (patch)
tree2c2b6003fa94f743bc6e6e4b5121a0edc93f62f0 /chrome/browser
parent5a2b69999950076443aa3c9c1def3c676eeeb870 (diff)
downloadchromium_src-a8171203aadbc0d452ec3b46eb16d6b5b5e8427b.zip
chromium_src-a8171203aadbc0d452ec3b46eb16d6b5b5e8427b.tar.gz
chromium_src-a8171203aadbc0d452ec3b46eb16d6b5b5e8427b.tar.bz2
First CL for the about:policy page. This only implements the policy section of the page.
Preliminary design doc: https://docs.google.com/a/google.com/document/d/1KWsF52ImY4eJbNgizaA6Gw_aMVg24zgZfypKZBs376k/edit?hl=en_US&ndplr=1 TEST=set some policies, start chrome and go to chrome://policy Review URL: http://codereview.chromium.org/7585036 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@98977 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser')
-rw-r--r--chrome/browser/browser_resources.grd3
-rw-r--r--chrome/browser/policy/configuration_policy_reader.cc272
-rw-r--r--chrome/browser/policy/configuration_policy_reader.h120
-rw-r--r--chrome/browser/policy/configuration_policy_reader_unittest.cc352
-rw-r--r--chrome/browser/policy/mock_configuration_policy_reader.cc13
-rw-r--r--chrome/browser/policy/mock_configuration_policy_reader.h28
-rw-r--r--chrome/browser/policy/policy_status_info.cc86
-rw-r--r--chrome/browser/policy/policy_status_info.h97
-rw-r--r--chrome/browser/resources/policy.css143
-rw-r--r--chrome/browser/resources/policy.html14
-rw-r--r--chrome/browser/resources/policy.js160
-rw-r--r--chrome/browser/ui/webui/chrome_web_ui_factory.cc3
-rw-r--r--chrome/browser/ui/webui/policy_ui.cc109
-rw-r--r--chrome/browser/ui/webui/policy_ui.h46
14 files changed, 1438 insertions, 8 deletions
diff --git a/chrome/browser/browser_resources.grd b/chrome/browser/browser_resources.grd
index 7891f2a..992e4e0 100644
--- a/chrome/browser/browser_resources.grd
+++ b/chrome/browser/browser_resources.grd
@@ -87,6 +87,9 @@
<include name="IDR_NOTIFICATION_ICON_HTML" file="resources\notification_icon.html" type="BINDATA" />
<include name="IDR_PLUGINS_HTML" file="resources\plugins.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" />
<include name="IDR_PLUGINS_JS" file="resources\plugins.js" type="BINDATA" />
+ <include name="IDR_POLICY_HTML" file="resources\policy.html" type="BINDATA"/>
+ <include name="IDR_POLICY_CSS" file="resources\policy.css" type="BINDATA"/>
+ <include name="IDR_POLICY_JS" file="resources\policy.js" type="BINDATA"/>
<include name="IDR_READER_OUT_OF_DATE_HTML" file="resources\reader_out_of_date.html" flattenhtml="true" type="BINDATA" />
<include name="IDR_PRINT_PREVIEW_HTML" file="resources\print_preview\print_preview.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" />
<include name="IDR_PRINT_PREVIEW_JS" file="resources\print_preview\print_preview.js" flattenhtml="true" type="BINDATA" />
diff --git a/chrome/browser/policy/configuration_policy_reader.cc b/chrome/browser/policy/configuration_policy_reader.cc
new file mode 100644
index 0000000..472a151
--- /dev/null
+++ b/chrome/browser/policy/configuration_policy_reader.cc
@@ -0,0 +1,272 @@
+// Copyright (c) 2011 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.
+
+#include "chrome/browser/policy/configuration_policy_reader.h"
+
+#include <map>
+#include <vector>
+
+#include "base/stl_util.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/policy/browser_policy_connector.h"
+#include "chrome/browser/policy/configuration_policy_pref_store.h"
+#include "chrome/browser/policy/configuration_policy_store_interface.h"
+
+namespace policy {
+
+// This class functions as a container for policy status information used by the
+// ConfigurationPolicyReader class. It obtains policy values from a
+// ConfigurationPolicyProvider and maps them to their status information.
+class ConfigurationPolicyStatusKeeper
+ : public ConfigurationPolicyStoreInterface {
+ public:
+ ConfigurationPolicyStatusKeeper(ConfigurationPolicyProvider* provider,
+ PolicyStatusInfo::PolicyLevel policy_level);
+ virtual ~ConfigurationPolicyStatusKeeper();
+
+ // ConfigurationPolicyStoreInterface methods.
+ virtual void Apply(ConfigurationPolicyType policy, base::Value* value);
+
+ // Returns a pointer to a DictionaryValue containing the status information
+ // of the policy |policy|. The caller acquires ownership of the returned
+ // value. Returns NULL if no such policy is stored in this keeper.
+ DictionaryValue* GetPolicyStatus(ConfigurationPolicyType policy) const;
+
+ private:
+ typedef std::map<ConfigurationPolicyType, PolicyStatusInfo*> PolicyStatusMap;
+ typedef std::map<ConfigurationPolicyType, string16> PolicyNameMap;
+ typedef ConfigurationPolicyProvider::PolicyDefinitionList
+ PolicyDefinitionList;
+
+ // Mapping from ConfigurationPolicyType to PolicyStatusInfo.
+ PolicyStatusMap policy_map_;
+
+ // The level of the policies stored in this keeper (mandatory or
+ // recommended).
+ PolicyStatusInfo::PolicyLevel policy_level_;
+
+ DISALLOW_COPY_AND_ASSIGN(ConfigurationPolicyStatusKeeper);
+};
+
+// ConfigurationPolicyStatusKeeper
+ConfigurationPolicyStatusKeeper::ConfigurationPolicyStatusKeeper(
+ ConfigurationPolicyProvider* provider,
+ PolicyStatusInfo::PolicyLevel policy_level) : policy_level_(policy_level) {
+
+ if (!provider->Provide(this))
+ LOG(WARNING) << "Failed to get policy from provider.";
+}
+
+ConfigurationPolicyStatusKeeper::~ConfigurationPolicyStatusKeeper() {
+ STLDeleteContainerPairSecondPointers(policy_map_.begin(), policy_map_.end());
+ policy_map_.clear();
+}
+
+void ConfigurationPolicyStatusKeeper::Apply(
+ ConfigurationPolicyType policy, base::Value* value) {
+ string16 name = PolicyStatus::GetPolicyName(policy);
+
+ if (name == string16()) {
+ NOTREACHED();
+ }
+
+ // TODO(simo) actually determine whether the policy is a user or a device one
+ // and whether the policy could be enforced or not once this information
+ // is available.
+ PolicyStatusInfo* info = new PolicyStatusInfo(name,
+ PolicyStatusInfo::USER,
+ policy_level_,
+ value,
+ PolicyStatusInfo::ENFORCED,
+ string16());
+ policy_map_[policy] = info;
+}
+
+DictionaryValue* ConfigurationPolicyStatusKeeper::GetPolicyStatus(
+ ConfigurationPolicyType policy) const {
+ PolicyStatusMap::const_iterator entry = policy_map_.find(policy);
+ return entry != policy_map_.end() ?
+ (entry->second)->GetDictionaryValue() : NULL;
+}
+
+// ConfigurationPolicyReader
+ConfigurationPolicyReader::~ConfigurationPolicyReader() {
+}
+
+void ConfigurationPolicyReader::OnUpdatePolicy() {
+ Refresh();
+}
+
+void ConfigurationPolicyReader::OnProviderGoingAway() {
+ provider_ = NULL;
+}
+
+// static
+ConfigurationPolicyReader*
+ ConfigurationPolicyReader::CreateManagedPlatformPolicyReader() {
+ BrowserPolicyConnector* connector =
+ g_browser_process->browser_policy_connector();
+ return new ConfigurationPolicyReader(
+ connector->GetManagedPlatformProvider(), PolicyStatusInfo::MANDATORY);
+}
+
+// static
+ConfigurationPolicyReader*
+ ConfigurationPolicyReader::CreateManagedCloudPolicyReader() {
+ BrowserPolicyConnector* connector =
+ g_browser_process->browser_policy_connector();
+ return new ConfigurationPolicyReader(
+ connector->GetManagedCloudProvider(), PolicyStatusInfo::MANDATORY);
+}
+
+// static
+ConfigurationPolicyReader*
+ ConfigurationPolicyReader::CreateRecommendedPlatformPolicyReader() {
+ BrowserPolicyConnector* connector =
+ g_browser_process->browser_policy_connector();
+ return new ConfigurationPolicyReader(
+ connector->GetRecommendedPlatformProvider(),
+ PolicyStatusInfo::RECOMMENDED);
+}
+
+// static
+ConfigurationPolicyReader*
+ ConfigurationPolicyReader::CreateRecommendedCloudPolicyReader() {
+ BrowserPolicyConnector* connector =
+ g_browser_process->browser_policy_connector();
+ return new ConfigurationPolicyReader(
+ connector->GetRecommendedCloudProvider(), PolicyStatusInfo::RECOMMENDED);
+}
+
+DictionaryValue* ConfigurationPolicyReader::GetPolicyStatus(
+ ConfigurationPolicyType policy) const {
+ return policy_keeper_->GetPolicyStatus(policy);
+}
+
+ConfigurationPolicyReader::ConfigurationPolicyReader(
+ ConfigurationPolicyProvider* provider,
+ PolicyStatusInfo::PolicyLevel policy_level)
+ : provider_(provider),
+ policy_level_(policy_level) {
+ if (provider_) {
+ // Read initial policy.
+ policy_keeper_.reset(
+ new ConfigurationPolicyStatusKeeper(provider, policy_level));
+ registrar_.Init(provider_, this);
+ }
+}
+
+ConfigurationPolicyReader::ConfigurationPolicyReader()
+ : provider_(NULL),
+ policy_level_(PolicyStatusInfo::LEVEL_UNDEFINED),
+ policy_keeper_(NULL) {
+}
+
+void ConfigurationPolicyReader::Refresh() {
+ if (!provider_)
+ return;
+
+ // Read policy state into a new keeper and swap out old keeper.
+ scoped_ptr<ConfigurationPolicyStatusKeeper> new_keeper(
+ new ConfigurationPolicyStatusKeeper(provider_, policy_level_));
+ policy_keeper_.reset(new_keeper.release());
+}
+
+// PolicyStatus
+PolicyStatus::PolicyStatus(ConfigurationPolicyReader* managed_platform,
+ ConfigurationPolicyReader* managed_cloud,
+ ConfigurationPolicyReader* recommended_platform,
+ ConfigurationPolicyReader* recommended_cloud)
+ : managed_platform_(managed_platform),
+ managed_cloud_(managed_cloud),
+ recommended_platform_(recommended_platform),
+ recommended_cloud_(recommended_cloud) {
+}
+
+PolicyStatus::~PolicyStatus() {
+}
+
+ListValue* PolicyStatus::GetPolicyStatusList(bool* any_policies_sent) const {
+ ListValue* result = new ListValue();
+ std::vector<DictionaryValue*> unsent_policies;
+
+ *any_policies_sent = false;
+ const PolicyDefinitionList* supported_policies =
+ ConfigurationPolicyPrefStore::GetChromePolicyDefinitionList();
+ const PolicyDefinitionList::Entry* policy = supported_policies->begin;
+ for ( ; policy != supported_policies->end; ++policy) {
+ if (!AddPolicyFromReaders(policy->policy_type, result)) {
+ PolicyStatusInfo info(ASCIIToUTF16(policy->name),
+ PolicyStatusInfo::SOURCE_TYPE_UNDEFINED,
+ PolicyStatusInfo::LEVEL_UNDEFINED,
+ Value::CreateNullValue(),
+ PolicyStatusInfo::STATUS_UNDEFINED,
+ string16());
+ unsent_policies.push_back(info.GetDictionaryValue());
+ } else {
+ *any_policies_sent = true;
+ }
+ }
+
+ // Add policies that weren't actually sent from providers to list.
+ std::vector<DictionaryValue*>::const_iterator info = unsent_policies.begin();
+ for ( ; info != unsent_policies.end(); ++info)
+ result->Append(*info);
+
+ return result;
+}
+
+// static
+string16 PolicyStatus::GetPolicyName(ConfigurationPolicyType policy_type) {
+ static std::map<ConfigurationPolicyType, string16> name_map;
+ static const ConfigurationPolicyProvider::PolicyDefinitionList*
+ supported_policies;
+
+ if (!supported_policies) {
+ supported_policies =
+ ConfigurationPolicyPrefStore::GetChromePolicyDefinitionList();
+
+ // Create mapping from ConfigurationPolicyTypes to actual policy names.
+ const ConfigurationPolicyProvider::PolicyDefinitionList::Entry* entry =
+ supported_policies->begin;
+ for ( ; entry != supported_policies->end; ++entry)
+ name_map[entry->policy_type] = ASCIIToUTF16(entry->name);
+ }
+
+ std::map<ConfigurationPolicyType, string16>::const_iterator entry =
+ name_map.find(policy_type);
+
+ if (entry == name_map.end())
+ return string16();
+
+ return entry->second;
+}
+
+bool PolicyStatus::AddPolicyFromReaders(
+ ConfigurationPolicyType policy, ListValue* list) const {
+ DictionaryValue* mp_policy =
+ managed_platform_->GetPolicyStatus(policy);
+ DictionaryValue* mc_policy =
+ managed_cloud_->GetPolicyStatus(policy);
+ DictionaryValue* rp_policy =
+ recommended_platform_->GetPolicyStatus(policy);
+ DictionaryValue* rc_policy =
+ recommended_cloud_->GetPolicyStatus(policy);
+
+ bool added_policy = mp_policy || mc_policy || rp_policy || rc_policy;
+
+ if (mp_policy)
+ list->Append(mp_policy);
+ if (mc_policy)
+ list->Append(mc_policy);
+ if (rp_policy)
+ list->Append(rp_policy);
+ if (rc_policy)
+ list->Append(rc_policy);
+
+ return added_policy;
+}
+
+} // namespace policy
diff --git a/chrome/browser/policy/configuration_policy_reader.h b/chrome/browser/policy/configuration_policy_reader.h
new file mode 100644
index 0000000..372ff28
--- /dev/null
+++ b/chrome/browser/policy/configuration_policy_reader.h
@@ -0,0 +1,120 @@
+// Copyright (c) 2011 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.
+
+#ifndef CHROME_BROWSER_POLICY_CONFIGURATION_POLICY_READER_H_
+#define CHROME_BROWSER_POLICY_CONFIGURATION_POLICY_READER_H_
+#pragma once
+
+#include "base/scoped_ptr.h"
+#include "base/values.h"
+#include "chrome/browser/policy/configuration_policy_provider.h"
+#include "chrome/browser/policy/policy_status_info.h"
+
+namespace policy {
+
+class ConfigurationPolicyStatusKeeper;
+
+// This class reads policy information from a ConfigurationPolicyProvider in
+// order to determine the status of a policy (this includes its value and
+// whether it could be enforced on the client or not), as required by the
+// about:policy UI.
+class ConfigurationPolicyReader : public ConfigurationPolicyProvider::Observer {
+ public:
+ ConfigurationPolicyReader(ConfigurationPolicyProvider* provider,
+ PolicyStatusInfo::PolicyLevel policy_level);
+ virtual ~ConfigurationPolicyReader();
+
+ // ConfigurationPolicyProvider::Observer methods:
+ virtual void OnUpdatePolicy();
+ virtual void OnProviderGoingAway();
+
+ // Creates a ConfigurationPolicyReader that reads managed platform policy.
+ static ConfigurationPolicyReader*
+ CreateManagedPlatformPolicyReader();
+
+ // Creates a ConfigurationPolicyReader that reads managed cloud policy.
+ static ConfigurationPolicyReader*
+ CreateManagedCloudPolicyReader();
+
+ // Creates a ConfigurationPolicyReader that reads recommended platform policy.
+ static ConfigurationPolicyReader*
+ CreateRecommendedPlatformPolicyReader();
+
+ // Creates a ConfigurationPolicyReader that reads recommended cloud policy.
+ 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
+ // caller. Returns NULL if the reader is not aware of the given policy.
+ virtual DictionaryValue*
+ GetPolicyStatus(ConfigurationPolicyType policy) const;
+
+ private:
+ friend class MockConfigurationPolicyReader;
+
+ // Only used in tests.
+ ConfigurationPolicyReader();
+
+ // Updates the policy information held in this reader. This is called when
+ // the ConfigurationPolicyProvider is updated.
+ void Refresh();
+
+ // The policy provider from which policy settings are read.
+ ConfigurationPolicyProvider* provider_;
+
+ // Whether this ConfigurationPolicyReader contains managed policies.
+ PolicyStatusInfo::PolicyLevel policy_level_;
+
+ // Current policy status.
+ scoped_ptr<ConfigurationPolicyStatusKeeper> policy_keeper_;
+
+ ConfigurationPolicyObserverRegistrar registrar_;
+
+ DISALLOW_COPY_AND_ASSIGN(ConfigurationPolicyReader);
+};
+
+// This class combines the policy information from different
+// ConfigurationPolicyReaders into a single list of policy information that the
+// about:policy UI can display.
+class PolicyStatus {
+ public:
+ PolicyStatus(ConfigurationPolicyReader* managed_platform,
+ ConfigurationPolicyReader* managed_cloud,
+ ConfigurationPolicyReader* recommended_platform,
+ ConfigurationPolicyReader* recommended_cloud);
+ ~PolicyStatus();
+
+ // Returns a ListValue pointer containing the status information of all
+ // policies supported by the client. |any_policies_sent| 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;
+
+ // 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
+ // among the policies supported by the client.
+ static string16 GetPolicyName(ConfigurationPolicyType policy_type);
+
+ private:
+ typedef ConfigurationPolicyProvider::PolicyDefinitionList
+ PolicyDefinitionList;
+
+ // Add the policy information for |policy| to the ListValue pointed to be
+ // |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;
+
+ scoped_ptr<ConfigurationPolicyReader> managed_platform_;
+ scoped_ptr<ConfigurationPolicyReader> managed_cloud_;
+ scoped_ptr<ConfigurationPolicyReader> recommended_platform_;
+ scoped_ptr<ConfigurationPolicyReader> recommended_cloud_;
+
+ DISALLOW_COPY_AND_ASSIGN(PolicyStatus);
+};
+
+} // namespace policy
+
+#endif // CHROME_BROWSER_POLICY_CONFIGURATION_POLICY_READER_H_
diff --git a/chrome/browser/policy/configuration_policy_reader_unittest.cc b/chrome/browser/policy/configuration_policy_reader_unittest.cc
new file mode 100644
index 0000000..f7164a4
--- /dev/null
+++ b/chrome/browser/policy/configuration_policy_reader_unittest.cc
@@ -0,0 +1,352 @@
+// Copyright (c) 2011 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.
+
+#include "base/scoped_ptr.h"
+#include "base/string16.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/policy/configuration_policy_pref_store.h"
+#include "chrome/browser/policy/configuration_policy_reader.h"
+#include "chrome/browser/policy/mock_configuration_policy_provider.h"
+#include "chrome/browser/policy/mock_configuration_policy_reader.h"
+#include "policy/policy_constants.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using ::testing::Return;
+using ::testing::ReturnNull;
+using ::testing::_;
+
+namespace policy {
+
+class ConfigurationPolicyReaderTest : public testing::Test {
+ protected:
+ ConfigurationPolicyReaderTest() : provider_() {
+ managed_reader_.reset(
+ new ConfigurationPolicyReader(&provider_, PolicyStatusInfo::MANDATORY));
+ recommended_reader_.reset(new ConfigurationPolicyReader(&provider_,
+ PolicyStatusInfo::RECOMMENDED));
+ status_ok_ = ASCIIToUTF16("ok");
+ }
+
+ DictionaryValue* CreateDictionary(const char* policy_name,
+ Value* policy_value) {
+ DictionaryValue* dict = new DictionaryValue();
+ dict->SetString(
+ PolicyStatusInfo::kNameDictPath, ASCIIToUTF16(policy_name));
+ dict->SetString(PolicyStatusInfo::kLevelDictPath,
+ PolicyStatusInfo::GetPolicyLevelString(PolicyStatusInfo::MANDATORY));
+ dict->SetString(PolicyStatusInfo::kSourceTypeDictPath,
+ PolicyStatusInfo::GetSourceTypeString(PolicyStatusInfo::USER));
+ dict->Set(PolicyStatusInfo::kValueDictPath, policy_value);
+ dict->SetBoolean(PolicyStatusInfo::kSetDictPath, true);
+ dict->SetString(PolicyStatusInfo::kStatusDictPath, status_ok_);
+
+ return dict;
+ }
+
+ MockConfigurationPolicyProvider provider_;
+ scoped_ptr<ConfigurationPolicyReader> managed_reader_;
+ scoped_ptr<ConfigurationPolicyReader> recommended_reader_;
+ string16 status_ok_;
+};
+
+TEST_F(ConfigurationPolicyReaderTest, GetDefault) {
+ EXPECT_EQ(NULL, managed_reader_->GetPolicyStatus(kPolicyHomepageLocation));
+}
+
+// Test for list-valued policy settings.
+TEST_F(ConfigurationPolicyReaderTest, SetListValue) {
+ ListValue* in_value = new ListValue();
+ in_value->Append(Value::CreateStringValue("test1"));
+ in_value->Append(Value::CreateStringValue("test2"));
+ provider_.AddPolicy(kPolicyRestoreOnStartupURLs, in_value);
+ managed_reader_->OnUpdatePolicy();
+
+ scoped_ptr<DictionaryValue>
+ dict(CreateDictionary(key::kRestoreOnStartupURLs, in_value->DeepCopy()));
+ scoped_ptr<DictionaryValue> result(
+ managed_reader_->GetPolicyStatus(kPolicyRestoreOnStartupURLs));
+ EXPECT_TRUE(dict->Equals(result.get()));
+
+ recommended_reader_->OnUpdatePolicy();
+ dict->SetString("level",
+ PolicyStatusInfo::GetPolicyLevelString(PolicyStatusInfo::RECOMMENDED));
+ result.reset(
+ recommended_reader_->GetPolicyStatus(kPolicyRestoreOnStartupURLs));
+ EXPECT_TRUE(dict->Equals(result.get()));
+}
+
+// Test for string-valued policy settings.
+TEST_F(ConfigurationPolicyReaderTest, SetStringValue) {
+ provider_.AddPolicy(kPolicyHomepageLocation,
+ Value::CreateStringValue("http://chromium.org"));
+ managed_reader_->OnUpdatePolicy();
+ scoped_ptr<DictionaryValue> dict(CreateDictionary(key::kHomepageLocation,
+ Value::CreateStringValue("http://chromium.org")));
+ scoped_ptr<DictionaryValue> result(
+ managed_reader_->GetPolicyStatus(kPolicyHomepageLocation));
+ EXPECT_TRUE(dict->Equals(result.get()));
+
+ recommended_reader_->OnUpdatePolicy();
+ dict->SetString("level",
+ PolicyStatusInfo::GetPolicyLevelString(PolicyStatusInfo::RECOMMENDED));
+ result.reset(
+ recommended_reader_->GetPolicyStatus(kPolicyHomepageLocation));
+ EXPECT_TRUE(dict->Equals(result.get()));
+}
+
+// Test for boolean-valued policy settings.
+TEST_F(ConfigurationPolicyReaderTest, SetBooleanValue) {
+ provider_.AddPolicy(kPolicyShowHomeButton, Value::CreateBooleanValue(true));
+ managed_reader_->OnUpdatePolicy();
+ scoped_ptr<DictionaryValue> dict(CreateDictionary(key::kShowHomeButton,
+ Value::CreateBooleanValue(true)));
+ scoped_ptr<DictionaryValue> result(
+ managed_reader_->GetPolicyStatus(kPolicyShowHomeButton));
+ EXPECT_TRUE(dict->Equals(result.get()));
+
+ recommended_reader_->OnUpdatePolicy();
+ dict->SetString("level",
+ PolicyStatusInfo::GetPolicyLevelString(PolicyStatusInfo::RECOMMENDED));
+ result.reset(recommended_reader_->GetPolicyStatus(kPolicyShowHomeButton));
+ EXPECT_TRUE(dict->Equals(result.get()));
+
+ provider_.AddPolicy(kPolicyShowHomeButton, Value::CreateBooleanValue(false));
+ managed_reader_->OnUpdatePolicy();
+ dict->Set(
+ PolicyStatusInfo::kValueDictPath, Value::CreateBooleanValue(false));
+ dict->SetString("level",
+ PolicyStatusInfo::GetPolicyLevelString(PolicyStatusInfo::MANDATORY));
+ result.reset(managed_reader_->GetPolicyStatus(kPolicyShowHomeButton));
+ EXPECT_TRUE(dict->Equals(result.get()));
+
+ recommended_reader_->OnUpdatePolicy();
+ dict->SetString("level",
+ PolicyStatusInfo::GetPolicyLevelString(PolicyStatusInfo::RECOMMENDED));
+ result.reset(recommended_reader_->GetPolicyStatus(kPolicyShowHomeButton));
+ EXPECT_TRUE(dict->Equals(result.get()));
+}
+
+// Test for integer-valued policy settings.
+TEST_F(ConfigurationPolicyReaderTest, SetIntegerValue) {
+ provider_.AddPolicy(kPolicyRestoreOnStartup, Value::CreateIntegerValue(3));
+ managed_reader_->OnUpdatePolicy();
+ scoped_ptr<DictionaryValue> dict(CreateDictionary(key::kRestoreOnStartup,
+ Value::CreateIntegerValue(3)));
+ scoped_ptr<DictionaryValue> result(
+ managed_reader_->GetPolicyStatus(kPolicyRestoreOnStartup));
+ EXPECT_TRUE(dict->Equals(result.get()));
+
+ recommended_reader_->OnUpdatePolicy();
+ dict->SetString("level",
+ PolicyStatusInfo::GetPolicyLevelString(PolicyStatusInfo::RECOMMENDED));
+ result.reset(recommended_reader_->GetPolicyStatus(kPolicyRestoreOnStartup));
+ EXPECT_TRUE(dict->Equals(result.get()));
+}
+
+class PolicyStatusTest : public testing::Test {
+ protected:
+ typedef ConfigurationPolicyProvider::PolicyDefinitionList
+ PolicyDefinitionList;
+
+ PolicyStatusTest() {
+ managed_platform_ = new MockConfigurationPolicyReader();
+ managed_cloud_ = new MockConfigurationPolicyReader();
+ recommended_platform_ = new MockConfigurationPolicyReader();
+ recommended_cloud_ = new MockConfigurationPolicyReader();
+
+ policy_status_.reset(new PolicyStatus(managed_platform_,
+ managed_cloud_,
+ recommended_platform_,
+ recommended_cloud_));
+ status_ok_ = ASCIIToUTF16("ok");
+
+ policy_list_ =
+ ConfigurationPolicyPrefStore::GetChromePolicyDefinitionList();
+ policy_list_size_ =
+ static_cast<size_t>(policy_list_->end - policy_list_->begin);
+ }
+
+ void DontSendPolicies() {
+ EXPECT_CALL(*managed_platform_, GetPolicyStatus(_))
+ .WillRepeatedly(ReturnNull());
+ EXPECT_CALL(*managed_cloud_, GetPolicyStatus(_))
+ .WillRepeatedly(ReturnNull());
+ EXPECT_CALL(*recommended_platform_, GetPolicyStatus(_))
+ .WillRepeatedly(ReturnNull());
+ EXPECT_CALL(*recommended_cloud_, GetPolicyStatus(_))
+ .WillRepeatedly(ReturnNull());
+ }
+
+ void SendPolicies() {
+ EXPECT_CALL(*managed_platform_, GetPolicyStatus(_))
+ .WillRepeatedly(ReturnNull());
+ EXPECT_CALL(*managed_cloud_, GetPolicyStatus(_))
+ .WillRepeatedly(ReturnNull());
+ EXPECT_CALL(*recommended_platform_, GetPolicyStatus(_))
+ .WillRepeatedly(ReturnNull());
+ EXPECT_CALL(*recommended_cloud_, GetPolicyStatus(_))
+ .WillRepeatedly(ReturnNull());
+
+ EXPECT_CALL(*managed_platform_, GetPolicyStatus(kPolicyInstantEnabled))
+ .WillRepeatedly(Return(CreateDictionary(key::kInstantEnabled,
+ PolicyStatusInfo::MANDATORY)));
+ EXPECT_CALL(*managed_cloud_, GetPolicyStatus(kPolicyDisablePluginFinder))
+ .WillRepeatedly(Return(CreateDictionary(key::kDisablePluginFinder,
+ PolicyStatusInfo::MANDATORY)));
+ EXPECT_CALL(*recommended_platform_, GetPolicyStatus(kPolicySyncDisabled))
+ .WillRepeatedly(
+ Return(CreateDictionary(key::kSyncDisabled,
+ PolicyStatusInfo::RECOMMENDED)));
+ EXPECT_CALL(*recommended_cloud_, GetPolicyStatus(kPolicyTranslateEnabled))
+ .WillRepeatedly(
+ Return(CreateDictionary(key::kTranslateEnabled,
+ PolicyStatusInfo::RECOMMENDED)));
+ }
+
+ DictionaryValue* CreateDictionary(const char* name,
+ PolicyStatusInfo::PolicyLevel level) {
+ DictionaryValue* value = new DictionaryValue();
+ value->SetString(PolicyStatusInfo::kNameDictPath, ASCIIToUTF16(name));
+ value->SetString(PolicyStatusInfo::kLevelDictPath,
+ PolicyStatusInfo::GetPolicyLevelString(level));
+ value->SetString(PolicyStatusInfo::kSourceTypeDictPath,
+ PolicyStatusInfo::GetSourceTypeString(
+ PolicyStatusInfo::USER));
+ value->SetBoolean(PolicyStatusInfo::kValueDictPath, true);
+ value->SetBoolean(PolicyStatusInfo::kSetDictPath, true);
+ value->SetString(PolicyStatusInfo::kStatusDictPath, status_ok_);
+
+ return value;
+ }
+
+ void SetDictionaryPaths(DictionaryValue* dict,
+ const char* policy_name,
+ bool defined,
+ PolicyStatusInfo::PolicyLevel level) {
+ dict->SetString(PolicyStatusInfo::kNameDictPath,
+ ASCIIToUTF16(policy_name));
+ if (defined) {
+ dict->SetString(PolicyStatusInfo::kLevelDictPath,
+ PolicyStatusInfo::GetPolicyLevelString(level));
+ }
+ }
+
+ MockConfigurationPolicyReader* managed_platform_;
+ MockConfigurationPolicyReader* managed_cloud_;
+ MockConfigurationPolicyReader* recommended_platform_;
+ MockConfigurationPolicyReader* recommended_cloud_;
+ scoped_ptr<PolicyStatus> policy_status_;
+ const PolicyDefinitionList* policy_list_;
+ size_t policy_list_size_;
+ string16 status_ok_;
+};
+
+TEST_F(PolicyStatusTest, GetPolicyStatusListNoSetPolicies) {
+ DontSendPolicies();
+ bool any_policies_sent;
+ scoped_ptr<ListValue> status_list(
+ policy_status_->GetPolicyStatusList(&any_policies_sent));
+ EXPECT_FALSE(any_policies_sent);
+ EXPECT_EQ(policy_list_size_, status_list->GetSize());
+}
+
+TEST_F(PolicyStatusTest, GetPolicyStatusListSetPolicies) {
+ SendPolicies();
+ bool any_policies_sent;
+ scoped_ptr<ListValue> status_list(
+ policy_status_->GetPolicyStatusList(&any_policies_sent));
+ EXPECT_TRUE(any_policies_sent);
+ EXPECT_EQ(policy_list_size_, status_list->GetSize());
+
+ scoped_ptr<DictionaryValue> undefined_dict(new DictionaryValue());
+ undefined_dict->SetString(PolicyStatusInfo::kLevelDictPath,
+ PolicyStatusInfo::GetPolicyLevelString(
+ PolicyStatusInfo::LEVEL_UNDEFINED));
+ undefined_dict->SetString(PolicyStatusInfo::kSourceTypeDictPath,
+ PolicyStatusInfo::GetSourceTypeString(
+ PolicyStatusInfo::SOURCE_TYPE_UNDEFINED));
+ undefined_dict->Set(PolicyStatusInfo::kValueDictPath,
+ Value::CreateNullValue());
+ undefined_dict->SetBoolean(PolicyStatusInfo::kSetDictPath, false);
+ undefined_dict->SetString(PolicyStatusInfo::kStatusDictPath, string16());
+
+ scoped_ptr<DictionaryValue> defined_dict(new DictionaryValue());
+ defined_dict->SetString(PolicyStatusInfo::kSourceTypeDictPath,
+ PolicyStatusInfo::GetSourceTypeString(
+ PolicyStatusInfo::USER));
+ defined_dict->Set(PolicyStatusInfo::kValueDictPath,
+ Value::CreateBooleanValue(true));
+ defined_dict->SetBoolean(PolicyStatusInfo::kSetDictPath, true);
+ defined_dict->SetString(PolicyStatusInfo::kStatusDictPath, status_ok_);
+
+ for (const PolicyDefinitionList::Entry* entry = policy_list_->begin;
+ entry != policy_list_->end; ++entry) {
+ Value* status_dict = NULL;
+
+ // Every policy in |policy_list_| has to appear in the returned ListValue.
+ string16 name = ASCIIToUTF16(entry->name);
+ for (ListValue::const_iterator status_entry = status_list->begin();
+ status_entry != status_list->end();
+ ++status_entry) {
+ string16 value;
+ ASSERT_TRUE((*status_entry)->IsType(Value::TYPE_DICTIONARY));
+ DictionaryValue* dict = static_cast<DictionaryValue*>(*status_entry);
+ ASSERT_TRUE(dict->GetString(PolicyStatusInfo::kNameDictPath, &value));
+
+ if (value == name) {
+ status_dict = *status_entry;
+ }
+ }
+
+ ASSERT_FALSE(status_dict == NULL);
+
+ switch (entry->policy_type) {
+ case kPolicyInstantEnabled:
+ SetDictionaryPaths(defined_dict.get(),
+ entry->name,
+ true,
+ PolicyStatusInfo::MANDATORY);
+ EXPECT_TRUE(defined_dict->Equals(status_dict));
+ break;
+ case kPolicyDisablePluginFinder:
+ SetDictionaryPaths(defined_dict.get(),
+ entry->name,
+ true,
+ PolicyStatusInfo::MANDATORY);
+ EXPECT_TRUE(defined_dict->Equals(status_dict));
+ break;
+ case kPolicySyncDisabled:
+ SetDictionaryPaths(defined_dict.get(),
+ entry->name,
+ true,
+ PolicyStatusInfo::RECOMMENDED);
+ EXPECT_TRUE(defined_dict->Equals(status_dict));
+ break;
+ case kPolicyTranslateEnabled:
+ SetDictionaryPaths(defined_dict.get(),
+ entry->name,
+ true,
+ PolicyStatusInfo::RECOMMENDED);
+ EXPECT_TRUE(defined_dict->Equals(status_dict));
+ break;
+ default:
+ SetDictionaryPaths(undefined_dict.get(),
+ entry->name,
+ false,
+ PolicyStatusInfo::LEVEL_UNDEFINED);
+ EXPECT_TRUE(undefined_dict->Equals(status_dict));
+ break;
+ }
+ }
+}
+
+TEST_F(PolicyStatusTest, GetPolicyName) {
+ for (const PolicyDefinitionList::Entry* entry = policy_list_->begin;
+ entry != policy_list_->end; ++entry) {
+ EXPECT_EQ(ASCIIToUTF16(entry->name),
+ PolicyStatus::GetPolicyName(entry->policy_type));
+ }
+}
+
+} // namespace policy
diff --git a/chrome/browser/policy/mock_configuration_policy_reader.cc b/chrome/browser/policy/mock_configuration_policy_reader.cc
new file mode 100644
index 0000000..ccfb6f1
--- /dev/null
+++ b/chrome/browser/policy/mock_configuration_policy_reader.cc
@@ -0,0 +1,13 @@
+// Copyright (c) 2011 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.
+
+#include "chrome/browser/policy/mock_configuration_policy_reader.h"
+
+namespace policy {
+
+MockConfigurationPolicyReader::MockConfigurationPolicyReader() {}
+
+MockConfigurationPolicyReader::~MockConfigurationPolicyReader() {}
+
+} // namespace policy
diff --git a/chrome/browser/policy/mock_configuration_policy_reader.h b/chrome/browser/policy/mock_configuration_policy_reader.h
new file mode 100644
index 0000000..f94e4a3
--- /dev/null
+++ b/chrome/browser/policy/mock_configuration_policy_reader.h
@@ -0,0 +1,28 @@
+// Copyright (c) 2011 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.
+
+#ifndef CHROME_BROWSER_POLICY_MOCK_CONFIGURATION_POLICY_READER_H_
+#define CHROME_BROWSER_POLICY_MOCK_CONFIGURATION_POLICY_READER_H_
+#pragma once
+
+#include "chrome/browser/policy/configuration_policy_reader.h"
+
+#include "base/values.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+namespace policy {
+
+// Mock ConfigurationPolicyReader implementation.
+class MockConfigurationPolicyReader : public ConfigurationPolicyReader {
+ public:
+ MockConfigurationPolicyReader();
+ virtual ~MockConfigurationPolicyReader();
+
+ MOCK_CONST_METHOD1(GetPolicyStatus,
+ DictionaryValue*(ConfigurationPolicyType policy));
+};
+
+} // namespace policy
+
+#endif // CHROME_BROWSER_POLICY_MOCK_CONFIGURATION_POLICY_READER_H_
diff --git a/chrome/browser/policy/policy_status_info.cc b/chrome/browser/policy/policy_status_info.cc
new file mode 100644
index 0000000..e2fdc00
--- /dev/null
+++ b/chrome/browser/policy/policy_status_info.cc
@@ -0,0 +1,86 @@
+// Copyright (c) 2011 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.
+
+#include "chrome/browser/policy/policy_status_info.h"
+
+#include <algorithm>
+
+#include "base/logging.h"
+#include "base/utf_string_conversions.h"
+
+namespace policy {
+
+const std::string PolicyStatusInfo::kLevelDictPath = "level";
+const std::string PolicyStatusInfo::kNameDictPath = "name";
+const std::string PolicyStatusInfo::kSetDictPath = "set";
+const std::string PolicyStatusInfo::kSourceTypeDictPath = "sourceType";
+const std::string PolicyStatusInfo::kStatusDictPath = "status";
+const std::string PolicyStatusInfo::kValueDictPath = "value";
+
+// PolicyStatusInfo
+PolicyStatusInfo::PolicyStatusInfo() {
+}
+
+PolicyStatusInfo::PolicyStatusInfo(
+ string16 name,
+ PolicySourceType source_type,
+ PolicyLevel level,
+ Value* value,
+ PolicyStatus status,
+ string16 error_message)
+ : name(name),
+ source_type(source_type),
+ level(level),
+ value(value),
+ status(status),
+ error_message(error_message) {
+}
+
+PolicyStatusInfo::~PolicyStatusInfo() {
+}
+
+DictionaryValue* PolicyStatusInfo::GetDictionaryValue() const {
+ string16 level_string = GetPolicyLevelString(level);
+ string16 source_type_string = GetSourceTypeString(source_type);
+ string16 status_message = status == ENFORCED ? ASCIIToUTF16("ok")
+ : error_message;
+ DictionaryValue* result = new DictionaryValue();
+ result->SetString(kNameDictPath, name);
+ result->SetString(kLevelDictPath, level_string);
+ result->SetString(kSourceTypeDictPath, source_type_string);
+ result->Set(kValueDictPath, value->DeepCopy());
+ result->SetBoolean(kSetDictPath, level != LEVEL_UNDEFINED);
+ result->SetString(kStatusDictPath, status_message);
+
+ return result;
+}
+
+bool PolicyStatusInfo::Equals(const PolicyStatusInfo* other_info) const {
+ return name == other_info->name &&
+ source_type == other_info->source_type &&
+ level == other_info->level &&
+ value->Equals(other_info->value.get()) &&
+ status == other_info->status &&
+ error_message == other_info->error_message;
+}
+
+// static
+string16 PolicyStatusInfo::GetSourceTypeString(PolicySourceType source_type) {
+ static string16 strings[] = { ASCIIToUTF16("user"),
+ ASCIIToUTF16("device"),
+ ASCIIToUTF16("undefined") };
+ DCHECK(static_cast<size_t>(source_type) < arraysize(strings));
+ return strings[source_type];
+}
+
+// static
+string16 PolicyStatusInfo::GetPolicyLevelString(PolicyLevel level) {
+ static string16 strings[] = { ASCIIToUTF16("mandatory"),
+ ASCIIToUTF16("recommended"),
+ ASCIIToUTF16("undefined") };
+ DCHECK(static_cast<size_t>(level) < arraysize(strings));
+ return strings[level];
+}
+
+} // namespace policy
diff --git a/chrome/browser/policy/policy_status_info.h b/chrome/browser/policy/policy_status_info.h
new file mode 100644
index 0000000..ab1726e
--- /dev/null
+++ b/chrome/browser/policy/policy_status_info.h
@@ -0,0 +1,97 @@
+ // Copyright (c) 2011 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.
+
+#ifndef CHROME_BROWSER_POLICY_POLICY_STATUS_INFO_H_
+#define CHROME_BROWSER_POLICY_POLICY_STATUS_INFO_H_
+
+#include <map>
+#include <string>
+
+#include "base/scoped_ptr.h"
+#include "base/string16.h"
+#include "base/values.h"
+#include "policy/configuration_policy_type.h"
+
+namespace policy {
+
+// Describes a policy's status on the client.
+struct PolicyStatusInfo {
+
+ // Defines the possible sources a policy can have.
+ enum PolicySourceType {
+ USER,
+ DEVICE,
+ SOURCE_TYPE_UNDEFINED,
+ };
+
+ // Defines the possible levels a policy can be operating on.
+ enum PolicyLevel {
+ MANDATORY,
+ RECOMMENDED,
+ LEVEL_UNDEFINED,
+ };
+
+ // Defines the possible statuses a policy can have.
+ enum PolicyStatus {
+ ENFORCED,
+ FAILED,
+ STATUS_UNDEFINED,
+ };
+
+ PolicyStatusInfo();
+ PolicyStatusInfo(string16 name,
+ PolicySourceType source_type,
+ PolicyLevel level,
+ Value* value,
+ PolicyStatus status,
+ string16 error_message);
+ ~PolicyStatusInfo();
+
+ // Returns a DictionaryValue pointer containing the information in the object
+ // for UI purposes. The caller acquires ownership of the returned value.
+ DictionaryValue* GetDictionaryValue() const;
+
+ // Returns true if this PolicyStatusInfo object and |other_info| have equal
+ // contents and false otherwise.
+ bool Equals(const PolicyStatusInfo* other_info) const;
+
+ // Returns the string corresponding to the PolicySourceType enum value
+ // |source_type|.
+ static string16 GetSourceTypeString(PolicySourceType source_type);
+
+ // Returns the string corresponding to the PolicyLevel enum value |level|.
+ static string16 GetPolicyLevelString(PolicyLevel level);
+
+ // The name of the policy.
+ string16 name;
+
+ // The source type of the policy (user, device or undefined).
+ PolicySourceType source_type;
+
+ // The level of the policy (mandatory, recommended or undefined).
+ PolicyLevel level;
+
+ // The policy value.
+ scoped_ptr<Value> value;
+
+ // The policy status (details whether the policy was successfully enforced).
+ PolicyStatus status;
+
+ // An error message in cases where the policy could not be enforced.
+ string16 error_message;
+
+ // Paths for the DictionaryValue returned by GetDictionaryValue().
+ static const std::string kLevelDictPath;
+ static const std::string kNameDictPath;
+ static const std::string kSetDictPath;
+ static const std::string kSourceTypeDictPath;
+ static const std::string kStatusDictPath;
+ static const std::string kValueDictPath;
+
+ DISALLOW_COPY_AND_ASSIGN(PolicyStatusInfo);
+};
+
+} // namespace policy
+
+#endif // CHROME_BROWSER_POLICY_POLICY_STATUS_INFO_H_
diff --git a/chrome/browser/resources/policy.css b/chrome/browser/resources/policy.css
new file mode 100644
index 0000000..2fa9a1b
--- /dev/null
+++ b/chrome/browser/resources/policy.css
@@ -0,0 +1,143 @@
+body {
+ color: black;
+ cursor: default;
+ font-family: Arial, sans-serif;
+ font-size: 14px;
+ margin: 0 10px;
+ min-width: 47em;
+}
+
+button {
+ font-size: 0.9em;
+}
+
+#header {
+ border-bottom: 1px solid #000;
+ padding-top: 20px;
+}
+
+#about-policy-title {
+ -webkit-padding-end: 24px;
+ -webkit-user-select: none;
+ border-bottom: 1px solid #c6c9ce;
+ color: #53637d;
+ cursor: pointer;
+ font-size: 200%;
+ font-weight: normal;
+ margin: 0;
+ padding-bottom: 14px;
+ padding-top: 13px;
+ text-shadow: white 0 1px 2px;
+}
+
+#main-content {
+ min-height: 100%;
+}
+
+#status-title,
+#policies-title {
+ font-size: 120%;
+ font-weight: bold;
+ width: 65%;
+}
+
+section {
+ border-bottom: 1px solid #eee;
+ margin-top: 17px;
+ padding-bottom: 20px;
+ width: 100%;
+}
+
+.separator {
+ -webkit-box-orient: horizontal;
+ display: -webkit-box;
+}
+
+#fetch-policies,
+#unsent-policies-control {
+ -webkit-box-flex: 1;
+}
+
+#fetch-policies,
+#unsent-policies-control,
+#search {
+ bottom: 3px;
+ position: relative;
+}
+
+#fetch-policies {
+ direction: rtl;
+}
+
+#checkbox-and-label {
+ -webkit-padding-end: 20px;
+ float: right;
+}
+
+html[dir='rtl'] #checkbox-and-label {
+ float: left;
+}
+
+#search-field {
+ bottom: 2px;
+ position: relative;
+}
+
+#status-pane {
+ -webkit-box-flex: 1;
+ -webkit-box-orient: horizontal;
+ display: -webkit-box;
+ margin: 0 10%;
+}
+
+.status-box {
+ border: 1px solid #d9d9d9;
+ margin: 20px 100px;
+ min-height: 140px;
+ min-width: 300px;
+ overflow: hidden;
+ padding: 2px;
+ width: 30%;
+}
+
+legend {
+ padding: 0.2em 0.5em;
+}
+
+.status-box ul {
+ -webkit-padding-start: 10px;
+ list-style-type: none;
+}
+
+.status-box li {
+ padding: 3px;
+}
+
+#no-policies-text {
+ font-weight: bold;
+ margin: 20px;
+ text-align: center;
+}
+
+#policy-table {
+ table-layout: fixed;
+ width: 100%;
+}
+
+#policy-table th td {
+ border: 1px solid #fff;
+ border-collapse: collapse;
+}
+
+#policy-table th {
+ background-color: #dadadd;
+ padding: 10px;
+}
+
+#policy-table td {
+ background-color: #eaeef3;
+ overflow: hidden;
+ padding: 10px;
+ text-overflow: ellipsis;
+ width: 20%;
+}
diff --git a/chrome/browser/resources/policy.html b/chrome/browser/resources/policy.html
index 8eb63e1..db547b4 100644
--- a/chrome/browser/resources/policy.html
+++ b/chrome/browser/resources/policy.html
@@ -20,9 +20,6 @@
<h1 id="about-policy-title" i18n-content="policyTitle"></h1>
</div>
<div id="main-content">
- <section id="description-section">
- <p i18n-content="aboutPolicyDescription"></p>
- </section>
<section id="status-section">
<div class="separator">
<span id="status-title" i18n-content="statusPaneTitle"></span>
@@ -65,7 +62,7 @@
</div>
<div id="search">
<input id="search-field" type="search" incremental
- placeholder="Filter policies by name">
+ i18n-values="placeholder: filterPoliciesText">
</div>
</div>
<div>
@@ -73,7 +70,8 @@
<div id="no-policies-text" i18n-content="noPoliciesSet"></div>
</div>
<div id="policies"
- jsvalues=".style.visibility: anyPoliciesSet ? 'visible': 'hidden'">
+ jsvalues=".style.display: anyPoliciesSet ?
+ '': 'none'">
<table id="policy-table">
<tr>
<th i18n-content="appliesToTableHeader"></th>
@@ -82,11 +80,11 @@
<th i18n-content="policyValueTableHeader"></th>
<th i18n-content="policyStatusTableHeader"></th>
</tr>
- <tr jsselect="policies"
- jsvalues=".className: Policy.isPolicySet($this)?
+ <tr jsselect="policies"
+ jsvalues=".className: $this.set ?
'policy-set': 'policy-unset';
.style.display: Policy.shouldDisplayPolicy($this) ?
- 'table-row': 'none'">
+ '': 'none'">
<td>
<span class="policy-type" jscontent="sourceType"></span>
</td>
diff --git a/chrome/browser/resources/policy.js b/chrome/browser/resources/policy.js
new file mode 100644
index 0000000..db4f404
--- /dev/null
+++ b/chrome/browser/resources/policy.js
@@ -0,0 +1,160 @@
+// Copyright (c) 2011 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.
+
+var localStrings = new LocalStrings();
+
+/**
+ * This variable structure is here to document the structure that the template
+ * expects to correctly populate the page.
+ */
+var policyDataformat = {
+ 'policies': [
+ {
+ 'level': 'managed',
+ 'name': 'AllowXYZ',
+ 'set': true,
+ 'sourceType': 'Device',
+ 'status': 'ok',
+ 'value': true,
+ },
+ ],
+ 'anyPoliciesSet': true
+};
+
+cr.define('policies', function() {
+
+ function Policy() {
+ }
+
+ cr.addSingletonGetter(Policy);
+
+ Policy.prototype = {
+
+ /**
+ * True if none of the received policies are actually set, false otherwise.
+ * @type {boolean}
+ */
+ noActivePolicies_: false,
+
+ /**
+ * The current search term for filtering of the policy table.
+ * @type {string}
+ * @private
+ */
+ 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
+ */
+ renderTemplate: function(policyData) {
+ this.noActivePolicies_ = !policyData.anyPoliciesSet;
+
+ // This is the javascript code that processes the template:
+ var input = new JsEvalContext(policyData);
+ var output = $('policiesTemplate');
+ jstProcess(input, output);
+ },
+
+ /**
+ * Filters the table of policies by name.
+ * @param {string} term The search string
+ */
+ 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;
+ if (cellContents.toLowerCase().indexOf(this.searchTerm_) >= 0)
+ row.style.display = 'table-row';
+ else
+ row.style.display = 'none';
+ }
+ },
+
+ /**
+ * Updates the visibility of the policies depending on the state of the
+ * 'toggle-unsent-policies' checkbox.
+ */
+ 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++) {
+ if ($('toggle-unsent-policies').checked)
+ tableRows[i].style.visibility = 'visible';
+ else
+ tableRows[i].style.visibility = 'hidden';
+ }
+
+ // Filter table again in case a search was active.
+ this.filterTable(this.searchTerm_);
+ }
+ };
+
+ /**
+ * Asks the C++ PolicyUIHandler to get details about policies. The
+ * PolicyDOMHandler should reply to returnPolicyData() (below).
+ */
+ Policy.requestPolicyData = function() {
+ chrome.send('requestPolicyData');
+ };
+
+ /**
+ * Called by the C++ PolicyUIHandler when it has the requested policy data.
+ */
+ Policy.returnPolicyData = function(policyData) {
+ Policy.getInstance().renderTemplate(policyData);
+ };
+
+ /**
+ * Determines whether a policy should be visible or not.
+ * @param {policy} policy information in the format given by above the
+ * PolicyDataFormat
+ */
+ Policy.shouldDisplayPolicy = function(policy) {
+ return $('toggle-unsent-policies').checked || policy.set;
+ };
+
+ /**
+ * Initializes the page and loads the list of policies.
+ */
+ Policy.initialize = function() {
+ i18nTemplate.process(document, templateData);
+ Policy.requestPolicyData();
+
+ // Set HTML event handlers.
+ $('toggle-unsent-policies').onchange = function(event) {
+ Policy.getInstance().updatePolicyVisibility();
+ };
+
+ $('search-field').onsearch = function(event) {
+ Policy.getInstance().filterTable(this.value);
+ };
+ };
+
+ // Export
+ return {
+ Policy: Policy
+ };
+});
+
+var Policy = policies.Policy;
+
+// Get data and have it displayed upon loading.
+document.addEventListener('DOMContentLoaded', policies.Policy.initialize);
diff --git a/chrome/browser/ui/webui/chrome_web_ui_factory.cc b/chrome/browser/ui/webui/chrome_web_ui_factory.cc
index 4df28b0..5a788a3 100644
--- a/chrome/browser/ui/webui/chrome_web_ui_factory.cc
+++ b/chrome/browser/ui/webui/chrome_web_ui_factory.cc
@@ -30,6 +30,7 @@
#include "chrome/browser/ui/webui/ntp/new_tab_ui.h"
#include "chrome/browser/ui/webui/options/options_ui.h"
#include "chrome/browser/ui/webui/plugins_ui.h"
+#include "chrome/browser/ui/webui/policy_ui.h"
#include "chrome/browser/ui/webui/print_preview_ui.h"
#include "chrome/browser/ui/webui/quota_internals_ui.h"
#include "chrome/browser/ui/webui/sessions_ui.h"
@@ -195,6 +196,8 @@ static WebUIFactoryFunction GetWebUIFactoryFunction(Profile* profile,
return &NewWebUI<NetInternalsUI>;
if (url.host() == chrome::kChromeUIPluginsHost)
return &NewWebUI<PluginsUI>;
+ if (url.host() == chrome::kChromeUIPolicyHost)
+ return &NewWebUI<PolicyUI>;
if (url.host() == chrome::kChromeUISessionsHost)
return &NewWebUI<SessionsUI>;
if (url.host() == chrome::kChromeUISyncInternalsHost)
diff --git a/chrome/browser/ui/webui/policy_ui.cc b/chrome/browser/ui/webui/policy_ui.cc
new file mode 100644
index 0000000..99ebb3e
--- /dev/null
+++ b/chrome/browser/ui/webui/policy_ui.cc
@@ -0,0 +1,109 @@
+// Copyright (c) 2011 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.
+
+#include "chrome/browser/ui/webui/policy_ui.h"
+
+#include "chrome/browser/policy/policy_status_info.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/webui/chrome_web_ui_data_source.h"
+#include "chrome/common/url_constants.h"
+#include "content/browser/tab_contents/tab_contents.h"
+#include "grit/browser_resources.h"
+#include "grit/generated_resources.h"
+
+ChromeWebUIDataSource* CreatePolicyUIHTMLSource() {
+ ChromeWebUIDataSource* source =
+ new ChromeWebUIDataSource(chrome::kChromeUIPolicyHost);
+
+ // Localized strings.
+ source->AddLocalizedString("policyTitle", IDS_POLICY_TITLE);
+ source->AddLocalizedString("statusPaneTitle", IDS_POLICY_STATUS_TITLE);
+ source->AddLocalizedString("fetchPoliciesText", IDS_POLICY_FETCH);
+ source->AddLocalizedString("devicePoliciesBoxTitle",
+ IDS_POLICY_DEVICE_POLICIES);
+ source->AddLocalizedString("userPoliciesBoxTitle",
+ IDS_POLICY_USER_POLICIES);
+ source->AddLocalizedString("enrollmentDomainText",
+ IDS_POLICY_ENROLLMENT_DOMAIN);
+ source->AddLocalizedString("lastFetchedText", IDS_POLICY_LAST_FETCHED);
+ source->AddLocalizedString("fetchIntervalText", IDS_POLICY_FETCH_INTERVAL);
+ source->AddLocalizedString("serverStatusText", IDS_POLICY_SERVER_STATUS);
+ source->AddLocalizedString("showUnsentPoliciesText",
+ IDS_POLICY_SHOW_UNSENT);
+ source->AddLocalizedString("filterPoliciesText", IDS_POLICY_FILTER);
+ source->AddLocalizedString("noPoliciesSet",IDS_POLICY_NO_POLICIES_SET);
+ source->AddLocalizedString("appliesToTableHeader", IDS_POLICY_APPLIES_TO);
+ source->AddLocalizedString("policyLevelTableHeader", IDS_POLICY_LEVEL);
+ source->AddLocalizedString("policyNameTableHeader", IDS_POLICY_ENTRY_NAME);
+ source->AddLocalizedString("policyValueTableHeader", IDS_POLICY_ENTRY_VALUE);
+ source->AddLocalizedString("policyStatusTableHeader",
+ IDS_POLICY_ENTRY_STATUS);
+ source->set_json_path("strings.js");
+
+ // Add required resources.
+ source->add_resource_path("policy.css", IDR_POLICY_CSS);
+ source->add_resource_path("policy.js", IDR_POLICY_JS);
+ source->set_default_resource(IDR_POLICY_HTML);
+
+ return source;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// PolicyUIHandler
+//
+////////////////////////////////////////////////////////////////////////////////
+
+PolicyUIHandler::PolicyUIHandler() {
+ policy::ConfigurationPolicyReader* managed_platform =
+ ConfigurationPolicyReader::CreateManagedPlatformPolicyReader();
+ policy::ConfigurationPolicyReader* managed_cloud =
+ ConfigurationPolicyReader::CreateManagedCloudPolicyReader();
+ policy::ConfigurationPolicyReader* recommended_platform =
+ ConfigurationPolicyReader::CreateRecommendedPlatformPolicyReader();
+ policy::ConfigurationPolicyReader* recommended_cloud =
+ ConfigurationPolicyReader::CreateRecommendedCloudPolicyReader();
+ policy_status_.reset(new policy::PolicyStatus(managed_platform,
+ managed_cloud,
+ recommended_platform,
+ recommended_cloud));
+}
+
+PolicyUIHandler::~PolicyUIHandler() {
+}
+
+WebUIMessageHandler* PolicyUIHandler::Attach(WebUI* web_ui) {
+ return WebUIMessageHandler::Attach(web_ui);
+}
+
+void PolicyUIHandler::RegisterMessages() {
+ web_ui_->RegisterMessageCallback("requestPolicyData",
+ NewCallback(this, &PolicyUIHandler::HandleRequestPolicyData));
+}
+
+void PolicyUIHandler::HandleRequestPolicyData(const ListValue* args) {
+ bool any_policies_sent;
+ ListValue* list = policy_status_->GetPolicyStatusList(&any_policies_sent);
+ DictionaryValue results;
+ results.Set("policies", list);
+ results.SetBoolean("anyPoliciesSet", any_policies_sent);
+ web_ui_->CallJavascriptFunction("Policy.returnPolicyData", results);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// PolicyUI
+//
+////////////////////////////////////////////////////////////////////////////////
+
+PolicyUI::PolicyUI(TabContents* contents) : ChromeWebUI(contents) {
+ AddMessageHandler((new PolicyUIHandler)->Attach(this));
+
+ // Set up the chrome://policy/ source.
+ Profile* profile = Profile::FromBrowserContext(contents->browser_context());
+ profile->GetChromeURLDataManager()->AddDataSource(CreatePolicyUIHTMLSource());
+}
+
+PolicyUI::~PolicyUI() {
+}
diff --git a/chrome/browser/ui/webui/policy_ui.h b/chrome/browser/ui/webui/policy_ui.h
new file mode 100644
index 0000000..f773a4b
--- /dev/null
+++ b/chrome/browser/ui/webui/policy_ui.h
@@ -0,0 +1,46 @@
+// Copyright (c) 2011 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.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_POLICY_UI_H_
+#define CHROME_BROWSER_UI_WEBUI_POLICY_UI_H_
+#pragma once
+
+#include "base/scoped_ptr.h"
+#include "base/values.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 {
+ public:
+ PolicyUIHandler();
+ virtual ~PolicyUIHandler();
+
+ // WebUIMessageHandler implementation.
+ virtual WebUIMessageHandler* Attach(WebUI* web_ui) OVERRIDE;
+ virtual void RegisterMessages() OVERRIDE;
+
+ private:
+ typedef policy::ConfigurationPolicyReader ConfigurationPolicyReader;
+
+ // Callback for the "requestPolicyData" message.
+ void HandleRequestPolicyData(const ListValue* args);
+
+ scoped_ptr<policy::PolicyStatus> policy_status_;
+
+ DISALLOW_COPY_AND_ASSIGN(PolicyUIHandler);
+};
+
+// The Web UI handler for about:policy.
+class PolicyUI : public ChromeWebUI {
+ public:
+ explicit PolicyUI(TabContents* contents);
+ virtual ~PolicyUI();
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(PolicyUI);
+};
+
+#endif // CHROME_BROWSER_UI_WEBUI_POLICY_UI_H_