diff options
author | joaodasilva@chromium.org <joaodasilva@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-03-31 22:02:23 +0000 |
---|---|---|
committer | joaodasilva@chromium.org <joaodasilva@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-03-31 22:02:23 +0000 |
commit | d9720f50db7dbe830e4b9acd302e7f799a2a85f1 (patch) | |
tree | 9d81bb0e4718c189e1a6746460e9b3bc45c9944e /chrome/browser/policy | |
parent | 65c09bc81db6fa9b0c43345a00cf16b054d65a43 (diff) | |
download | chromium_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.cc | 40 | ||||
-rw-r--r-- | chrome/browser/policy/cloud_policy_provider.cc | 98 | ||||
-rw-r--r-- | chrome/browser/policy/cloud_policy_provider.h | 89 | ||||
-rw-r--r-- | chrome/browser/policy/cloud_policy_provider_impl.cc | 113 | ||||
-rw-r--r-- | chrome/browser/policy/cloud_policy_provider_impl.h | 77 | ||||
-rw-r--r-- | chrome/browser/policy/cloud_policy_provider_unittest.cc | 394 | ||||
-rw-r--r-- | chrome/browser/policy/cloud_policy_subsystem_unittest.cc | 8 | ||||
-rw-r--r-- | chrome/browser/policy/configuration_policy_provider.cc | 6 | ||||
-rw-r--r-- | chrome/browser/policy/user_policy_disk_cache.cc | 3 |
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( |