Index: chrome/browser/policy/policy_change_watcher.cc |
diff --git a/chrome/browser/policy/policy_change_watcher.cc b/chrome/browser/policy/policy_change_watcher.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..0bc86ab2b4471f3e1be451492f0edb564cbc9522 |
--- /dev/null |
+++ b/chrome/browser/policy/policy_change_watcher.cc |
@@ -0,0 +1,190 @@ |
+// Copyright (c) 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_change_watcher.h" |
+ |
+#include "base/json/json_writer.h" |
+ #include "base/logging.h" |
+#include "base/memory/scoped_ptr.h" |
+#include "base/prefs/pref_registry_simple.h" |
+#include "base/prefs/pref_service.h" |
+#include "base/strings/string_number_conversions.h" |
+#include "base/values.h" |
+#include "chrome/browser/browser_process.h" |
+#include "chrome/browser/policy/policy_namespace.h" |
+#include "chrome/browser/prefs/pref_registry_syncable.h" |
+#include "chrome/browser/prefs/scoped_user_pref_update.h" |
+#include "chrome/browser/profiles/profile.h" |
+#include "chrome/common/pref_names.h" |
+#include "crypto/sha2.h" |
+ |
+namespace policy { |
+ |
+PolicyServiceChangeWatcher::PolicyServiceChangeWatcher( |
+ PolicyService* policy_service, |
+ const std::string& current_hash) |
+ : domains_pending_initialization_(0), |
+ current_hash_(current_hash), |
+ policy_service_(policy_service) { |
+} |
+ |
+PolicyServiceChangeWatcher::~PolicyServiceChangeWatcher() { |
+ for (size_t i = 0; i < POLICY_DOMAIN_SIZE; ++i) |
+ policy_service_->RemoveObserver(static_cast<PolicyDomain>(i), this); |
+} |
+ |
+void PolicyServiceChangeWatcher::OnPolicyUpdated(const PolicyNamespace& ns, |
+ const PolicyMap& previous, |
+ const PolicyMap& current) { |
+ if (is_initialization_complete()) |
+ CheckIfPolicyChanged(policy_service_->GetAllPolicies()); |
+} |
+ |
+void PolicyServiceChangeWatcher::OnPolicyServiceInitialized( |
+ PolicyDomain domain) { |
+ --domains_pending_initialization_; |
+ if (is_initialization_complete()) |
+ CheckIfPolicyChanged(policy_service_->GetAllPolicies()); |
+} |
+ |
+void PolicyServiceChangeWatcher::Init() { |
+ for (size_t i = 0; i < POLICY_DOMAIN_SIZE; ++i) { |
+ PolicyDomain domain = static_cast<PolicyDomain>(i); |
+ policy_service_->AddObserver(domain, this); |
+ if (!policy_service_->IsInitializationComplete(domain)) |
+ ++domains_pending_initialization_; |
+ } |
+ if (is_initialization_complete()) |
+ CheckIfPolicyChanged(policy_service_->GetAllPolicies()); |
+} |
+ |
+void PolicyServiceChangeWatcher::CheckIfPolicyChanged( |
+ const PolicyBundle& bundle) { |
+ scoped_ptr<base::DictionaryValue> policy(new base::DictionaryValue); |
+ for (PolicyBundle::const_iterator bundle_it = bundle.begin(); |
+ bundle_it != bundle.end(); ++bundle_it) { |
+ if (bundle_it->second->empty()) |
+ continue; |
+ |
+ base::DictionaryValue* map = new base::DictionaryValue; |
+ for (PolicyMap::const_iterator map_it = bundle_it->second->begin(); |
+ map_it != bundle_it->second->end(); ++map_it) { |
+ base::DictionaryValue* entry = new base::DictionaryValue; |
+ entry->SetInteger("level", map_it->second.level); |
+ entry->SetInteger("scope", map_it->second.scope); |
+ entry->Set("value", map_it->second.value->DeepCopy()); |
+ map->Set(map_it->first, entry); |
+ } |
+ const PolicyNamespace& ns = bundle_it->first; |
+ policy->Set(base::IntToString(ns.domain) + ":" + ns.component_id, map); |
+ } |
+ |
+ std::string json; |
+ base::JSONWriter::Write(policy.get(), &json); |
+ char hash[crypto::kSHA256Length]; |
+ crypto::SHA256HashString(json, &hash, sizeof(hash)); |
+ const std::string new_hash = base::HexEncode(&hash, sizeof(hash)); |
+ |
+ if (new_hash != current_hash_) { |
+ current_hash_ = new_hash; |
+ OnPolicyChanged(); |
+ } |
+} |
+ |
+DevicePolicyChangeWatcher::Observer::~Observer() { |
+} |
+ |
+DevicePolicyChangeWatcher::DevicePolicyChangeWatcher() |
+ : PolicyServiceChangeWatcher(g_browser_process->policy_service(), "") { |
+ Init(); |
+ LOG(ERROR) << "*** DevicePolicyChangeWatcher UP"; |
+} |
+ |
+DevicePolicyChangeWatcher::~DevicePolicyChangeWatcher() { |
+ LOG(ERROR) << "*** DevicePolicyChangeWatcher DOWN"; |
+} |
+ |
+void DevicePolicyChangeWatcher::AddObserver(Observer* observer) { |
+ observers_.AddObserver(observer); |
+ if (is_initialization_complete()) |
+ observer->OnDevicePolicyStatusChanged(ListUsersWithChangedDevicePolicy()); |
+} |
+ |
+void DevicePolicyChangeWatcher::RemoveObserver(Observer* observer) { |
+ observers_.RemoveObserver(observer); |
+} |
+ |
+// static |
+void DevicePolicyChangeWatcher::RegisterPrefs(PrefRegistrySimple* registry) { |
+ registry->RegisterDictionaryPref(prefs::kDevicePolicyHashes); |
+} |
+ |
+void DevicePolicyChangeWatcher::AcknowledgePolicyChange( |
+ const std::string& username) { |
+ if (!is_initialization_complete()) |
+ return; |
+ |
+ DictionaryPrefUpdate pref_update(g_browser_process->local_state(), |
+ prefs::kDevicePolicyHashes); |
+ pref_update->SetWithoutPathExpansion( |
+ username, |
+ base::Value::CreateStringValue(current_hash())); |
+ |
+ NotifyDevicePolicyStatusChanged(); |
+} |
+ |
+std::vector<std::string> |
+ DevicePolicyChangeWatcher::ListUsersWithChangedDevicePolicy() const { |
+ DCHECK(is_initialization_complete()); |
+ std::vector<std::string> users_with_changed_device_policy; |
+ for (base::DictionaryValue::Iterator it( |
+ *g_browser_process->local_state()->GetDictionary( |
+ prefs::kDevicePolicyHashes)); |
+ !it.IsAtEnd(); it.Advance()) { |
+ std::string previous_hash; |
+ if (!it.value().GetAsString(&previous_hash) || |
+ previous_hash != current_hash()) { |
+ users_with_changed_device_policy.push_back(it.key()); |
+ } |
+ } |
+ return users_with_changed_device_policy; |
+} |
+ |
+void DevicePolicyChangeWatcher::NotifyDevicePolicyStatusChanged() { |
+ std::vector<std::string> users_with_changed_device_policy = |
+ ListUsersWithChangedDevicePolicy(); |
+ FOR_EACH_OBSERVER( |
+ Observer, |
+ observers_, |
+ OnDevicePolicyStatusChanged(users_with_changed_device_policy)); |
+} |
+ |
+void DevicePolicyChangeWatcher::OnPolicyChanged() { |
+ NotifyDevicePolicyStatusChanged(); |
+} |
+ |
+UserPolicyChangeWatcher::UserPolicyChangeWatcher(Profile* profile) |
+ : PolicyServiceChangeWatcher( |
+ profile->GetPolicyService(), |
+ profile->GetPrefs()->GetString(prefs::kUserPolicyHash)) { |
+ Init(); |
+} |
+ |
+UserPolicyChangeWatcher::~UserPolicyChangeWatcher() { |
+} |
+ |
+// static |
+void UserPolicyChangeWatcher::RegisterUserPrefs( |
+ PrefRegistrySyncable* registry) { |
+ registry->RegisterStringPref(prefs::kUserPolicyHash, |
+ std::string(), |
+ PrefRegistrySyncable::UNSYNCABLE_PREF); |
+} |
+ |
+void UserPolicyChangeWatcher::OnPolicyChanged() { |
+ LOG(ERROR) << "New user policy: " << current_hash(); |
+} |
+ |
+ |
+} // namespace policy |