summaryrefslogtreecommitdiffstats
path: root/chrome/browser/policy
diff options
context:
space:
mode:
authordconnelly@chromium.org <dconnelly@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-11-21 13:04:28 +0000
committerdconnelly@chromium.org <dconnelly@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-11-21 13:04:28 +0000
commitf97bd48680e0d3809f521dbcb06bd36aae5eaf0b (patch)
tree89c79bce7dacfb0cb601460247c8b748d84b6d6e /chrome/browser/policy
parentcead7ee37b1c9f0597c5033f6593901c14865283 (diff)
downloadchromium_src-f97bd48680e0d3809f521dbcb06bd36aae5eaf0b.zip
chromium_src-f97bd48680e0d3809f521dbcb06bd36aae5eaf0b.tar.gz
chromium_src-f97bd48680e0d3809f521dbcb06bd36aae5eaf0b.tar.bz2
Move ProxyPolicy fixup logic out of PolicyProvider and inject it instead.
The logic was previously applied at the UpdatePolicy level of every ConfigurationPolicyProvider, but this needs to move to facilitiate the refactoring of chrome/browser/policy into a layered component. Instead a fixup function can be injected into a PolicyService at construction time and is applied before policies from the various PolicyProviders are merged. There are three tests for this: - PolicyTransformationsTest.FixDeprecatedPolicies tests that the proxy policy fixup function works properly. - PolicyServiceTest.PolicyPreprocessing tests that the preprocessor function is applied during policy merge. - PolicyTest.PolicyPreprocessing tests that the proxy fixup function is added BrowserPolicyConnector and ProfilePolicyConnector. TEST=unit test, integration test, browser test BUG=271392 Review URL: https://codereview.chromium.org/59243005 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@236511 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/policy')
-rw-r--r--chrome/browser/policy/DEPS2
-rw-r--r--chrome/browser/policy/browser_policy_connector.cc4
-rw-r--r--chrome/browser/policy/configuration_policy_pref_store_unittest.cc7
-rw-r--r--chrome/browser/policy/configuration_policy_pref_store_unittest.h2
-rw-r--r--chrome/browser/policy/configuration_policy_provider.cc57
-rw-r--r--chrome/browser/policy/configuration_policy_provider_test.cc39
-rw-r--r--chrome/browser/policy/policy_browsertest.cc36
-rw-r--r--chrome/browser/policy/policy_service_impl.cc18
-rw-r--r--chrome/browser/policy/policy_service_impl.h10
-rw-r--r--chrome/browser/policy/policy_service_impl_unittest.cc50
-rw-r--r--chrome/browser/policy/policy_transformations.cc71
-rw-r--r--chrome/browser/policy/policy_transformations.h18
-rw-r--r--chrome/browser/policy/policy_transformations_unittest.cc76
-rw-r--r--chrome/browser/policy/profile_policy_connector.cc5
14 files changed, 285 insertions, 110 deletions
diff --git a/chrome/browser/policy/DEPS b/chrome/browser/policy/DEPS
index 9231735..71d05f2 100644
--- a/chrome/browser/policy/DEPS
+++ b/chrome/browser/policy/DEPS
@@ -30,6 +30,8 @@ specific_include_rules = {
r"policy_path_parser_unittest|"
r"policy_path_parser_win|"
r"policy_prefs_browsertest|"
+ r"policy_transformations|"
+ r"policy_transformations_unittest|"
r"profile_policy_connector|"
r"profile_policy_connector_factory|"
r"url_blacklist_manager|"
diff --git a/chrome/browser/policy/browser_policy_connector.cc b/chrome/browser/policy/browser_policy_connector.cc
index f6457cb..1f0fb1e 100644
--- a/chrome/browser/policy/browser_policy_connector.cc
+++ b/chrome/browser/policy/browser_policy_connector.cc
@@ -33,6 +33,7 @@
#include "chrome/browser/policy/configuration_policy_provider.h"
#include "chrome/browser/policy/policy_service_impl.h"
#include "chrome/browser/policy/policy_statistics_collector.h"
+#include "chrome/browser/policy/policy_transformations.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/chrome_version_info.h"
@@ -400,7 +401,8 @@ PolicyService* BrowserPolicyConnector::GetPolicyService() {
providers.push_back(&global_user_cloud_policy_provider_);
#endif
}
- policy_service_.reset(new PolicyServiceImpl(providers));
+ policy_service_.reset(new PolicyServiceImpl(
+ providers, base::Bind(&policy::FixDeprecatedPolicies)));
}
return policy_service_.get();
}
diff --git a/chrome/browser/policy/configuration_policy_pref_store_unittest.cc b/chrome/browser/policy/configuration_policy_pref_store_unittest.cc
index b12b10d..b304930e 100644
--- a/chrome/browser/policy/configuration_policy_pref_store_unittest.cc
+++ b/chrome/browser/policy/configuration_policy_pref_store_unittest.cc
@@ -14,7 +14,6 @@
#include "chrome/browser/policy/configuration_policy_pref_store.h"
#include "chrome/browser/policy/external_data_fetcher.h"
#include "chrome/browser/policy/policy_map.h"
-#include "chrome/browser/policy/policy_service_impl.h"
#include "components/policy/core/common/policy_pref_names.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -48,9 +47,9 @@ ConfigurationPolicyPrefStoreTest::ConfigurationPolicyPrefStoreTest() {
EXPECT_CALL(provider_, IsInitializationComplete(_))
.WillRepeatedly(Return(false));
provider_.Init();
- PolicyServiceImpl::Providers providers;
- providers.push_back(&provider_);
- policy_service_.reset(new PolicyServiceImpl(providers));
+ providers_.push_back(&provider_);
+ policy_service_.reset(new PolicyServiceImpl(
+ providers_, PolicyServiceImpl::PreprocessCallback()));
store_ = new ConfigurationPolicyPrefStore(
policy_service_.get(), &handler_list_, POLICY_LEVEL_MANDATORY);
}
diff --git a/chrome/browser/policy/configuration_policy_pref_store_unittest.h b/chrome/browser/policy/configuration_policy_pref_store_unittest.h
index 9fdf866..0012d2b 100644
--- a/chrome/browser/policy/configuration_policy_pref_store_unittest.h
+++ b/chrome/browser/policy/configuration_policy_pref_store_unittest.h
@@ -10,6 +10,7 @@
#include "base/message_loop/message_loop.h"
#include "chrome/browser/policy/configuration_policy_handler_list.h"
#include "chrome/browser/policy/mock_configuration_policy_provider.h"
+#include "chrome/browser/policy/policy_service_impl.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace policy {
@@ -25,6 +26,7 @@ class ConfigurationPolicyPrefStoreTest : public testing::Test {
virtual void TearDown() OVERRIDE;
void UpdateProviderPolicy(const PolicyMap& policy);
+ PolicyServiceImpl::Providers providers_;
ConfigurationPolicyHandlerList handler_list_;
MockConfigurationPolicyProvider provider_;
scoped_ptr<PolicyService> policy_service_;
diff --git a/chrome/browser/policy/configuration_policy_provider.cc b/chrome/browser/policy/configuration_policy_provider.cc
index a0ae969..87c8127 100644
--- a/chrome/browser/policy/configuration_policy_provider.cc
+++ b/chrome/browser/policy/configuration_policy_provider.cc
@@ -6,64 +6,9 @@
#include "base/callback.h"
#include "chrome/browser/policy/external_data_fetcher.h"
-#include "chrome/browser/policy/policy_map.h"
-#include "policy/policy_constants.h"
namespace policy {
-namespace {
-
-const char* kProxyPolicies[] = {
- key::kProxyMode,
- key::kProxyServerMode,
- key::kProxyServer,
- key::kProxyPacUrl,
- key::kProxyBypassList,
-};
-
-// Helper that converts deprecated chrome policies into their corresponding
-// actual policies.
-void FixDeprecatedPolicies(PolicyMap* policies) {
- // Proxy settings have been configured by 5 policies that didn't mix well
- // together, and maps of policies had to take this into account when merging
- // policy sources. The proxy settings will eventually be configured by a
- // single Dictionary policy when all providers have support for that. For
- // now, the individual policies are mapped here to a single Dictionary policy
- // that the rest of the policy machinery uses.
-
- // The highest (level, scope) pair for an existing proxy policy is determined
- // first, and then only policies with those exact attributes are merged.
- PolicyMap::Entry current_priority; // Defaults to the lowest priority.
- scoped_ptr<DictionaryValue> proxy_settings(new DictionaryValue);
- for (size_t i = 0; i < arraysize(kProxyPolicies); ++i) {
- const PolicyMap::Entry* entry = policies->Get(kProxyPolicies[i]);
- if (entry) {
- if (entry->has_higher_priority_than(current_priority)) {
- proxy_settings->Clear();
- current_priority = *entry;
- }
- if (!entry->has_higher_priority_than(current_priority) &&
- !current_priority.has_higher_priority_than(*entry)) {
- proxy_settings->Set(kProxyPolicies[i], entry->value->DeepCopy());
- }
- policies->Erase(kProxyPolicies[i]);
- }
- }
- // Sets the new |proxy_settings| if kProxySettings isn't set yet, or if the
- // new priority is higher.
- const PolicyMap::Entry* existing = policies->Get(key::kProxySettings);
- if (!proxy_settings->empty() &&
- (!existing || current_priority.has_higher_priority_than(*existing))) {
- policies->Set(key::kProxySettings,
- current_priority.level,
- current_priority.scope,
- proxy_settings.release(),
- NULL);
- }
-}
-
-} // namespace
-
ConfigurationPolicyProvider::Observer::~Observer() {}
ConfigurationPolicyProvider::ConfigurationPolicyProvider()
@@ -100,8 +45,6 @@ void ConfigurationPolicyProvider::UpdatePolicy(
policy_bundle_.Swap(bundle.get());
else
policy_bundle_.Clear();
- FixDeprecatedPolicies(&policy_bundle_.Get(
- PolicyNamespace(POLICY_DOMAIN_CHROME, std::string())));
FOR_EACH_OBSERVER(ConfigurationPolicyProvider::Observer,
observer_list_,
OnUpdatePolicy(this));
diff --git a/chrome/browser/policy/configuration_policy_provider_test.cc b/chrome/browser/policy/configuration_policy_provider_test.cc
index 2dd3f2b..7bee548 100644
--- a/chrome/browser/policy/configuration_policy_provider_test.cc
+++ b/chrome/browser/policy/configuration_policy_provider_test.cc
@@ -14,7 +14,6 @@
#include "chrome/browser/policy/policy_bundle.h"
#include "chrome/browser/policy/policy_map.h"
#include "components/policy/core/common/policy_namespace.h"
-#include "policy/policy_constants.h"
#include "testing/gmock/include/gmock/gmock.h"
using ::testing::Mock;
@@ -337,44 +336,6 @@ TEST_P(ConfigurationPolicyProviderTest, RefreshPolicies) {
provider_->RemoveObserver(&observer);
}
-TEST(ConfigurationPolicyProviderTest, FixDeprecatedPolicies) {
- PolicyMap policy_map;
- policy_map.Set(key::kProxyServerMode,
- POLICY_LEVEL_MANDATORY,
- POLICY_SCOPE_USER,
- base::Value::CreateIntegerValue(3),
- NULL);
-
- // Both these policies should be ignored, since there's a higher priority
- // policy available.
- policy_map.Set(key::kProxyMode,
- POLICY_LEVEL_RECOMMENDED,
- POLICY_SCOPE_USER,
- base::Value::CreateStringValue("pac_script"),
- NULL);
- policy_map.Set(key::kProxyPacUrl,
- POLICY_LEVEL_RECOMMENDED,
- POLICY_SCOPE_USER,
- base::Value::CreateStringValue("http://example.com/wpad.dat"),
- NULL);
-
- MockConfigurationPolicyProvider provider;
- provider.Init();
- provider.UpdateChromePolicy(policy_map);
-
- PolicyBundle expected_bundle;
- base::DictionaryValue* expected_value = new base::DictionaryValue();
- expected_value->SetInteger(key::kProxyServerMode, 3);
- expected_bundle.Get(PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()))
- .Set(key::kProxySettings,
- POLICY_LEVEL_MANDATORY,
- POLICY_SCOPE_USER,
- expected_value,
- NULL);
- EXPECT_TRUE(provider.policies().Equals(expected_bundle));
- provider.Shutdown();
-}
-
Configuration3rdPartyPolicyProviderTest::
Configuration3rdPartyPolicyProviderTest() {}
diff --git a/chrome/browser/policy/policy_browsertest.cc b/chrome/browser/policy/policy_browsertest.cc
index 13853f3..26b69ca 100644
--- a/chrome/browser/policy/policy_browsertest.cc
+++ b/chrome/browser/policy/policy_browsertest.cc
@@ -50,6 +50,9 @@
#include "chrome/browser/policy/external_data_fetcher.h"
#include "chrome/browser/policy/mock_configuration_policy_provider.h"
#include "chrome/browser/policy/policy_map.h"
+#include "chrome/browser/policy/policy_service.h"
+#include "chrome/browser/policy/profile_policy_connector.h"
+#include "chrome/browser/policy/profile_policy_connector_factory.h"
#include "chrome/browser/prefs/session_startup_pref.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/search/instant_service.h"
@@ -930,6 +933,39 @@ IN_PROC_BROWSER_TEST_F(PolicyTest, DefaultSearchProvider) {
EXPECT_EQ(GURL(content::kAboutBlankURL), web_contents->GetURL());
}
+IN_PROC_BROWSER_TEST_F(PolicyTest, PolicyPreprocessing) {
+ // Add an individual proxy policy value.
+ PolicyMap policies;
+ policies.Set(key::kProxyServerMode,
+ POLICY_LEVEL_MANDATORY,
+ POLICY_SCOPE_USER,
+ base::Value::CreateIntegerValue(3),
+ NULL);
+ UpdateProviderPolicy(policies);
+
+ // It should be removed and replaced with a dictionary.
+ PolicyMap expected;
+ scoped_ptr<base::DictionaryValue> expected_value(new base::DictionaryValue);
+ expected_value->SetInteger(key::kProxyServerMode, 3);
+ expected.Set(key::kProxySettings,
+ POLICY_LEVEL_MANDATORY,
+ POLICY_SCOPE_USER,
+ expected_value.release(),
+ NULL);
+
+ // Check both the browser and the profile.
+ const PolicyMap& actual_from_browser =
+ g_browser_process->browser_policy_connector()
+ ->GetPolicyService()
+ ->GetPolicies(PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()));
+ EXPECT_TRUE(expected.Equals(actual_from_browser));
+ const PolicyMap& actual_from_profile =
+ ProfilePolicyConnectorFactory::GetForProfile(browser()->profile())
+ ->policy_service()
+ ->GetPolicies(PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()));
+ EXPECT_TRUE(expected.Equals(actual_from_profile));
+}
+
IN_PROC_BROWSER_TEST_F(PolicyTest, ForceSafeSearch) {
// Makes the requests fail since all we want to check is that the redirection
// is done properly.
diff --git a/chrome/browser/policy/policy_service_impl.cc b/chrome/browser/policy/policy_service_impl.cc
index 4604f75..7820559 100644
--- a/chrome/browser/policy/policy_service_impl.cc
+++ b/chrome/browser/policy/policy_service_impl.cc
@@ -9,14 +9,17 @@
#include "base/bind.h"
#include "base/message_loop/message_loop.h"
#include "base/stl_util.h"
-#include "chrome/browser/policy/policy_map.h"
+#include "chrome/browser/policy/policy_bundle.h"
namespace policy {
typedef PolicyServiceImpl::Providers::const_iterator Iterator;
-PolicyServiceImpl::PolicyServiceImpl(const Providers& providers)
- : update_task_ptr_factory_(this) {
+PolicyServiceImpl::PolicyServiceImpl(
+ const Providers& providers,
+ const PreprocessCallback& preprocess_callback)
+ : preprocess_callback_(preprocess_callback),
+ update_task_ptr_factory_(this) {
for (int domain = 0; domain < POLICY_DOMAIN_SIZE; ++domain)
initialization_complete_[domain] = true;
providers_ = providers;
@@ -127,8 +130,13 @@ void PolicyServiceImpl::NotifyNamespaceUpdated(
void PolicyServiceImpl::MergeAndTriggerUpdates() {
// Merge from each provider in their order of priority.
PolicyBundle bundle;
- for (Iterator it = providers_.begin(); it != providers_.end(); ++it)
- bundle.MergeFrom((*it)->policies());
+ for (Iterator it = providers_.begin(); it != providers_.end(); ++it) {
+ PolicyBundle provided_bundle;
+ provided_bundle.CopyFrom((*it)->policies());
+ if (!preprocess_callback_.is_null())
+ preprocess_callback_.Run(&provided_bundle);
+ bundle.MergeFrom(provided_bundle);
+ }
// Swap first, so that observers that call GetPolicies() see the current
// values.
diff --git a/chrome/browser/policy/policy_service_impl.h b/chrome/browser/policy/policy_service_impl.h
index 6817574..b199c51 100644
--- a/chrome/browser/policy/policy_service_impl.h
+++ b/chrome/browser/policy/policy_service_impl.h
@@ -11,6 +11,7 @@
#include <vector>
#include "base/basictypes.h"
+#include "base/callback.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "chrome/browser/policy/configuration_policy_provider.h"
@@ -25,12 +26,16 @@ class PolicyServiceImpl : public PolicyService,
public ConfigurationPolicyProvider::Observer {
public:
typedef std::vector<ConfigurationPolicyProvider*> Providers;
+ typedef base::Callback<void(PolicyBundle*)> PreprocessCallback;
// The PolicyServiceImpl will merge policies from |providers|. |providers|
// must be sorted in decreasing order of priority; the first provider will
// have the highest priority. The PolicyServiceImpl does not take ownership of
// the providers, and they must outlive the PolicyServiceImpl.
- explicit PolicyServiceImpl(const Providers& providers);
+ // |preprocess_callback| will be applied every PolicyBundle before merginng.
+ PolicyServiceImpl(const Providers& providers,
+ const PreprocessCallback& preprocess_callback);
+
virtual ~PolicyServiceImpl();
// PolicyService overrides:
@@ -83,6 +88,9 @@ class PolicyServiceImpl : public PolicyService,
// call to RefreshPolicies().
std::set<ConfigurationPolicyProvider*> refresh_pending_;
+ // Callback invoked to manipulate a PolicyBundle before it is merged.
+ PreprocessCallback preprocess_callback_;
+
// List of callbacks to invoke once all providers refresh after a
// RefreshPolicies() call.
std::vector<base::Closure> refresh_callbacks_;
diff --git a/chrome/browser/policy/policy_service_impl_unittest.cc b/chrome/browser/policy/policy_service_impl_unittest.cc
index 365e5ff..c43a5efb 100644
--- a/chrome/browser/policy/policy_service_impl_unittest.cc
+++ b/chrome/browser/policy/policy_service_impl_unittest.cc
@@ -29,6 +29,17 @@ const char kExtension[] = "extension-id";
const char kSameLevelPolicy[] = "policy-same-level-and-scope";
const char kDiffLevelPolicy[] = "chrome-diff-level-and-scope";
+void SetPolicyMapValue(const std::string& key,
+ const std::string& value,
+ PolicyBundle* bundle) {
+ bundle->Get(PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()))
+ .Set(key,
+ POLICY_LEVEL_MANDATORY,
+ POLICY_SCOPE_USER,
+ new base::StringValue(value),
+ NULL);
+}
+
// Helper to compare the arguments to an EXPECT_CALL of OnPolicyUpdated() with
// their expected values.
MATCHER_P(PolicyEquals, expected, "") {
@@ -111,7 +122,8 @@ class PolicyServiceTest : public testing::Test {
providers.push_back(&provider0_);
providers.push_back(&provider1_);
providers.push_back(&provider2_);
- policy_service_.reset(new PolicyServiceImpl(providers));
+ policy_service_.reset(new PolicyServiceImpl(
+ providers, PolicyServiceImpl::PreprocessCallback()));
}
virtual void TearDown() OVERRIDE {
@@ -522,6 +534,39 @@ TEST_F(PolicyServiceTest, NamespaceMerge) {
PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, kExtension)).Equals(expected));
}
+TEST_F(PolicyServiceTest, PolicyPreprocessing) {
+ // Reset the PolicyServiceImpl to one that has the preprocessor.
+ PolicyServiceImpl::Providers providers;
+ providers.push_back(&provider0_);
+ policy_service_.reset(new PolicyServiceImpl(
+ providers, base::Bind(&SetPolicyMapValue, kSameLevelPolicy, "bar")));
+
+ // Set the policy value to "foo".
+ scoped_ptr<PolicyBundle> bundle(new PolicyBundle());
+ PolicyMap& map =
+ bundle->Get(PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()));
+ map.Set(kSameLevelPolicy,
+ POLICY_LEVEL_MANDATORY,
+ POLICY_SCOPE_USER,
+ base::Value::CreateStringValue("foo"),
+ NULL);
+
+ // Push the update through the provider.
+ provider0_.UpdatePolicy(bundle.Pass());
+ RunUntilIdle();
+
+ // The value should have been changed from "foo" to "bar".
+ const PolicyMap& actual = policy_service_->GetPolicies(
+ PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()));
+ PolicyMap expected;
+ expected.Set(kSameLevelPolicy,
+ POLICY_LEVEL_MANDATORY,
+ POLICY_SCOPE_USER,
+ base::Value::CreateStringValue("bar"),
+ NULL);
+ EXPECT_TRUE(actual.Equals(expected));
+}
+
TEST_F(PolicyServiceTest, IsInitializationComplete) {
// |provider0| has all domains initialized.
Mock::VerifyAndClearExpectations(&provider1_);
@@ -534,7 +579,8 @@ TEST_F(PolicyServiceTest, IsInitializationComplete) {
providers.push_back(&provider0_);
providers.push_back(&provider1_);
providers.push_back(&provider2_);
- policy_service_.reset(new PolicyServiceImpl(providers));
+ policy_service_.reset(new PolicyServiceImpl(
+ providers, PolicyServiceImpl::PreprocessCallback()));
EXPECT_FALSE(policy_service_->IsInitializationComplete(POLICY_DOMAIN_CHROME));
EXPECT_FALSE(
policy_service_->IsInitializationComplete(POLICY_DOMAIN_EXTENSIONS));
diff --git a/chrome/browser/policy/policy_transformations.cc b/chrome/browser/policy/policy_transformations.cc
new file mode 100644
index 0000000..3504e2a
--- /dev/null
+++ b/chrome/browser/policy/policy_transformations.cc
@@ -0,0 +1,71 @@
+// Copyright 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.
+
+#include "chrome/browser/policy/policy_transformations.h"
+
+#include "base/memory/scoped_ptr.h"
+#include "base/values.h"
+#include "chrome/browser/policy/policy_bundle.h"
+#include "chrome/browser/policy/policy_map.h"
+#include "policy/policy_constants.h"
+
+namespace policy {
+
+namespace {
+
+const char* kProxyPolicies[] = {
+ key::kProxyMode,
+ key::kProxyServerMode,
+ key::kProxyServer,
+ key::kProxyPacUrl,
+ key::kProxyBypassList,
+};
+
+void FixDeprecatedPolicies(PolicyMap* policies) {
+ // Proxy settings have been configured by 5 policies that didn't mix well
+ // together, and maps of policies had to take this into account when merging
+ // policy sources. The proxy settings will eventually be configured by a
+ // single Dictionary policy when all providers have support for that. For
+ // now, the individual policies are mapped here to a single Dictionary policy
+ // that the rest of the policy machinery uses.
+
+ // The highest (level, scope) pair for an existing proxy policy is determined
+ // first, and then only policies with those exact attributes are merged.
+ PolicyMap::Entry current_priority; // Defaults to the lowest priority.
+ scoped_ptr<base::DictionaryValue> proxy_settings(new base::DictionaryValue);
+ for (size_t i = 0; i < arraysize(kProxyPolicies); ++i) {
+ const PolicyMap::Entry* entry = policies->Get(kProxyPolicies[i]);
+ if (entry) {
+ if (entry->has_higher_priority_than(current_priority)) {
+ proxy_settings->Clear();
+ current_priority = *entry;
+ }
+ if (!entry->has_higher_priority_than(current_priority) &&
+ !current_priority.has_higher_priority_than(*entry)) {
+ proxy_settings->Set(kProxyPolicies[i], entry->value->DeepCopy());
+ }
+ policies->Erase(kProxyPolicies[i]);
+ }
+ }
+ // Sets the new |proxy_settings| if kProxySettings isn't set yet, or if the
+ // new priority is higher.
+ const PolicyMap::Entry* existing = policies->Get(key::kProxySettings);
+ if (!proxy_settings->empty() &&
+ (!existing || current_priority.has_higher_priority_than(*existing))) {
+ policies->Set(key::kProxySettings,
+ current_priority.level,
+ current_priority.scope,
+ proxy_settings.release(),
+ NULL);
+ }
+}
+
+} // namespace
+
+void FixDeprecatedPolicies(PolicyBundle* bundle) {
+ FixDeprecatedPolicies(
+ &bundle->Get(PolicyNamespace(POLICY_DOMAIN_CHROME, std::string())));
+}
+
+} // namespace policy
diff --git a/chrome/browser/policy/policy_transformations.h b/chrome/browser/policy/policy_transformations.h
new file mode 100644
index 0000000..12f4c9f
--- /dev/null
+++ b/chrome/browser/policy/policy_transformations.h
@@ -0,0 +1,18 @@
+// Copyright 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.
+
+#ifndef CHROME_BROWSER_POLICY_POLICY_TRANSFORMATIONS_H_
+#define CHROME_BROWSER_POLICY_POLICY_TRANSFORMATIONS_H_
+
+namespace policy {
+
+class PolicyBundle;
+
+// Helper that converts deprecated chrome policies into their corresponding
+// actual policies.
+void FixDeprecatedPolicies(PolicyBundle* bundle);
+
+} // namespace policy
+
+#endif // CHROME_BROWSER_POLICY_POLICY_TRANSFORMATIONS_H_
diff --git a/chrome/browser/policy/policy_transformations_unittest.cc b/chrome/browser/policy/policy_transformations_unittest.cc
new file mode 100644
index 0000000..53cfdd8
--- /dev/null
+++ b/chrome/browser/policy/policy_transformations_unittest.cc
@@ -0,0 +1,76 @@
+// Copyright 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.
+
+#include "chrome/browser/policy/policy_transformations.h"
+
+#include "base/memory/scoped_ptr.h"
+#include "base/values.h"
+#include "chrome/browser/policy/policy_bundle.h"
+#include "chrome/browser/policy/policy_map.h"
+#include "policy/policy_constants.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace policy {
+
+TEST(PolicyTransformationsTest, FixDeprecatedPolicies) {
+ PolicyBundle policy_bundle;
+ PolicyMap& policy_map =
+ policy_bundle.Get(PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()));
+
+ // Individual proxy policy values in the Chrome namespace should be collected
+ // into a dictionary.
+ policy_map.Set(key::kProxyServerMode,
+ POLICY_LEVEL_MANDATORY,
+ POLICY_SCOPE_USER,
+ base::Value::CreateIntegerValue(3),
+ NULL);
+
+ // Both these policies should be ignored, since there's a higher priority
+ // policy available.
+ policy_map.Set(key::kProxyMode,
+ POLICY_LEVEL_RECOMMENDED,
+ POLICY_SCOPE_USER,
+ base::Value::CreateStringValue("pac_script"),
+ NULL);
+ policy_map.Set(key::kProxyPacUrl,
+ POLICY_LEVEL_RECOMMENDED,
+ POLICY_SCOPE_USER,
+ base::Value::CreateStringValue("http://example.com/wpad.dat"),
+ NULL);
+
+ // Add a value to a non-Chrome namespace.
+ policy_bundle.Get(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, std::string()))
+ .Set(key::kProxyServerMode,
+ POLICY_LEVEL_MANDATORY,
+ POLICY_SCOPE_USER,
+ base::Value::CreateIntegerValue(3),
+ NULL);
+
+ PolicyBundle actual_bundle;
+ actual_bundle.CopyFrom(policy_bundle);
+ FixDeprecatedPolicies(&actual_bundle);
+
+ PolicyBundle expected_bundle;
+ // The resulting Chrome namespace map should have the collected policy.
+ PolicyMap& expected_map =
+ expected_bundle.Get(PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()));
+ scoped_ptr<base::DictionaryValue> expected_value(new base::DictionaryValue);
+ expected_value->SetInteger(key::kProxyServerMode, 3);
+ expected_map.Set(key::kProxySettings,
+ POLICY_LEVEL_MANDATORY,
+ POLICY_SCOPE_USER,
+ expected_value.release(),
+ NULL);
+ // The resulting Extensions namespace map shouldn't have been modified.
+ expected_bundle.Get(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, std::string()))
+ .Set(key::kProxyServerMode,
+ POLICY_LEVEL_MANDATORY,
+ POLICY_SCOPE_USER,
+ base::Value::CreateIntegerValue(3),
+ NULL);
+
+ EXPECT_TRUE(expected_bundle.Equals(actual_bundle));
+}
+
+} // namespace policy
diff --git a/chrome/browser/policy/profile_policy_connector.cc b/chrome/browser/policy/profile_policy_connector.cc
index 73eea77..61ac00d 100644
--- a/chrome/browser/policy/profile_policy_connector.cc
+++ b/chrome/browser/policy/profile_policy_connector.cc
@@ -6,6 +6,7 @@
#include <vector>
+#include "base/bind.h"
#include "base/logging.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/policy/browser_policy_connector.h"
@@ -13,6 +14,7 @@
#include "chrome/browser/policy/configuration_policy_provider.h"
#include "chrome/browser/policy/forwarding_policy_provider.h"
#include "chrome/browser/policy/policy_service_impl.h"
+#include "chrome/browser/policy/policy_transformations.h"
#if defined(OS_CHROMEOS)
#include "chrome/browser/chromeos/login/user.h"
@@ -80,7 +82,8 @@ void ProfilePolicyConnector::Init(
providers.push_back(special_user_policy_provider_.get());
#endif
- policy_service_.reset(new PolicyServiceImpl(providers));
+ policy_service_.reset(new PolicyServiceImpl(
+ providers, base::Bind(&policy::FixDeprecatedPolicies)));
#if defined(OS_CHROMEOS)
if (is_primary_user_) {