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/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 24 namespace remoting { 25 namespace policy_hack { 26 27 namespace { 28 29 // The time interval for rechecking policy. This is our fallback in case the 30 // delegate never reports a change to the ReloadObserver. 31 const 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. 36 scoped_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 77 const char PolicyWatcher::kNatPolicyName[] = 78 "RemoteAccessHostFirewallTraversal"; 79 80 const char PolicyWatcher::kHostRequireTwoFactorPolicyName[] = 81 "RemoteAccessHostRequireTwoFactor"; 82 83 const char PolicyWatcher::kHostDomainPolicyName[] = 84 "RemoteAccessHostDomain"; 85 86 const char PolicyWatcher::kHostMatchUsernamePolicyName[] = 87 "RemoteAccessHostMatchUsername"; 88 89 const char PolicyWatcher::kHostTalkGadgetPrefixPolicyName[] = 90 "RemoteAccessHostTalkGadgetPrefix"; 91 92 const char PolicyWatcher::kHostRequireCurtainPolicyName[] = 93 "RemoteAccessHostRequireCurtain"; 94 95 const char PolicyWatcher::kHostTokenUrlPolicyName[] = 96 "RemoteAccessHostTokenUrl"; 97 98 const char PolicyWatcher::kHostTokenValidationUrlPolicyName[] = 99 "RemoteAccessHostTokenValidationUrl"; 100 101 const char PolicyWatcher::kHostAllowClientPairing[] = 102 "RemoteAccessHostAllowClientPairing"; 103 104 const char PolicyWatcher::kHostDebugOverridePoliciesName[] = 105 "RemoteAccessHostDebugOverridePolicies"; 106 107 PolicyWatcher::PolicyWatcher( 108 scoped_refptr<base::SingleThreadTaskRunner> task_runner) 109 : task_runner_(task_runner), 110 old_policies_(new base::DictionaryValue()), 111 default_values_(new base::DictionaryValue()), 112 weak_factory_(this) { 113 // Initialize the default values for each policy. 114 default_values_->SetBoolean(kNatPolicyName, true); 115 default_values_->SetBoolean(kHostRequireTwoFactorPolicyName, false); 116 default_values_->SetBoolean(kHostRequireCurtainPolicyName, false); 117 default_values_->SetBoolean(kHostMatchUsernamePolicyName, false); 118 default_values_->SetString(kHostDomainPolicyName, std::string()); 119 default_values_->SetString(kHostTalkGadgetPrefixPolicyName, 120 kDefaultHostTalkGadgetPrefix); 121 default_values_->SetString(kHostTokenUrlPolicyName, std::string()); 122 default_values_->SetString(kHostTokenValidationUrlPolicyName, std::string()); 123 default_values_->SetBoolean(kHostAllowClientPairing, true); 124 #if !defined(NDEBUG) 125 default_values_->SetString(kHostDebugOverridePoliciesName, std::string()); 126 #endif 127 128 // Initialize the fall-back values to use for unreadable policies. 129 // For most policies these match the defaults. 130 bad_type_values_.reset(default_values_->DeepCopy()); 131 bad_type_values_->SetBoolean(kNatPolicyName, false); 132 } 133 134 PolicyWatcher::~PolicyWatcher() { 135 } 136 137 void PolicyWatcher::StartWatching(const PolicyCallback& policy_callback) { 138 if (!OnPolicyWatcherThread()) { 139 task_runner_->PostTask(FROM_HERE, 140 base::Bind(&PolicyWatcher::StartWatching, 141 base::Unretained(this), 142 policy_callback)); 143 return; 144 } 145 146 policy_callback_ = policy_callback; 147 StartWatchingInternal(); 148 } 149 150 void PolicyWatcher::StopWatching(base::WaitableEvent* done) { 151 if (!OnPolicyWatcherThread()) { 152 task_runner_->PostTask(FROM_HERE, 153 base::Bind(&PolicyWatcher::StopWatching, 154 base::Unretained(this), done)); 155 return; 156 } 157 158 StopWatchingInternal(); 159 weak_factory_.InvalidateWeakPtrs(); 160 policy_callback_.Reset(); 161 162 done->Signal(); 163 } 164 165 void PolicyWatcher::ScheduleFallbackReloadTask() { 166 DCHECK(OnPolicyWatcherThread()); 167 ScheduleReloadTask( 168 base::TimeDelta::FromMinutes(kFallbackReloadDelayMinutes)); 169 } 170 171 void PolicyWatcher::ScheduleReloadTask(const base::TimeDelta& delay) { 172 DCHECK(OnPolicyWatcherThread()); 173 task_runner_->PostDelayedTask( 174 FROM_HERE, 175 base::Bind(&PolicyWatcher::Reload, weak_factory_.GetWeakPtr()), 176 delay); 177 } 178 179 const base::DictionaryValue& PolicyWatcher::Defaults() const { 180 return *default_values_; 181 } 182 183 bool PolicyWatcher::OnPolicyWatcherThread() const { 184 return task_runner_->BelongsToCurrentThread(); 185 } 186 187 void PolicyWatcher::UpdatePolicies( 188 const base::DictionaryValue* new_policies_raw) { 189 DCHECK(OnPolicyWatcherThread()); 190 191 // Use default values for any missing policies. 192 scoped_ptr<base::DictionaryValue> new_policies = 193 CopyGoodValuesAndAddDefaults( 194 new_policies_raw, default_values_.get(), bad_type_values_.get()); 195 196 // Find the changed policies. 197 scoped_ptr<base::DictionaryValue> changed_policies( 198 new base::DictionaryValue()); 199 base::DictionaryValue::Iterator iter(*new_policies); 200 while (!iter.IsAtEnd()) { 201 base::Value* old_policy; 202 if (!(old_policies_->Get(iter.key(), &old_policy) && 203 old_policy->Equals(&iter.value()))) { 204 changed_policies->Set(iter.key(), iter.value().DeepCopy()); 205 } 206 iter.Advance(); 207 } 208 209 // Save the new policies. 210 old_policies_.swap(new_policies); 211 212 // Notify our client of the changed policies. 213 if (!changed_policies->empty()) { 214 policy_callback_.Run(changed_policies.Pass()); 215 } 216 } 217 218 } // namespace policy_hack 219 } // namespace remoting 220