summaryrefslogtreecommitdiffstats
path: root/chrome/browser/policy
diff options
context:
space:
mode:
authorjoaodasilva@chromium.org <joaodasilva@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-03-31 22:02:23 +0000
committerjoaodasilva@chromium.org <joaodasilva@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-03-31 22:02:23 +0000
commitd9720f50db7dbe830e4b9acd302e7f799a2a85f1 (patch)
tree9d81bb0e4718c189e1a6746460e9b3bc45c9944e /chrome/browser/policy
parent65c09bc81db6fa9b0c43345a00cf16b054d65a43 (diff)
downloadchromium_src-d9720f50db7dbe830e4b9acd302e7f799a2a85f1.zip
chromium_src-d9720f50db7dbe830e4b9acd302e7f799a2a85f1.tar.gz
chromium_src-d9720f50db7dbe830e4b9acd302e7f799a2a85f1.tar.bz2
Refactored the CloudPolicyProvider so that it becomes initialized once and stays initialized.
Also added device policy command line flags to InProcessBrowserTest, so that browser_tests run with this provider on ChromeOS. BUG=120967 TEST=Everything works as before Review URL: http://codereview.chromium.org/9911029 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@130067 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/policy')
-rw-r--r--chrome/browser/policy/browser_policy_connector.cc40
-rw-r--r--chrome/browser/policy/cloud_policy_provider.cc98
-rw-r--r--chrome/browser/policy/cloud_policy_provider.h89
-rw-r--r--chrome/browser/policy/cloud_policy_provider_impl.cc113
-rw-r--r--chrome/browser/policy/cloud_policy_provider_impl.h77
-rw-r--r--chrome/browser/policy/cloud_policy_provider_unittest.cc394
-rw-r--r--chrome/browser/policy/cloud_policy_subsystem_unittest.cc8
-rw-r--r--chrome/browser/policy/configuration_policy_provider.cc6
-rw-r--r--chrome/browser/policy/user_policy_disk_cache.cc3
9 files changed, 364 insertions, 464 deletions
diff --git a/chrome/browser/policy/browser_policy_connector.cc b/chrome/browser/policy/browser_policy_connector.cc
index 9686851..de17f0d 100644
--- a/chrome/browser/policy/browser_policy_connector.cc
+++ b/chrome/browser/policy/browser_policy_connector.cc
@@ -11,7 +11,6 @@
#include "base/path_service.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/policy/cloud_policy_provider.h"
-#include "chrome/browser/policy/cloud_policy_provider_impl.h"
#include "chrome/browser/policy/cloud_policy_subsystem.h"
#include "chrome/browser/policy/configuration_policy_provider.h"
#include "chrome/browser/policy/policy_service_impl.h"
@@ -111,19 +110,28 @@ void BrowserPolicyConnector::Init() {
managed_platform_provider_.reset(CreateManagedPlatformProvider());
recommended_platform_provider_.reset(CreateRecommendedPlatformProvider());
- managed_cloud_provider_.reset(new CloudPolicyProviderImpl(
- this,
- GetChromePolicyDefinitionList(),
- POLICY_LEVEL_MANDATORY));
- recommended_cloud_provider_.reset(new CloudPolicyProviderImpl(
- this,
- GetChromePolicyDefinitionList(),
- POLICY_LEVEL_RECOMMENDED));
-
#if defined(OS_CHROMEOS)
+ // The CloudPolicyProvider blocks asynchronous Profile creation until a login
+ // is performed. This is used to ensure that the Profile's PrefService sees
+ // managed preferences on managed Chrome OS devices. However, this also
+ // prevents creation of new Profiles in Desktop Chrome. The implementation of
+ // cloud policy on the Desktop requires a refactoring of the cloud provider,
+ // but for now it just isn't created.
+ CommandLine* command_line = CommandLine::ForCurrentProcess();
+ if (command_line->HasSwitch(switches::kDeviceManagementUrl)) {
+ managed_cloud_provider_.reset(new CloudPolicyProvider(
+ this,
+ GetChromePolicyDefinitionList(),
+ POLICY_LEVEL_MANDATORY));
+ recommended_cloud_provider_.reset(new CloudPolicyProvider(
+ this,
+ GetChromePolicyDefinitionList(),
+ POLICY_LEVEL_RECOMMENDED));
+ }
+
InitializeDevicePolicy();
- if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnableONCPolicy)) {
+ if (command_line->HasSwitch(switches::kEnableONCPolicy)) {
network_configuration_updater_.reset(
new NetworkConfigurationUpdater(
managed_cloud_provider_.get(),
@@ -320,10 +328,8 @@ void BrowserPolicyConnector::InitializeUserPolicy(
new UserPolicyTokenCache(user_data_store_.get(),
policy_cache_dir.Append(kTokenCacheFile)));
- // Prepending user caches meaning they will take precedence of device policy
- // caches.
- managed_cloud_provider_->PrependCache(user_policy_cache);
- recommended_cloud_provider_->PrependCache(user_policy_cache);
+ managed_cloud_provider_->SetUserPolicyCache(user_policy_cache);
+ recommended_cloud_provider_->SetUserPolicyCache(user_policy_cache);
user_cloud_policy_subsystem_.reset(new CloudPolicySubsystem(
user_data_store_.get(),
user_policy_cache));
@@ -457,8 +463,8 @@ void BrowserPolicyConnector::InitializeDevicePolicy() {
new DevicePolicyCache(device_data_store_.get(),
install_attributes_.get());
- managed_cloud_provider_->AppendCache(device_policy_cache);
- recommended_cloud_provider_->AppendCache(device_policy_cache);
+ managed_cloud_provider_->SetDevicePolicyCache(device_policy_cache);
+ recommended_cloud_provider_->SetDevicePolicyCache(device_policy_cache);
device_cloud_policy_subsystem_.reset(new CloudPolicySubsystem(
device_data_store_.get(),
diff --git a/chrome/browser/policy/cloud_policy_provider.cc b/chrome/browser/policy/cloud_policy_provider.cc
index a5f5c2c..be91926 100644
--- a/chrome/browser/policy/cloud_policy_provider.cc
+++ b/chrome/browser/policy/cloud_policy_provider.cc
@@ -1,17 +1,109 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 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/cloud_policy_provider.h"
+#include "chrome/browser/policy/browser_policy_connector.h"
+
namespace policy {
CloudPolicyProvider::CloudPolicyProvider(
- const PolicyDefinitionList* policy_list)
- : ConfigurationPolicyProvider(policy_list) {
+ BrowserPolicyConnector* browser_policy_connector,
+ const PolicyDefinitionList* policy_list,
+ PolicyLevel level)
+ : ConfigurationPolicyProvider(policy_list),
+ browser_policy_connector_(browser_policy_connector),
+ level_(level),
+ initialization_complete_(false) {
+ for (size_t i = 0; i < CACHE_SIZE; ++i)
+ caches_[i] = NULL;
}
CloudPolicyProvider::~CloudPolicyProvider() {
+ for (size_t i = 0; i < CACHE_SIZE; ++i) {
+ if (caches_[i])
+ caches_[i]->RemoveObserver(this);
+ }
+}
+
+void CloudPolicyProvider::SetUserPolicyCache(CloudPolicyCacheBase* cache) {
+ DCHECK(!caches_[CACHE_USER]);
+ caches_[CACHE_USER] = cache;
+ cache->AddObserver(this);
+ Merge();
+}
+
+#if defined(OS_CHROMEOS)
+void CloudPolicyProvider::SetDevicePolicyCache(CloudPolicyCacheBase* cache) {
+ DCHECK(caches_[CACHE_DEVICE] == NULL);
+ caches_[CACHE_DEVICE] = cache;
+ cache->AddObserver(this);
+ Merge();
+}
+#endif
+
+bool CloudPolicyProvider::ProvideInternal(PolicyMap* result) {
+ result->CopyFrom(combined_);
+ return true;
+}
+
+bool CloudPolicyProvider::IsInitializationComplete() const {
+ return initialization_complete_;
+}
+
+void CloudPolicyProvider::RefreshPolicies() {
+ for (size_t i = 0; i < CACHE_SIZE; ++i) {
+ if (caches_[i])
+ pending_updates_.insert(caches_[i]);
+ }
+ if (pending_updates_.empty())
+ NotifyPolicyUpdated();
+ else
+ browser_policy_connector_->FetchCloudPolicy();
+}
+
+void CloudPolicyProvider::OnCacheUpdate(CloudPolicyCacheBase* cache) {
+ pending_updates_.erase(cache);
+ Merge();
+}
+
+void CloudPolicyProvider::OnCacheGoingAway(CloudPolicyCacheBase* cache) {
+ for (size_t i = 0; i < CACHE_SIZE; ++i) {
+ if (caches_[i] == cache) {
+ caches_[i] = NULL;
+ cache->RemoveObserver(this);
+ pending_updates_.erase(cache);
+ Merge();
+ return;
+ }
+ }
+ NOTREACHED();
+}
+
+void CloudPolicyProvider::Merge() {
+ // Re-check whether all caches are ready.
+ if (!initialization_complete_) {
+ initialization_complete_ = true;
+ for (size_t i = 0; i < CACHE_SIZE; ++i) {
+ if (caches_[i] == NULL || !caches_[i]->IsReady()) {
+ initialization_complete_ = false;
+ break;
+ }
+ }
+ }
+
+ combined_.Clear();
+ for (size_t i = 0; i < CACHE_SIZE; ++i) {
+ if (caches_[i] && caches_[i]->IsReady())
+ combined_.MergeFrom(*caches_[i]->policy());
+ }
+ FixDeprecatedPolicies(&combined_);
+ combined_.FilterLevel(level_);
+
+ // Trigger a notification.
+ if (pending_updates_.empty())
+ NotifyPolicyUpdated();
}
} // namespace policy
diff --git a/chrome/browser/policy/cloud_policy_provider.h b/chrome/browser/policy/cloud_policy_provider.h
index a9bc606..52ce81e 100644
--- a/chrome/browser/policy/cloud_policy_provider.h
+++ b/chrome/browser/policy/cloud_policy_provider.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 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.
@@ -6,39 +6,82 @@
#define CHROME_BROWSER_POLICY_CLOUD_POLICY_PROVIDER_H_
#pragma once
+#include <set>
+
#include "base/basictypes.h"
+#include "chrome/browser/policy/cloud_policy_cache_base.h"
#include "chrome/browser/policy/configuration_policy_provider.h"
+#include "chrome/browser/policy/policy_map.h"
namespace policy {
-class CloudPolicyCacheBase;
-
-// A policy provider having multiple backend caches, combining their relevant
-// PolicyMaps and keeping the result cached. The underlying caches are kept as
-// weak references and can be added dynamically. Also the
-// |CloudPolicyProvider| instance listens to cache-notifications and removes
-// the caches automatically when they go away. The order in which the caches are
-// stored matters! The first cache is applied as is and the following caches
-// only contribute the not-yet applied policies. There are two functions to add
-// a new cache:
-// PrependCache(cache): adds |cache| to the front (i.e. most important cache).
-// AppendCache(cache): adds |cache| to the back (i.e. least important cache).
-class CloudPolicyProvider : public ConfigurationPolicyProvider {
+class BrowserPolicyConnector;
+
+// A policy provider that merges the policies contained in the caches it
+// observes. The caches receive their policies by fetching them from the cloud,
+// through the CloudPolicyController.
+class CloudPolicyProvider : public ConfigurationPolicyProvider,
+ public CloudPolicyCacheBase::Observer {
public:
- explicit CloudPolicyProvider(const PolicyDefinitionList* policy_list);
+ CloudPolicyProvider(BrowserPolicyConnector* browser_policy_connector,
+ const PolicyDefinitionList* policy_list,
+ PolicyLevel level);
virtual ~CloudPolicyProvider();
- // Adds a new instance of CloudPolicyCacheBase to the end of |caches_|.
- // Does not take ownership of |cache| and listens to OnCacheGoingAway to
- // automatically remove it from |caches_|.
- virtual void AppendCache(CloudPolicyCacheBase* cache) = 0;
+ // Sets the user policy cache. This must be invoked only once, and |cache|
+ // must not be NULL.
+ void SetUserPolicyCache(CloudPolicyCacheBase* cache);
+
+#if defined(OS_CHROMEOS)
+ // Sets the device policy cache. This must be invoked only once, and |cache|
+ // must not be NULL.
+ void SetDevicePolicyCache(CloudPolicyCacheBase* cache);
+#endif
- // Adds a new instance of CloudPolicyCacheBase to the beginning of |caches_|.
- // Does not take ownership of |cache| and listens to OnCacheGoingAway to
- // automatically remove it from |caches_|.
- virtual void PrependCache(CloudPolicyCacheBase* cache) = 0;
+ // ConfigurationPolicyProvider implementation.
+ virtual bool ProvideInternal(PolicyMap* result) OVERRIDE;
+ virtual bool IsInitializationComplete() const OVERRIDE;
+ virtual void RefreshPolicies() OVERRIDE;
+
+ // CloudPolicyCacheBase::Observer implementation.
+ virtual void OnCacheUpdate(CloudPolicyCacheBase* cache) OVERRIDE;
+ virtual void OnCacheGoingAway(CloudPolicyCacheBase* cache) OVERRIDE;
private:
+ // Indices of the known caches in |caches_|.
+ enum {
+ CACHE_USER,
+#if defined(OS_CHROMEOS)
+ CACHE_DEVICE,
+#endif
+ CACHE_SIZE,
+ };
+
+ // Merges policies from both caches, and triggers a notification if ready.
+ void Merge();
+
+ // The device and user policy caches, whose policies are provided by |this|.
+ // Both are initially NULL, and the provider only becomes initialized once
+ // all the caches are available and ready.
+ CloudPolicyCacheBase* caches_[CACHE_SIZE];
+
+ // Weak pointer to the connector. Guaranteed to outlive |this|.
+ BrowserPolicyConnector* browser_policy_connector_;
+
+ // The policy level published by this provider.
+ PolicyLevel level_;
+
+ // Whether all caches are present and fully initialized.
+ bool initialization_complete_;
+
+ // Used to determine when updates due to a RefreshPolicies() call have been
+ // completed.
+ std::set<const CloudPolicyCacheBase*> pending_updates_;
+
+ // The currently valid combination of the caches. ProvideInternal() fills
+ // |results| with a copy of |combined_|.
+ PolicyMap combined_;
+
DISALLOW_COPY_AND_ASSIGN(CloudPolicyProvider);
};
diff --git a/chrome/browser/policy/cloud_policy_provider_impl.cc b/chrome/browser/policy/cloud_policy_provider_impl.cc
deleted file mode 100644
index 3e229a3..0000000
--- a/chrome/browser/policy/cloud_policy_provider_impl.cc
+++ /dev/null
@@ -1,113 +0,0 @@
-// Copyright (c) 2012 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/cloud_policy_provider_impl.h"
-
-#include <algorithm>
-
-#include "chrome/browser/policy/browser_policy_connector.h"
-#include "chrome/browser/policy/configuration_policy_pref_store.h"
-
-namespace policy {
-
-CloudPolicyProviderImpl::CloudPolicyProviderImpl(
- BrowserPolicyConnector* browser_policy_connector,
- const PolicyDefinitionList* policy_list,
- PolicyLevel level)
- : CloudPolicyProvider(policy_list),
- browser_policy_connector_(browser_policy_connector),
- level_(level),
- initialization_complete_(true) {}
-
-CloudPolicyProviderImpl::~CloudPolicyProviderImpl() {
- for (ListType::iterator i = caches_.begin(); i != caches_.end(); ++i)
- (*i)->RemoveObserver(this);
-}
-
-bool CloudPolicyProviderImpl::ProvideInternal(PolicyMap* result) {
- result->CopyFrom(combined_);
- return true;
-}
-
-bool CloudPolicyProviderImpl::IsInitializationComplete() const {
- return initialization_complete_;
-}
-
-void CloudPolicyProviderImpl::RefreshPolicies() {
- pending_update_caches_ = caches_;
- if (pending_update_caches_.empty())
- NotifyPolicyUpdated();
- else
- browser_policy_connector_->FetchCloudPolicy();
-}
-
-void CloudPolicyProviderImpl::OnCacheUpdate(CloudPolicyCacheBase* cache) {
- RemoveCache(cache, &pending_update_caches_);
- RecombineCachesAndTriggerUpdate();
-}
-
-void CloudPolicyProviderImpl::OnCacheGoingAway(CloudPolicyCacheBase* cache) {
- cache->RemoveObserver(this);
- RemoveCache(cache, &caches_);
- RemoveCache(cache, &pending_update_caches_);
- RecombineCachesAndTriggerUpdate();
-}
-
-void CloudPolicyProviderImpl::AppendCache(CloudPolicyCacheBase* cache) {
- initialization_complete_ &= cache->IsReady();
- cache->AddObserver(this);
- caches_.push_back(cache);
- RecombineCachesAndTriggerUpdate();
-}
-
-void CloudPolicyProviderImpl::PrependCache(CloudPolicyCacheBase* cache) {
- initialization_complete_ &= cache->IsReady();
- cache->AddObserver(this);
- caches_.insert(caches_.begin(), cache);
- RecombineCachesAndTriggerUpdate();
-}
-
-void CloudPolicyProviderImpl::RecombineCachesAndTriggerUpdate() {
- // Re-check whether all caches are ready.
- if (!initialization_complete_) {
- bool all_caches_ready = true;
- for (ListType::const_iterator i = caches_.begin();
- i != caches_.end(); ++i) {
- if (!(*i)->IsReady()) {
- all_caches_ready = false;
- break;
- }
- }
- if (all_caches_ready)
- initialization_complete_ = true;
- }
-
- // Reconstruct the merged policy map.
- PolicyMap newly_combined;
- PolicyMap cache_policies;
- for (ListType::iterator i = caches_.begin(); i != caches_.end(); ++i) {
- if (!(*i)->IsReady())
- continue;
- cache_policies.CopyFrom(*(*i)->policy());
- FixDeprecatedPolicies(&cache_policies);
- newly_combined.MergeFrom(cache_policies);
- }
-
- newly_combined.FilterLevel(level_);
- combined_.Swap(&newly_combined);
-
- // Trigger a notification.
- if (pending_update_caches_.empty())
- NotifyPolicyUpdated();
-}
-
-// static
-void CloudPolicyProviderImpl::RemoveCache(CloudPolicyCacheBase* cache,
- ListType* caches) {
- ListType::iterator it = std::find(caches->begin(), caches->end(), cache);
- if (it != caches->end())
- caches->erase(it);
-}
-
-} // namespace policy
diff --git a/chrome/browser/policy/cloud_policy_provider_impl.h b/chrome/browser/policy/cloud_policy_provider_impl.h
deleted file mode 100644
index da0acbe..0000000
--- a/chrome/browser/policy/cloud_policy_provider_impl.h
+++ /dev/null
@@ -1,77 +0,0 @@
-// Copyright (c) 2012 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_CLOUD_POLICY_PROVIDER_IMPL_H_
-#define CHROME_BROWSER_POLICY_CLOUD_POLICY_PROVIDER_IMPL_H_
-#pragma once
-
-#include <vector>
-
-#include "chrome/browser/policy/cloud_policy_cache_base.h"
-#include "chrome/browser/policy/cloud_policy_provider.h"
-#include "chrome/browser/policy/policy_map.h"
-
-namespace policy {
-
-class BrowserPolicyConnector;
-
-class CloudPolicyProviderImpl : public CloudPolicyProvider,
- public CloudPolicyCacheBase::Observer {
- public:
- CloudPolicyProviderImpl(BrowserPolicyConnector* browser_policy_connector,
- const PolicyDefinitionList* policy_list,
- PolicyLevel level);
- virtual ~CloudPolicyProviderImpl();
-
- // ConfigurationPolicyProvider implementation.
- virtual bool ProvideInternal(PolicyMap* result) OVERRIDE;
- virtual bool IsInitializationComplete() const OVERRIDE;
- virtual void RefreshPolicies() OVERRIDE;
-
- // CloudPolicyCacheBase::Observer implementation.
- virtual void OnCacheUpdate(CloudPolicyCacheBase* cache) OVERRIDE;
- virtual void OnCacheGoingAway(CloudPolicyCacheBase* cache) OVERRIDE;
- virtual void AppendCache(CloudPolicyCacheBase* cache) OVERRIDE;
- virtual void PrependCache(CloudPolicyCacheBase* cache) OVERRIDE;
-
- private:
- friend class CloudPolicyProviderTest;
-
- typedef std::vector<CloudPolicyCacheBase*> ListType;
-
- // Recompute |combined_| from |caches_| and trigger an OnUpdatePolicy if
- // something changed. This is called whenever a change in one of the caches
- // is observed. For i=0..n-1: |caches_[i]| will contribute all its policies
- // except those already provided by |caches_[0]|..|caches_[i-1]|.
- void RecombineCachesAndTriggerUpdate();
-
- // Removes |cache| from |caches|, if contained therein.
- static void RemoveCache(CloudPolicyCacheBase* cache, ListType* caches);
-
- // Weak pointer to the connector. Guaranteed to outlive |this|.
- BrowserPolicyConnector* browser_policy_connector_;
-
- // The underlying policy caches.
- ListType caches_;
-
- // Caches with pending updates. Used by RefreshPolicies to determine if a
- // refresh has fully completed.
- ListType pending_update_caches_;
-
- // Policy level this provider will handle.
- PolicyLevel level_;
-
- // Whether all caches are fully initialized.
- bool initialization_complete_;
-
- // The currently valid combination of all the maps in |caches_|. Will be
- // applied as is on call of Provide.
- PolicyMap combined_;
-
- DISALLOW_COPY_AND_ASSIGN(CloudPolicyProviderImpl);
-};
-
-} // namespace policy
-
-#endif // CHROME_BROWSER_POLICY_CLOUD_POLICY_PROVIDER_IMPL_H_
diff --git a/chrome/browser/policy/cloud_policy_provider_unittest.cc b/chrome/browser/policy/cloud_policy_provider_unittest.cc
index cd0f1b9..8a96ec3 100644
--- a/chrome/browser/policy/cloud_policy_provider_unittest.cc
+++ b/chrome/browser/policy/cloud_policy_provider_unittest.cc
@@ -8,58 +8,46 @@
#include "base/values.h"
#include "chrome/browser/policy/browser_policy_connector.h"
#include "chrome/browser/policy/cloud_policy_cache_base.h"
-#include "chrome/browser/policy/cloud_policy_provider_impl.h"
-#include "chrome/browser/policy/configuration_policy_provider.h"
+#include "chrome/browser/policy/cloud_policy_provider.h"
#include "chrome/browser/policy/mock_configuration_policy_provider.h"
+#include "content/test/test_browser_thread.h"
#include "policy/policy_constants.h"
#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
using testing::Mock;
-using testing::_;
namespace em = enterprise_management;
namespace policy {
-namespace {
-
-// Utility function for tests.
-void SetPolicy(PolicyMap* map, const char* policy, Value* value) {
- map->Set(policy, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, value);
-}
-
-} // namespace
-
class MockCloudPolicyCache : public CloudPolicyCacheBase {
public:
MockCloudPolicyCache() {}
virtual ~MockCloudPolicyCache() {}
- // CloudPolicyCacheBase implementation.
- void Load() OVERRIDE {}
- bool SetPolicy(const em::PolicyFetchResponse& policy) OVERRIDE {
- return true;
- }
- bool DecodePolicyData(const em::PolicyData& policy_data,
- PolicyMap* policies) OVERRIDE {
+ virtual void Load() OVERRIDE {}
+
+ virtual bool SetPolicy(const em::PolicyFetchResponse& policy) OVERRIDE {
return true;
}
- void SetUnmanaged() OVERRIDE {
+ virtual void SetUnmanaged() OVERRIDE {
is_unmanaged_ = true;
}
- PolicyMap* mutable_policy() {
- return &policies_;
+ virtual bool DecodePolicyData(const em::PolicyData& policy_data,
+ PolicyMap* policies) OVERRIDE {
+ return true;
}
- void set_initialized(bool initialized) {
- initialization_complete_ = initialized;
+ PolicyMap* mutable_policy() {
+ return &policies_;
}
- void Set(const char *name, Value* value) {
- policies_.Set(name, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, value);
- }
+ // Make these methods public.
+ using CloudPolicyCacheBase::SetReady;
+ using CloudPolicyCacheBase::NotifyObservers;
private:
DISALLOW_COPY_AND_ASSIGN(MockCloudPolicyCache);
@@ -67,228 +55,184 @@ class MockCloudPolicyCache : public CloudPolicyCacheBase {
class CloudPolicyProviderTest : public testing::Test {
protected:
- void CreateCloudPolicyProvider() {
- cloud_policy_provider_.reset(
- new CloudPolicyProviderImpl(&browser_policy_connector_,
- GetChromePolicyDefinitionList(),
- POLICY_LEVEL_MANDATORY));
+ CloudPolicyProviderTest()
+ : cloud_policy_provider_(&browser_policy_connector_,
+ GetChromePolicyDefinitionList(),
+ POLICY_LEVEL_MANDATORY) {}
+
+ void SetUp() OVERRIDE {
+ registrar_.Init(&cloud_policy_provider_, &observer_);
}
- // Appends the caches to a provider and then provides the policies to
- // |result|.
- void RunCachesThroughProvider(MockCloudPolicyCache caches[], int n,
- PolicyMap* result) {
- CloudPolicyProviderImpl provider(
- &browser_policy_connector_,
- GetChromePolicyDefinitionList(),
- POLICY_LEVEL_MANDATORY);
- for (int i = 0; i < n; i++) {
- provider.AppendCache(&caches[i]);
- }
- provider.Provide(result);
+ void AddUserCache() {
+ EXPECT_CALL(observer_, OnUpdatePolicy(&cloud_policy_provider_));
+ cloud_policy_provider_.SetUserPolicyCache(&user_policy_cache_);
+ Mock::VerifyAndClearExpectations(&observer_);
}
- void CombineTwoPolicyMaps(const PolicyMap& base,
- const PolicyMap& overlay,
- PolicyMap* out_map) {
- MockCloudPolicyCache caches[2];
- caches[0].mutable_policy()->CopyFrom(base);
- caches[0].set_initialized(true);
- caches[1].mutable_policy()->CopyFrom(overlay);
- caches[1].set_initialized(true);
- RunCachesThroughProvider(caches, 2, out_map);
+ void AddDeviceCache() {
+#if defined(OS_CHROMEOS)
+ EXPECT_CALL(observer_, OnUpdatePolicy(&cloud_policy_provider_));
+ cloud_policy_provider_.SetDevicePolicyCache(&device_policy_cache_);
+ Mock::VerifyAndClearExpectations(&observer_);
+#endif
}
- void FixDeprecatedPolicies(PolicyMap* policies) {
- CloudPolicyProviderImpl::FixDeprecatedPolicies(policies);
+ void SetUserCacheReady() {
+ EXPECT_CALL(observer_, OnUpdatePolicy(&cloud_policy_provider_));
+ user_policy_cache_.SetReady();
+ Mock::VerifyAndClearExpectations(&observer_);
+ EXPECT_TRUE(user_policy_cache_.IsReady());
}
- scoped_ptr<CloudPolicyProviderImpl> cloud_policy_provider_;
+ void SetDeviceCacheReady() {
+#if defined(OS_CHROMEOS)
+ EXPECT_CALL(observer_, OnUpdatePolicy(&cloud_policy_provider_));
+ device_policy_cache_.SetReady();
+ Mock::VerifyAndClearExpectations(&observer_);
+ EXPECT_TRUE(device_policy_cache_.IsReady());
+#endif
+ }
- private:
BrowserPolicyConnector browser_policy_connector_;
-};
-// Proxy setting distributed over multiple caches.
-TEST_F(CloudPolicyProviderTest,
- ProxySettingDistributedOverMultipleCaches) {
- // There are proxy_policy_count()+1 = 6 caches and they are mixed together by
- // one instance of CloudPolicyProvider. The first cache has some policies but
- // no proxy-related ones. The following caches have each one proxy-policy set.
- const int n = 6;
- MockCloudPolicyCache caches[n];
-
- // Prepare |cache[0]| to serve some non-proxy policies.
- caches[0].Set(key::kShowHomeButton, Value::CreateBooleanValue(true));
- caches[0].Set(key::kIncognitoEnabled, Value::CreateBooleanValue(true));
- caches[0].Set(key::kTranslateEnabled, Value::CreateBooleanValue(true));
- caches[0].set_initialized(true);
-
- // Prepare the other caches to serve one proxy-policy each.
- caches[1].Set(key::kProxyMode, Value::CreateStringValue("cache 1"));
- caches[1].set_initialized(true);
- caches[2].Set(key::kProxyServerMode, Value::CreateIntegerValue(2));
- caches[2].set_initialized(true);
- caches[3].Set(key::kProxyServer, Value::CreateStringValue("cache 3"));
- caches[3].set_initialized(true);
- caches[4].Set(key::kProxyPacUrl, Value::CreateStringValue("cache 4"));
- caches[4].set_initialized(true);
- caches[5].Set(key::kProxyMode, Value::CreateStringValue("cache 5"));
- caches[5].set_initialized(true);
-
- PolicyMap policies;
- RunCachesThroughProvider(caches, n, &policies);
-
- // Verify expectations.
- EXPECT_TRUE(policies.Get(key::kProxyMode) == NULL);
- EXPECT_TRUE(policies.Get(key::kProxyServerMode) == NULL);
- EXPECT_TRUE(policies.Get(key::kProxyServer) == NULL);
- EXPECT_TRUE(policies.Get(key::kProxyPacUrl) == NULL);
-
- const Value* value = policies.GetValue(key::kProxySettings);
- ASSERT_TRUE(value != NULL);
- ASSERT_TRUE(value->IsType(Value::TYPE_DICTIONARY));
- const DictionaryValue* settings = static_cast<const DictionaryValue*>(value);
- std::string mode;
- EXPECT_TRUE(settings->GetString(key::kProxyMode, &mode));
- EXPECT_EQ("cache 1", mode);
-
- base::FundamentalValue expected(true);
- EXPECT_TRUE(base::Value::Equals(&expected,
- policies.GetValue(key::kShowHomeButton)));
- EXPECT_TRUE(base::Value::Equals(&expected,
- policies.GetValue(key::kIncognitoEnabled)));
- EXPECT_TRUE(base::Value::Equals(&expected,
- policies.GetValue(key::kTranslateEnabled)));
-}
-
-// Combining two PolicyMaps.
-TEST_F(CloudPolicyProviderTest, CombineTwoPolicyMapsSame) {
- PolicyMap A, B, C;
- SetPolicy(&A, key::kHomepageLocation,
- Value::CreateStringValue("http://www.chromium.org"));
- SetPolicy(&B, key::kHomepageLocation,
- Value::CreateStringValue("http://www.google.com"));
- SetPolicy(&A, key::kApplicationLocaleValue, Value::CreateStringValue("hu"));
- SetPolicy(&B, key::kApplicationLocaleValue, Value::CreateStringValue("us"));
- SetPolicy(&A, key::kDevicePolicyRefreshRate, new base::FundamentalValue(100));
- SetPolicy(&B, key::kDevicePolicyRefreshRate, new base::FundamentalValue(200));
- CombineTwoPolicyMaps(A, B, &C);
- EXPECT_TRUE(A.Equals(C));
-}
+ MockCloudPolicyCache user_policy_cache_;
+#if defined(OS_CHROMEOS)
+ MockCloudPolicyCache device_policy_cache_;
+#endif
-TEST_F(CloudPolicyProviderTest, CombineTwoPolicyMapsEmpty) {
- PolicyMap A, B, C;
- CombineTwoPolicyMaps(A, B, &C);
- EXPECT_TRUE(C.empty());
-}
+ CloudPolicyProvider cloud_policy_provider_;
+ MockConfigurationPolicyObserver observer_;
+ ConfigurationPolicyObserverRegistrar registrar_;
+};
-TEST_F(CloudPolicyProviderTest, CombineTwoPolicyMapsPartial) {
- PolicyMap A, B, C;
-
- SetPolicy(&A, key::kHomepageLocation,
- Value::CreateStringValue("http://www.chromium.org"));
- SetPolicy(&B, key::kHomepageLocation,
- Value::CreateStringValue("http://www.google.com"));
- SetPolicy(&B, key::kApplicationLocaleValue, Value::CreateStringValue("us"));
- SetPolicy(&A, key::kDevicePolicyRefreshRate, new base::FundamentalValue(100));
- SetPolicy(&B, key::kDevicePolicyRefreshRate, new base::FundamentalValue(200));
- CombineTwoPolicyMaps(A, B, &C);
-
- const Value* value;
- std::string string_value;
- int int_value;
- value = C.GetValue(key::kHomepageLocation);
- ASSERT_TRUE(NULL != value);
- EXPECT_TRUE(value->GetAsString(&string_value));
- EXPECT_EQ("http://www.chromium.org", string_value);
- value = C.GetValue(key::kApplicationLocaleValue);
- ASSERT_TRUE(NULL != value);
- EXPECT_TRUE(value->GetAsString(&string_value));
- EXPECT_EQ("us", string_value);
- value = C.GetValue(key::kDevicePolicyRefreshRate);
- ASSERT_TRUE(NULL != value);
- EXPECT_TRUE(value->GetAsInteger(&int_value));
- EXPECT_EQ(100, int_value);
+TEST_F(CloudPolicyProviderTest, Initialization) {
+ EXPECT_FALSE(cloud_policy_provider_.IsInitializationComplete());
+
+ // The provider only becomes initialized when it has all caches, and the
+ // caches are ready too.
+ AddDeviceCache();
+ EXPECT_FALSE(cloud_policy_provider_.IsInitializationComplete());
+ SetDeviceCacheReady();
+ EXPECT_FALSE(cloud_policy_provider_.IsInitializationComplete());
+ AddUserCache();
+ EXPECT_FALSE(user_policy_cache_.IsReady());
+ EXPECT_FALSE(cloud_policy_provider_.IsInitializationComplete());
+
+ PolicyMap policy;
+ EXPECT_TRUE(cloud_policy_provider_.Provide(&policy));
+ EXPECT_TRUE(policy.empty());
+
+ SetUserCacheReady();
+ EXPECT_TRUE(cloud_policy_provider_.IsInitializationComplete());
+ EXPECT_TRUE(cloud_policy_provider_.Provide(&policy));
+ EXPECT_TRUE(policy.empty());
+
+ const std::string kUrl("http://chromium.org");
+ user_policy_cache_.mutable_policy()->Set(key::kHomepageLocation,
+ POLICY_LEVEL_MANDATORY,
+ POLICY_SCOPE_USER,
+ Value::CreateStringValue(kUrl));
+ EXPECT_CALL(observer_, OnUpdatePolicy(&cloud_policy_provider_));
+ user_policy_cache_.NotifyObservers();
+ Mock::VerifyAndClearExpectations(&observer_);
+ EXPECT_TRUE(cloud_policy_provider_.Provide(&policy));
+
+ PolicyMap expected;
+ expected.Set(key::kHomepageLocation,
+ POLICY_LEVEL_MANDATORY,
+ POLICY_SCOPE_USER,
+ Value::CreateStringValue(kUrl));
+ EXPECT_TRUE(policy.Equals(expected));
}
-TEST_F(CloudPolicyProviderTest, CombineTwoPolicyMapsProxies) {
- const int a_value = 1;
- const int b_value = -1;
- PolicyMap A, B, C;
+TEST_F(CloudPolicyProviderTest, RefreshPolicies) {
+ // OnUpdatePolicy is called when the provider doesn't have any caches.
+ EXPECT_CALL(observer_, OnUpdatePolicy(&cloud_policy_provider_)).Times(1);
+ cloud_policy_provider_.RefreshPolicies();
+ Mock::VerifyAndClearExpectations(&observer_);
- SetPolicy(&A, key::kProxyMode, Value::CreateIntegerValue(a_value));
- SetPolicy(&B, key::kProxyServerMode, Value::CreateIntegerValue(b_value));
- SetPolicy(&B, key::kProxyServer, Value::CreateIntegerValue(b_value));
- SetPolicy(&B, key::kProxyPacUrl, Value::CreateIntegerValue(b_value));
- SetPolicy(&B, key::kProxyBypassList, Value::CreateIntegerValue(b_value));
+ // OnUpdatePolicy is called when all the caches have updated.
+ AddUserCache();
- CombineTwoPolicyMaps(A, B, &C);
+ EXPECT_CALL(observer_, OnUpdatePolicy(&cloud_policy_provider_)).Times(0);
+ cloud_policy_provider_.RefreshPolicies();
+ Mock::VerifyAndClearExpectations(&observer_);
- FixDeprecatedPolicies(&A);
- FixDeprecatedPolicies(&B);
- EXPECT_TRUE(A.Equals(C));
- EXPECT_FALSE(B.Equals(C));
-}
+ EXPECT_CALL(observer_, OnUpdatePolicy(&cloud_policy_provider_)).Times(1);
+ cloud_policy_provider_.OnCacheUpdate(&user_policy_cache_);
+ Mock::VerifyAndClearExpectations(&observer_);
-TEST_F(CloudPolicyProviderTest, RefreshPolicies) {
- CreateCloudPolicyProvider();
- MockCloudPolicyCache cache0;
- MockCloudPolicyCache cache1;
- MockCloudPolicyCache cache2;
- MockConfigurationPolicyObserver observer;
- ConfigurationPolicyObserverRegistrar registrar;
- registrar.Init(cloud_policy_provider_.get(), &observer);
+#if defined(OS_CHROMEOS)
+ AddDeviceCache();
- // OnUpdatePolicy is called when the provider doesn't have any caches.
- EXPECT_CALL(observer, OnUpdatePolicy(cloud_policy_provider_.get())).Times(1);
- cloud_policy_provider_->RefreshPolicies();
- Mock::VerifyAndClearExpectations(&observer);
+ EXPECT_CALL(observer_, OnUpdatePolicy(&cloud_policy_provider_)).Times(0);
+ cloud_policy_provider_.RefreshPolicies();
+ Mock::VerifyAndClearExpectations(&observer_);
- // OnUpdatePolicy is called when all the caches have updated.
- EXPECT_CALL(observer, OnUpdatePolicy(cloud_policy_provider_.get())).Times(2);
- cloud_policy_provider_->AppendCache(&cache0);
- cloud_policy_provider_->AppendCache(&cache1);
- Mock::VerifyAndClearExpectations(&observer);
-
- EXPECT_CALL(observer, OnUpdatePolicy(cloud_policy_provider_.get())).Times(0);
- cloud_policy_provider_->RefreshPolicies();
- Mock::VerifyAndClearExpectations(&observer);
-
- EXPECT_CALL(observer, OnUpdatePolicy(cloud_policy_provider_.get())).Times(0);
- // Updating just one of the caches is not enough.
- cloud_policy_provider_->OnCacheUpdate(&cache0);
- Mock::VerifyAndClearExpectations(&observer);
-
- EXPECT_CALL(observer, OnUpdatePolicy(cloud_policy_provider_.get())).Times(0);
- // This cache wasn't available when RefreshPolicies was called, so it isn't
- // required to fire the update.
- cloud_policy_provider_->AppendCache(&cache2);
- Mock::VerifyAndClearExpectations(&observer);
-
- EXPECT_CALL(observer, OnUpdatePolicy(cloud_policy_provider_.get())).Times(1);
- cloud_policy_provider_->OnCacheUpdate(&cache1);
- Mock::VerifyAndClearExpectations(&observer);
-
- EXPECT_CALL(observer, OnUpdatePolicy(cloud_policy_provider_.get())).Times(0);
- cloud_policy_provider_->RefreshPolicies();
- Mock::VerifyAndClearExpectations(&observer);
-
- EXPECT_CALL(observer, OnUpdatePolicy(cloud_policy_provider_.get())).Times(0);
- cloud_policy_provider_->OnCacheUpdate(&cache0);
- cloud_policy_provider_->OnCacheUpdate(&cache1);
- Mock::VerifyAndClearExpectations(&observer);
+ // Updating one of the caches is not enough, both must be updated.
+ EXPECT_CALL(observer_, OnUpdatePolicy(&cloud_policy_provider_)).Times(0);
+ cloud_policy_provider_.OnCacheUpdate(&user_policy_cache_);
+ Mock::VerifyAndClearExpectations(&observer_);
// If a cache refreshes more than once, the provider should still wait for
// the others before firing the update.
- EXPECT_CALL(observer, OnUpdatePolicy(cloud_policy_provider_.get())).Times(0);
- cloud_policy_provider_->OnCacheUpdate(&cache0);
- Mock::VerifyAndClearExpectations(&observer);
-
- // Fire updates if one of the required caches goes away while waiting.
- EXPECT_CALL(observer, OnUpdatePolicy(cloud_policy_provider_.get())).Times(1);
- cloud_policy_provider_->OnCacheGoingAway(&cache2);
- Mock::VerifyAndClearExpectations(&observer);
+ EXPECT_CALL(observer_, OnUpdatePolicy(&cloud_policy_provider_)).Times(0);
+ cloud_policy_provider_.OnCacheUpdate(&user_policy_cache_);
+ Mock::VerifyAndClearExpectations(&observer_);
+
+ EXPECT_CALL(observer_, OnUpdatePolicy(&cloud_policy_provider_)).Times(1);
+ cloud_policy_provider_.OnCacheUpdate(&device_policy_cache_);
+ Mock::VerifyAndClearExpectations(&observer_);
+#endif
+}
+
+#if defined(OS_CHROMEOS)
+TEST_F(CloudPolicyProviderTest, MergeProxyPolicies) {
+ AddDeviceCache();
+ AddUserCache();
+ SetDeviceCacheReady();
+ SetUserCacheReady();
+ EXPECT_TRUE(cloud_policy_provider_.IsInitializationComplete());
+ PolicyMap policy;
+ EXPECT_TRUE(cloud_policy_provider_.Provide(&policy));
+ EXPECT_TRUE(policy.empty());
+
+ // User policy takes precedence over device policy.
+ EXPECT_CALL(observer_, OnUpdatePolicy(&cloud_policy_provider_));
+ device_policy_cache_.mutable_policy()->Set(
+ key::kProxyMode, POLICY_LEVEL_RECOMMENDED, POLICY_SCOPE_MACHINE,
+ Value::CreateStringValue("device mode"));
+ device_policy_cache_.NotifyObservers();
+ Mock::VerifyAndClearExpectations(&observer_);
+
+ EXPECT_CALL(observer_, OnUpdatePolicy(&cloud_policy_provider_));
+ user_policy_cache_.mutable_policy()->Set(
+ key::kProxyMode, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
+ Value::CreateStringValue("user mode"));
+ user_policy_cache_.NotifyObservers();
+ Mock::VerifyAndClearExpectations(&observer_);
+
+ EXPECT_TRUE(cloud_policy_provider_.Provide(&policy));
+
+ // The deprecated proxy policies are converted to the new ProxySettings.
+ EXPECT_TRUE(policy.Get(key::kProxyMode) == NULL);
+ EXPECT_TRUE(policy.Get(key::kProxyServerMode) == NULL);
+ EXPECT_TRUE(policy.Get(key::kProxyServer) == NULL);
+ EXPECT_TRUE(policy.Get(key::kProxyPacUrl) == NULL);
+
+ EXPECT_EQ(1u, policy.size());
+ const PolicyMap::Entry* entry = policy.Get(key::kProxySettings);
+ ASSERT_TRUE(entry != NULL);
+ ASSERT_TRUE(entry->value != NULL);
+ EXPECT_EQ(POLICY_LEVEL_MANDATORY, entry->level);
+ EXPECT_EQ(POLICY_SCOPE_USER, entry->scope);
+ const DictionaryValue* settings;
+ ASSERT_TRUE(entry->value->GetAsDictionary(&settings));
+ std::string mode;
+ EXPECT_TRUE(settings->GetString(key::kProxyMode, &mode));
+ EXPECT_EQ("user mode", mode);
}
+#endif
} // namespace policy
diff --git a/chrome/browser/policy/cloud_policy_subsystem_unittest.cc b/chrome/browser/policy/cloud_policy_subsystem_unittest.cc
index aca96d4..054a2a0 100644
--- a/chrome/browser/policy/cloud_policy_subsystem_unittest.cc
+++ b/chrome/browser/policy/cloud_policy_subsystem_unittest.cc
@@ -104,11 +104,10 @@ class CloudPolicySubsystemTestBase : public testing::Test {
public:
CloudPolicySubsystemTestBase()
: ui_thread_(BrowserThread::UI, &loop_),
- io_thread_(BrowserThread::IO, &loop_) {
- }
+ file_thread_(BrowserThread::FILE, &loop_),
+ io_thread_(BrowserThread::IO, &loop_) {}
- virtual ~CloudPolicySubsystemTestBase() {
- }
+ virtual ~CloudPolicySubsystemTestBase() {}
protected:
void StopMessageLoop() {
@@ -250,6 +249,7 @@ class CloudPolicySubsystemTestBase : public testing::Test {
MessageLoop loop_;
content::TestBrowserThread ui_thread_;
+ content::TestBrowserThread file_thread_;
content::TestBrowserThread io_thread_;
scoped_ptr<EventLogger> logger_;
diff --git a/chrome/browser/policy/configuration_policy_provider.cc b/chrome/browser/policy/configuration_policy_provider.cc
index 6d67d67..4ecb9ec 100644
--- a/chrome/browser/policy/configuration_policy_provider.cc
+++ b/chrome/browser/policy/configuration_policy_provider.cc
@@ -97,7 +97,11 @@ void ConfigurationPolicyProvider::FixDeprecatedPolicies(PolicyMap* policies) {
policies->Erase(kProxyPolicies[i]);
}
}
- if (!proxy_settings->empty() && !policies->Get(key::kProxySettings)) {
+ // 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,
diff --git a/chrome/browser/policy/user_policy_disk_cache.cc b/chrome/browser/policy/user_policy_disk_cache.cc
index 1aa19a5..4b08836 100644
--- a/chrome/browser/policy/user_policy_disk_cache.cc
+++ b/chrome/browser/policy/user_policy_disk_cache.cc
@@ -46,9 +46,10 @@ UserPolicyDiskCache::UserPolicyDiskCache(
void UserPolicyDiskCache::Load() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- BrowserThread::PostTask(
+ bool ret = BrowserThread::PostTask(
BrowserThread::FILE, FROM_HERE,
base::Bind(&UserPolicyDiskCache::LoadOnFileThread, this));
+ DCHECK(ret);
}
void UserPolicyDiskCache::Store(