| 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
|
|
|