policy_watcher.cc revision c2e0dbddbe15c98d52c4786dac06cb8952a8ae6d
1// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5// Most of this code is copied from: 6// src/chrome/browser/policy/asynchronous_policy_loader.{h,cc} 7 8#include "remoting/host/policy_hack/policy_watcher.h" 9 10#include "base/bind.h" 11#include "base/compiler_specific.h" 12#include "base/location.h" 13#include "base/memory/weak_ptr.h" 14#include "base/single_thread_task_runner.h" 15#include "base/synchronization/waitable_event.h" 16#include "base/time.h" 17#include "base/values.h" 18#include "remoting/host/dns_blackhole_checker.h" 19 20#if !defined(NDEBUG) 21#include "base/json/json_reader.h" 22#endif 23 24namespace remoting { 25namespace policy_hack { 26 27namespace { 28 29// The time interval for rechecking policy. This is our fallback in case the 30// delegate never reports a change to the ReloadObserver. 31const int kFallbackReloadDelayMinutes = 15; 32 33// Copies all policy values from one dictionary to another, using values from 34// |default| if they are not set in |from|, or values from |bad_type_values| if 35// the value in |from| has the wrong type. 36scoped_ptr<base::DictionaryValue> CopyGoodValuesAndAddDefaults( 37 const base::DictionaryValue* from, 38 const base::DictionaryValue* default_values, 39 const base::DictionaryValue* bad_type_values) { 40 scoped_ptr<base::DictionaryValue> to(default_values->DeepCopy()); 41 for (base::DictionaryValue::Iterator i(*default_values); 42 !i.IsAtEnd(); i.Advance()) { 43 44 const base::Value* value = NULL; 45 46 // If the policy isn't in |from|, use the default. 47 if (!from->Get(i.key(), &value)) { 48 continue; 49 } 50 51 // If the policy is the wrong type, use the value from |bad_type_values|. 52 if (!value->IsType(i.value().GetType())) { 53 CHECK(bad_type_values->Get(i.key(), &value)); 54 } 55 56 to->Set(i.key(), value->DeepCopy()); 57 } 58 59#if !defined(NDEBUG) 60 // Replace values with those specified in DebugOverridePolicies, if present. 61 std::string policy_overrides; 62 if (from->GetString(PolicyWatcher::kHostDebugOverridePoliciesName, 63 &policy_overrides)) { 64 scoped_ptr<base::Value> value(base::JSONReader::Read(policy_overrides)); 65 const base::DictionaryValue* override_values; 66 if (value && value->GetAsDictionary(&override_values)) { 67 to->MergeDictionary(override_values); 68 } 69 } 70#endif // defined(NDEBUG) 71 72 return to.Pass(); 73} 74 75} // namespace 76 77const char PolicyWatcher::kNatPolicyName[] = 78 "RemoteAccessHostFirewallTraversal"; 79 80const char PolicyWatcher::kHostRequireTwoFactorPolicyName[] = 81 "RemoteAccessHostRequireTwoFactor"; 82 83const char PolicyWatcher::kHostDomainPolicyName[] = 84 "RemoteAccessHostDomain"; 85 86const char PolicyWatcher::kHostMatchUsernamePolicyName[] = 87 "RemoteAccessHostMatchUsername"; 88 89const char PolicyWatcher::kHostTalkGadgetPrefixPolicyName[] = 90 "RemoteAccessHostTalkGadgetPrefix"; 91 92const char PolicyWatcher::kHostRequireCurtainPolicyName[] = 93 "RemoteAccessHostRequireCurtain"; 94 95const char PolicyWatcher::kHostTokenUrlPolicyName[] = 96 "RemoteAccessHostTokenUrl"; 97 98const char PolicyWatcher::kHostTokenValidationUrlPolicyName[] = 99 "RemoteAccessHostTokenValidationUrl"; 100 101const char PolicyWatcher::kHostDebugOverridePoliciesName[] = 102 "RemoteAccessHostDebugOverridePolicies"; 103 104PolicyWatcher::PolicyWatcher( 105 scoped_refptr<base::SingleThreadTaskRunner> task_runner) 106 : task_runner_(task_runner), 107 old_policies_(new base::DictionaryValue()), 108 default_values_(new base::DictionaryValue()), 109 weak_factory_(this) { 110 // Initialize the default values for each policy. 111 default_values_->SetBoolean(kNatPolicyName, true); 112 default_values_->SetBoolean(kHostRequireTwoFactorPolicyName, false); 113 default_values_->SetBoolean(kHostRequireCurtainPolicyName, false); 114 default_values_->SetBoolean(kHostMatchUsernamePolicyName, false); 115 default_values_->SetString(kHostDomainPolicyName, std::string()); 116 default_values_->SetString(kHostTalkGadgetPrefixPolicyName, 117 kDefaultHostTalkGadgetPrefix); 118 default_values_->SetString(kHostTokenUrlPolicyName, std::string()); 119 default_values_->SetString(kHostTokenValidationUrlPolicyName, std::string()); 120#if !defined(NDEBUG) 121 default_values_->SetString(kHostDebugOverridePoliciesName, std::string()); 122#endif 123 124 // Initialize the fall-back values to use for unreadable policies. 125 // For most policies these match the defaults. 126 bad_type_values_.reset(default_values_->DeepCopy()); 127 bad_type_values_->SetBoolean(kNatPolicyName, false); 128} 129 130PolicyWatcher::~PolicyWatcher() { 131} 132 133void PolicyWatcher::StartWatching(const PolicyCallback& policy_callback) { 134 if (!OnPolicyWatcherThread()) { 135 task_runner_->PostTask(FROM_HERE, 136 base::Bind(&PolicyWatcher::StartWatching, 137 base::Unretained(this), 138 policy_callback)); 139 return; 140 } 141 142 policy_callback_ = policy_callback; 143 StartWatchingInternal(); 144} 145 146void PolicyWatcher::StopWatching(base::WaitableEvent* done) { 147 if (!OnPolicyWatcherThread()) { 148 task_runner_->PostTask(FROM_HERE, 149 base::Bind(&PolicyWatcher::StopWatching, 150 base::Unretained(this), done)); 151 return; 152 } 153 154 StopWatchingInternal(); 155 weak_factory_.InvalidateWeakPtrs(); 156 policy_callback_.Reset(); 157 158 done->Signal(); 159} 160 161void PolicyWatcher::ScheduleFallbackReloadTask() { 162 DCHECK(OnPolicyWatcherThread()); 163 ScheduleReloadTask( 164 base::TimeDelta::FromMinutes(kFallbackReloadDelayMinutes)); 165} 166 167void PolicyWatcher::ScheduleReloadTask(const base::TimeDelta& delay) { 168 DCHECK(OnPolicyWatcherThread()); 169 task_runner_->PostDelayedTask( 170 FROM_HERE, 171 base::Bind(&PolicyWatcher::Reload, weak_factory_.GetWeakPtr()), 172 delay); 173} 174 175const base::DictionaryValue& PolicyWatcher::Defaults() const { 176 return *default_values_; 177} 178 179bool PolicyWatcher::OnPolicyWatcherThread() const { 180 return task_runner_->BelongsToCurrentThread(); 181} 182 183void PolicyWatcher::UpdatePolicies( 184 const base::DictionaryValue* new_policies_raw) { 185 DCHECK(OnPolicyWatcherThread()); 186 187 // Use default values for any missing policies. 188 scoped_ptr<base::DictionaryValue> new_policies = 189 CopyGoodValuesAndAddDefaults( 190 new_policies_raw, default_values_.get(), bad_type_values_.get()); 191 192 // Find the changed policies. 193 scoped_ptr<base::DictionaryValue> changed_policies( 194 new base::DictionaryValue()); 195 base::DictionaryValue::Iterator iter(*new_policies); 196 while (!iter.IsAtEnd()) { 197 base::Value* old_policy; 198 if (!(old_policies_->Get(iter.key(), &old_policy) && 199 old_policy->Equals(&iter.value()))) { 200 changed_policies->Set(iter.key(), iter.value().DeepCopy()); 201 } 202 iter.Advance(); 203 } 204 205 // Save the new policies. 206 old_policies_.swap(new_policies); 207 208 // Notify our client of the changed policies. 209 if (!changed_policies->empty()) { 210 policy_callback_.Run(changed_policies.Pass()); 211 } 212} 213 214} // namespace policy_hack 215} // namespace remoting 216