Index: chrome/browser/policy/cloud_policy_cache_base.cc |
diff --git a/chrome/browser/policy/cloud_policy_cache_base.cc b/chrome/browser/policy/cloud_policy_cache_base.cc |
index 5fdf08ed3fa60c3ac5e8efd23457681e151f8e03..81937e75c4eaf354541591b1ef02fdb39fc23e4f 100644 |
--- a/chrome/browser/policy/cloud_policy_cache_base.cc |
+++ b/chrome/browser/policy/cloud_policy_cache_base.cc |
@@ -4,6 +4,7 @@ |
#include "chrome/browser/policy/cloud_policy_cache_base.h" |
+#include <set> |
#include <string> |
#include "base/logging.h" |
@@ -13,62 +14,182 @@ |
namespace policy { |
-// A thin ConfigurationPolicyProvider implementation sitting on top of |
-// CloudPolicyCacheBase for hooking up with ConfigurationPolicyPrefStore. |
-class CloudPolicyCacheBase::CloudPolicyProvider |
- : public ConfigurationPolicyProvider { |
- public: |
- CloudPolicyProvider(const PolicyDefinitionList* policy_list, |
- CloudPolicyCacheBase* cache, |
- CloudPolicyCacheBase::PolicyLevel level) |
- : ConfigurationPolicyProvider(policy_list), |
- cache_(cache), |
- level_(level) {} |
- virtual ~CloudPolicyProvider() {} |
- |
- virtual bool Provide(ConfigurationPolicyStoreInterface* store) { |
- if (level_ == POLICY_LEVEL_MANDATORY) |
- ApplyPolicyMap(&cache_->mandatory_policy_, store); |
- else if (level_ == POLICY_LEVEL_RECOMMENDED) |
- ApplyPolicyMap(&cache_->recommended_policy_, store); |
- return true; |
- } |
+CloudPolicyProvider::CloudPolicyProvider( |
+ const ConfigurationPolicyProvider::PolicyDefinitionList* policy_list, |
+ CloudPolicyCacheBase::PolicyLevel level) |
+ : ConfigurationPolicyProvider(policy_list), |
+ cache_(NULL), |
+ level_(level) {} |
- virtual bool IsInitializationComplete() const { |
- return cache_->initialization_complete_; |
- } |
+CloudPolicyProvider::~CloudPolicyProvider() { |
+ FOR_EACH_OBSERVER(ConfigurationPolicyProvider::Observer, |
+ observer_list_, OnProviderGoingAway()); |
+ if (cache_) |
+ cache_->RemoveObserver(this); |
+} |
+ |
+void CloudPolicyProvider::set_cache(CloudPolicyCacheBase* cache) { |
+ cache_ = cache; |
+ cache_->AddObserver(this); |
+} |
+ |
+bool CloudPolicyProvider::Provide(ConfigurationPolicyStoreInterface* store) { |
+ if (!cache_) |
+ return false; |
+ if (level_ == CloudPolicyCacheBase::POLICY_LEVEL_MANDATORY) |
+ ApplyPolicyMap(cache_->mandatory_policy(), store); |
+ else if (level_ == CloudPolicyCacheBase::POLICY_LEVEL_RECOMMENDED) |
+ ApplyPolicyMap(cache_->recommended_policy(), store); |
+ return true; |
+} |
+ |
+bool CloudPolicyProvider::IsInitializationComplete() const { |
+ return cache_ && cache_->initialization_complete(); |
+} |
+ |
+void CloudPolicyProvider::AddObserver( |
+ ConfigurationPolicyProvider::Observer* observer) { |
+ observer_list_.AddObserver(observer); |
+} |
+void CloudPolicyProvider::RemoveObserver( |
+ ConfigurationPolicyProvider::Observer* observer) { |
+ observer_list_.RemoveObserver(observer); |
+} |
+ |
+void CloudPolicyProvider::OnUpdatePolicy() { |
+ FOR_EACH_OBSERVER(ConfigurationPolicyProvider::Observer, |
+ observer_list_, OnUpdatePolicy()); |
+} |
+ |
+void CloudPolicyProvider::OnProviderGoingAway() { |
+ cache_->RemoveObserver(this); |
+ cache_ = NULL; |
+} |
+ |
+PolicyMap* CloudPolicyProvider::policy_map() { |
+ if (!cache_) |
+ return NULL; |
+ if (level_ == CloudPolicyCacheBase::POLICY_LEVEL_MANDATORY) |
+ return cache_->mandatory_policy(); |
+ else if (level_ == CloudPolicyCacheBase::POLICY_LEVEL_RECOMMENDED) |
+ return cache_->recommended_policy(); |
+ NOTREACHED(); |
+ return NULL; |
+} |
+ |
+CombiningCloudPolicyProvider::CombiningCloudPolicyProvider( |
+ const ConfigurationPolicyProvider::PolicyDefinitionList* policy_list) |
+ : ConfigurationPolicyProvider(policy_list) {} |
+ |
+CombiningCloudPolicyProvider::~CombiningCloudPolicyProvider() { |
+ FOR_EACH_OBSERVER(ConfigurationPolicyProvider::Observer, |
+ observer_list_, OnProviderGoingAway()); |
+} |
- virtual void AddObserver(ConfigurationPolicyProvider::Observer* observer) { |
- cache_->observer_list_.AddObserver(observer); |
+void CombiningCloudPolicyProvider::AddCloudPolicyProvider( |
+ CloudPolicyProvider* cloud_policy_provider) { |
+ cloud_policy_providers_.push_back( |
+ new CloudPolicyProviderWithObserver(this, |
+ cloud_policy_provider)); |
+} |
+ |
+bool CombiningCloudPolicyProvider::Provide( |
+ ConfigurationPolicyStoreInterface* store) { |
+ typedef std::set<ConfigurationPolicyType> PolicySet; |
+ PolicySet already_applied; |
+ PolicySet newly_applied; |
+ for (ListType::iterator i = cloud_policy_providers_.begin(); |
+ i != cloud_policy_providers_.end(); ++i) { |
+ if ((*i)->cloud_policy_provider() && |
+ (*i)->cloud_policy_provider()->IsInitializationComplete()) { |
+ PolicyMap* policy_map = (*i)->cloud_policy_provider()->policy_map(); |
+ if (policy_map) { |
+ const PolicyDefinitionList* policy_list(policy_definition_list()); |
+ for (const PolicyDefinitionList::Entry* j = policy_list->begin; |
+ j != policy_list->end; ++j) { |
+ // Already applied by a CloudProvider which takes precedence. |
+ if (already_applied.find(j->policy_type)!=already_applied.end()) |
+ continue; |
+ const Value* value = policy_map->Get(j->policy_type); |
+ if (value && value->IsType(j->value_type)) { |
+ newly_applied.insert(j->policy_type); |
+ store->Apply(j->policy_type, value->DeepCopy()); |
+ } |
+ } |
+ // Update the already_applied PolicySet |
+ for (PolicySet::iterator policy = newly_applied.begin(); |
+ policy != newly_applied.end(); ++policy) { |
+ already_applied.insert(*policy); |
+ // In case that one Proxy Policy got applied, we want to set all of |
+ // them as applied. We need that in order not to end up with an |
+ // inconsistend Proxy-state in case that the different Policy-related |
+ // Policies got set by different CloudPolicyProviders. |
+ if (*policy == kPolicyProxyMode || |
+ *policy == kPolicyProxyServerMode || |
+ *policy == kPolicyProxyServer || |
+ *policy == kPolicyProxyPacUrl || |
+ *policy == kPolicyProxyBypassList) { |
+ already_applied.insert(kPolicyProxyMode); |
+ already_applied.insert(kPolicyProxyServerMode); |
+ already_applied.insert(kPolicyProxyServer); |
+ already_applied.insert(kPolicyProxyPacUrl); |
+ already_applied.insert(kPolicyProxyBypassList); |
+ } |
+ } |
+ } |
+ } |
} |
- virtual void RemoveObserver(ConfigurationPolicyProvider::Observer* observer) { |
- cache_->observer_list_.RemoveObserver(observer); |
+ // Return true if we could apply at least one policy. |
+ return !already_applied.empty(); |
+} |
+ |
+bool CombiningCloudPolicyProvider::IsInitializationComplete() const { |
+ bool initialization_complete = false; |
+ for (ListType::const_iterator i = cloud_policy_providers_.begin(); |
+ i != cloud_policy_providers_.end(); ++i) { |
+ initialization_complete = initialization_complete || |
+ ((*i)->cloud_policy_provider() && |
+ (*i)->cloud_policy_provider()->IsInitializationComplete()); |
} |
+ return initialization_complete; |
+} |
+ |
+void CombiningCloudPolicyProvider::AddObserver( |
+ ConfigurationPolicyProvider::Observer* observer) { |
+ observer_list_.AddObserver(observer); |
+} |
- private: |
- // The underlying policy cache. |
- CloudPolicyCacheBase* cache_; |
- // Policy level this provider will handle. |
- CloudPolicyCacheBase::PolicyLevel level_; |
+void CombiningCloudPolicyProvider::RemoveObserver( |
+ ConfigurationPolicyProvider::Observer* observer) { |
+ observer_list_.RemoveObserver(observer); |
+} |
- DISALLOW_COPY_AND_ASSIGN(CloudPolicyProvider); |
-}; |
+// Note: we are triggering updates even though the change might not actually be |
+// visible to the outside. |
+void CombiningCloudPolicyProvider::OnUpdatePolicy( |
+ CloudPolicyProvider* cloud_policy_provider) { |
+ FOR_EACH_OBSERVER(ConfigurationPolicyProvider::Observer, |
+ observer_list_, OnUpdatePolicy()); |
+} |
+ |
+// Removes the going-away CloudPolicyProvider from |cloud_policy_providers_|. |
+void CombiningCloudPolicyProvider::OnProviderGoingAway( |
+ CloudPolicyProvider* cloud_policy_provider) { |
+ ListType::iterator i; |
+ for (i = cloud_policy_providers_.begin(); |
+ i != cloud_policy_providers_.end(); ++i) { |
+ if ((*i)->cloud_policy_provider() == cloud_policy_provider) { |
+ cloud_policy_providers_.erase(i); |
+ return; |
+ } |
+ } |
+} |
CloudPolicyCacheBase::CloudPolicyCacheBase() |
: notifier_(NULL), |
initialization_complete_(false), |
is_unmanaged_(false) { |
public_key_version_.valid = false; |
- managed_policy_provider_.reset( |
- new CloudPolicyProvider( |
- ConfigurationPolicyPrefStore::GetChromePolicyDefinitionList(), |
- this, |
- POLICY_LEVEL_MANDATORY)); |
- recommended_policy_provider_.reset( |
- new CloudPolicyProvider( |
- ConfigurationPolicyPrefStore::GetChromePolicyDefinitionList(), |
- this, |
- POLICY_LEVEL_RECOMMENDED)); |
} |
CloudPolicyCacheBase::~CloudPolicyCacheBase() { |
@@ -76,6 +197,24 @@ CloudPolicyCacheBase::~CloudPolicyCacheBase() { |
observer_list_, OnProviderGoingAway()); |
} |
+void CloudPolicyCacheBase::AddObserver( |
+ ConfigurationPolicyProvider::Observer* observer) { |
+ observer_list_.AddObserver(observer); |
+} |
+ |
+void CloudPolicyCacheBase::RemoveObserver( |
+ ConfigurationPolicyProvider::Observer* observer) { |
+ observer_list_.RemoveObserver(observer); |
+} |
+ |
+PolicyMap* CloudPolicyCacheBase::mandatory_policy() { |
+ return &mandatory_policy_; |
+} |
+ |
+PolicyMap* CloudPolicyCacheBase::recommended_policy() { |
+ return &recommended_policy_; |
+} |
+ |
bool CloudPolicyCacheBase::GetPublicKeyVersion(int* version) { |
if (public_key_version_.valid) |
*version = public_key_version_.version; |
@@ -139,17 +278,6 @@ void CloudPolicyCacheBase::SetUnmanagedInternal(const base::Time& timestamp) { |
observer_list_, OnUpdatePolicy()); |
} |
-ConfigurationPolicyProvider* CloudPolicyCacheBase::GetManagedPolicyProvider() { |
- DCHECK(CalledOnValidThread()); |
- return managed_policy_provider_.get(); |
-} |
- |
-ConfigurationPolicyProvider* |
- CloudPolicyCacheBase::GetRecommendedPolicyProvider() { |
- DCHECK(CalledOnValidThread()); |
- return recommended_policy_provider_.get(); |
-} |
- |
bool CloudPolicyCacheBase::DecodePolicyResponse( |
const em::PolicyFetchResponse& policy_response, |
PolicyMap* mandatory, |