Enable Enhanced Bookmark on Android Tablet
[chromium-blink-merge.git] / remoting / host / policy_hack / policy_watcher.cc
blobd0f59572c31ed2480d409bea355a8b5e68d89515
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.
5 // Most of this code is copied from:
6 // src/chrome/browser/policy/asynchronous_policy_loader.{h,cc}
8 #include "remoting/host/policy_hack/policy_watcher.h"
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/time/time.h"
16 #include "base/values.h"
17 #include "remoting/host/dns_blackhole_checker.h"
19 #if !defined(NDEBUG)
20 #include "base/json/json_reader.h"
21 #endif
23 namespace remoting {
24 namespace policy_hack {
26 namespace {
28 // The time interval for rechecking policy. This is our fallback in case the
29 // delegate never reports a change to the ReloadObserver.
30 const int kFallbackReloadDelayMinutes = 15;
32 // Copies all policy values from one dictionary to another, using values from
33 // |default| if they are not set in |from|, or values from |bad_type_values| if
34 // the value in |from| has the wrong type.
35 scoped_ptr<base::DictionaryValue> CopyGoodValuesAndAddDefaults(
36 const base::DictionaryValue* from,
37 const base::DictionaryValue* default_values,
38 const base::DictionaryValue* bad_type_values) {
39 scoped_ptr<base::DictionaryValue> to(default_values->DeepCopy());
40 for (base::DictionaryValue::Iterator i(*default_values);
41 !i.IsAtEnd(); i.Advance()) {
43 const base::Value* value = NULL;
45 // If the policy isn't in |from|, use the default.
46 if (!from->Get(i.key(), &value)) {
47 continue;
50 // If the policy is the wrong type, use the value from |bad_type_values|.
51 if (!value->IsType(i.value().GetType())) {
52 CHECK(bad_type_values->Get(i.key(), &value));
55 to->Set(i.key(), value->DeepCopy());
58 #if !defined(NDEBUG)
59 // Replace values with those specified in DebugOverridePolicies, if present.
60 std::string policy_overrides;
61 if (from->GetString(PolicyWatcher::kHostDebugOverridePoliciesName,
62 &policy_overrides)) {
63 scoped_ptr<base::Value> value(base::JSONReader::Read(policy_overrides));
64 const base::DictionaryValue* override_values;
65 if (value && value->GetAsDictionary(&override_values)) {
66 to->MergeDictionary(override_values);
69 #endif // defined(NDEBUG)
71 return to.Pass();
74 } // namespace
76 const char PolicyWatcher::kNatPolicyName[] =
77 "RemoteAccessHostFirewallTraversal";
79 const char PolicyWatcher::kHostRequireTwoFactorPolicyName[] =
80 "RemoteAccessHostRequireTwoFactor";
82 const char PolicyWatcher::kHostDomainPolicyName[] =
83 "RemoteAccessHostDomain";
85 const char PolicyWatcher::kHostMatchUsernamePolicyName[] =
86 "RemoteAccessHostMatchUsername";
88 const char PolicyWatcher::kHostTalkGadgetPrefixPolicyName[] =
89 "RemoteAccessHostTalkGadgetPrefix";
91 const char PolicyWatcher::kHostRequireCurtainPolicyName[] =
92 "RemoteAccessHostRequireCurtain";
94 const char PolicyWatcher::kHostTokenUrlPolicyName[] =
95 "RemoteAccessHostTokenUrl";
97 const char PolicyWatcher::kHostTokenValidationUrlPolicyName[] =
98 "RemoteAccessHostTokenValidationUrl";
100 const char PolicyWatcher::kHostTokenValidationCertIssuerPolicyName[] =
101 "RemoteAccessHostTokenValidationCertificateIssuer";
103 const char PolicyWatcher::kHostAllowClientPairing[] =
104 "RemoteAccessHostAllowClientPairing";
106 const char PolicyWatcher::kHostAllowGnubbyAuthPolicyName[] =
107 "RemoteAccessHostAllowGnubbyAuth";
109 const char PolicyWatcher::kRelayPolicyName[] =
110 "RemoteAccessHostAllowRelayedConnection";
112 const char PolicyWatcher::kUdpPortRangePolicyName[] =
113 "RemoteAccessHostUdpPortRange";
115 const char PolicyWatcher::kHostDebugOverridePoliciesName[] =
116 "RemoteAccessHostDebugOverridePolicies";
118 PolicyWatcher::PolicyWatcher(
119 scoped_refptr<base::SingleThreadTaskRunner> task_runner)
120 : task_runner_(task_runner),
121 transient_policy_error_retry_counter_(0),
122 old_policies_(new base::DictionaryValue()),
123 default_values_(new base::DictionaryValue()),
124 weak_factory_(this) {
125 // Initialize the default values for each policy.
126 default_values_->SetBoolean(kNatPolicyName, true);
127 default_values_->SetBoolean(kHostRequireTwoFactorPolicyName, false);
128 default_values_->SetBoolean(kHostRequireCurtainPolicyName, false);
129 default_values_->SetBoolean(kHostMatchUsernamePolicyName, false);
130 default_values_->SetString(kHostDomainPolicyName, std::string());
131 default_values_->SetString(kHostTalkGadgetPrefixPolicyName,
132 kDefaultHostTalkGadgetPrefix);
133 default_values_->SetString(kHostTokenUrlPolicyName, std::string());
134 default_values_->SetString(kHostTokenValidationUrlPolicyName, std::string());
135 default_values_->SetString(kHostTokenValidationCertIssuerPolicyName,
136 std::string());
137 default_values_->SetBoolean(kHostAllowClientPairing, true);
138 default_values_->SetBoolean(kHostAllowGnubbyAuthPolicyName, true);
139 default_values_->SetBoolean(kRelayPolicyName, true);
140 default_values_->SetString(kUdpPortRangePolicyName, "");
141 #if !defined(NDEBUG)
142 default_values_->SetString(kHostDebugOverridePoliciesName, std::string());
143 #endif
145 // Initialize the fall-back values to use for unreadable policies.
146 // For most policies these match the defaults.
147 bad_type_values_.reset(default_values_->DeepCopy());
148 bad_type_values_->SetBoolean(kNatPolicyName, false);
149 bad_type_values_->SetBoolean(kRelayPolicyName, false);
152 PolicyWatcher::~PolicyWatcher() {
155 void PolicyWatcher::StartWatching(
156 const PolicyUpdatedCallback& policy_updated_callback,
157 const PolicyErrorCallback& policy_error_callback) {
158 if (!OnPolicyWatcherThread()) {
159 task_runner_->PostTask(FROM_HERE,
160 base::Bind(&PolicyWatcher::StartWatching,
161 base::Unretained(this),
162 policy_updated_callback,
163 policy_error_callback));
164 return;
167 policy_updated_callback_ = policy_updated_callback;
168 policy_error_callback_ = policy_error_callback;
169 StartWatchingInternal();
172 void PolicyWatcher::StopWatching(const base::Closure& stopped_callback) {
173 task_runner_->PostTaskAndReply(
174 FROM_HERE, base::Bind(&PolicyWatcher::StopWatchingOnPolicyWatcherThread,
175 base::Unretained(this)),
176 stopped_callback);
179 void PolicyWatcher::StopWatchingOnPolicyWatcherThread() {
180 StopWatchingInternal();
181 weak_factory_.InvalidateWeakPtrs();
182 policy_updated_callback_.Reset();
183 policy_error_callback_.Reset();
186 void PolicyWatcher::ScheduleFallbackReloadTask() {
187 DCHECK(OnPolicyWatcherThread());
188 ScheduleReloadTask(
189 base::TimeDelta::FromMinutes(kFallbackReloadDelayMinutes));
192 void PolicyWatcher::ScheduleReloadTask(const base::TimeDelta& delay) {
193 DCHECK(OnPolicyWatcherThread());
194 task_runner_->PostDelayedTask(
195 FROM_HERE,
196 base::Bind(&PolicyWatcher::Reload, weak_factory_.GetWeakPtr()),
197 delay);
200 const base::DictionaryValue& PolicyWatcher::Defaults() const {
201 return *default_values_;
204 bool PolicyWatcher::OnPolicyWatcherThread() const {
205 return task_runner_->BelongsToCurrentThread();
208 void PolicyWatcher::UpdatePolicies(
209 const base::DictionaryValue* new_policies_raw) {
210 DCHECK(OnPolicyWatcherThread());
212 transient_policy_error_retry_counter_ = 0;
214 // Use default values for any missing policies.
215 scoped_ptr<base::DictionaryValue> new_policies =
216 CopyGoodValuesAndAddDefaults(
217 new_policies_raw, default_values_.get(), bad_type_values_.get());
219 // Find the changed policies.
220 scoped_ptr<base::DictionaryValue> changed_policies(
221 new base::DictionaryValue());
222 base::DictionaryValue::Iterator iter(*new_policies);
223 while (!iter.IsAtEnd()) {
224 base::Value* old_policy;
225 if (!(old_policies_->Get(iter.key(), &old_policy) &&
226 old_policy->Equals(&iter.value()))) {
227 changed_policies->Set(iter.key(), iter.value().DeepCopy());
229 iter.Advance();
232 // Save the new policies.
233 old_policies_.swap(new_policies);
235 // Notify our client of the changed policies.
236 if (!changed_policies->empty()) {
237 policy_updated_callback_.Run(changed_policies.Pass());
241 void PolicyWatcher::SignalPolicyError() {
242 transient_policy_error_retry_counter_ = 0;
243 policy_error_callback_.Run();
246 void PolicyWatcher::SignalTransientPolicyError() {
247 const int kMaxRetryCount = 5;
248 transient_policy_error_retry_counter_ += 1;
249 if (transient_policy_error_retry_counter_ >= kMaxRetryCount) {
250 SignalPolicyError();
254 } // namespace policy_hack
255 } // namespace remoting