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/synchronization/waitable_event.h"
16 #include "base/time/time.h"
17 #include "base/values.h"
18 #include "remoting/host/dns_blackhole_checker.h"
21 #include "base/json/json_reader.h"
25 namespace policy_hack
{
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;
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()) {
44 const base::Value
* value
= NULL
;
46 // If the policy isn't in |from|, use the default.
47 if (!from
->Get(i
.key(), &value
)) {
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
));
56 to
->Set(i
.key(), value
->DeepCopy());
60 // Replace values with those specified in DebugOverridePolicies, if present.
61 std::string policy_overrides
;
62 if (from
->GetString(PolicyWatcher::kHostDebugOverridePoliciesName
,
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
);
70 #endif // defined(NDEBUG)
77 const char PolicyWatcher::kNatPolicyName
[] =
78 "RemoteAccessHostFirewallTraversal";
80 const char PolicyWatcher::kHostRequireTwoFactorPolicyName
[] =
81 "RemoteAccessHostRequireTwoFactor";
83 const char PolicyWatcher::kHostDomainPolicyName
[] =
84 "RemoteAccessHostDomain";
86 const char PolicyWatcher::kHostMatchUsernamePolicyName
[] =
87 "RemoteAccessHostMatchUsername";
89 const char PolicyWatcher::kHostTalkGadgetPrefixPolicyName
[] =
90 "RemoteAccessHostTalkGadgetPrefix";
92 const char PolicyWatcher::kHostRequireCurtainPolicyName
[] =
93 "RemoteAccessHostRequireCurtain";
95 const char PolicyWatcher::kHostTokenUrlPolicyName
[] =
96 "RemoteAccessHostTokenUrl";
98 const char PolicyWatcher::kHostTokenValidationUrlPolicyName
[] =
99 "RemoteAccessHostTokenValidationUrl";
101 const char PolicyWatcher::kHostTokenValidationCertIssuerPolicyName
[] =
102 "RemoteAccessHostTokenValidationCertificateIssuer";
104 const char PolicyWatcher::kHostAllowClientPairing
[] =
105 "RemoteAccessHostAllowClientPairing";
107 const char PolicyWatcher::kHostAllowGnubbyAuthPolicyName
[] =
108 "RemoteAccessHostAllowGnubbyAuth";
110 const char PolicyWatcher::kRelayPolicyName
[] =
111 "RemoteAccessHostAllowRelayedConnection";
113 const char PolicyWatcher::kUdpPortRangePolicyName
[] =
114 "RemoteAccessHostUdpPortRange";
116 const char PolicyWatcher::kHostDebugOverridePoliciesName
[] =
117 "RemoteAccessHostDebugOverridePolicies";
119 PolicyWatcher::PolicyWatcher(
120 scoped_refptr
<base::SingleThreadTaskRunner
> task_runner
)
121 : task_runner_(task_runner
),
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
,
137 default_values_
->SetBoolean(kHostAllowClientPairing
, true);
138 default_values_
->SetBoolean(kHostAllowGnubbyAuthPolicyName
, true);
139 default_values_
->SetBoolean(kRelayPolicyName
, true);
140 default_values_
->SetString(kUdpPortRangePolicyName
, "");
142 default_values_
->SetString(kHostDebugOverridePoliciesName
, std::string());
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(const PolicyCallback
& policy_callback
) {
156 if (!OnPolicyWatcherThread()) {
157 task_runner_
->PostTask(FROM_HERE
,
158 base::Bind(&PolicyWatcher::StartWatching
,
159 base::Unretained(this),
164 policy_callback_
= policy_callback
;
165 StartWatchingInternal();
168 void PolicyWatcher::StopWatching(base::WaitableEvent
* done
) {
169 if (!OnPolicyWatcherThread()) {
170 task_runner_
->PostTask(FROM_HERE
,
171 base::Bind(&PolicyWatcher::StopWatching
,
172 base::Unretained(this), done
));
176 StopWatchingInternal();
177 weak_factory_
.InvalidateWeakPtrs();
178 policy_callback_
.Reset();
183 void PolicyWatcher::ScheduleFallbackReloadTask() {
184 DCHECK(OnPolicyWatcherThread());
186 base::TimeDelta::FromMinutes(kFallbackReloadDelayMinutes
));
189 void PolicyWatcher::ScheduleReloadTask(const base::TimeDelta
& delay
) {
190 DCHECK(OnPolicyWatcherThread());
191 task_runner_
->PostDelayedTask(
193 base::Bind(&PolicyWatcher::Reload
, weak_factory_
.GetWeakPtr()),
197 const base::DictionaryValue
& PolicyWatcher::Defaults() const {
198 return *default_values_
;
201 bool PolicyWatcher::OnPolicyWatcherThread() const {
202 return task_runner_
->BelongsToCurrentThread();
205 void PolicyWatcher::UpdatePolicies(
206 const base::DictionaryValue
* new_policies_raw
) {
207 DCHECK(OnPolicyWatcherThread());
209 // Use default values for any missing policies.
210 scoped_ptr
<base::DictionaryValue
> new_policies
=
211 CopyGoodValuesAndAddDefaults(
212 new_policies_raw
, default_values_
.get(), bad_type_values_
.get());
214 // Find the changed policies.
215 scoped_ptr
<base::DictionaryValue
> changed_policies(
216 new base::DictionaryValue());
217 base::DictionaryValue::Iterator
iter(*new_policies
);
218 while (!iter
.IsAtEnd()) {
219 base::Value
* old_policy
;
220 if (!(old_policies_
->Get(iter
.key(), &old_policy
) &&
221 old_policy
->Equals(&iter
.value()))) {
222 changed_policies
->Set(iter
.key(), iter
.value().DeepCopy());
227 // Save the new policies.
228 old_policies_
.swap(new_policies
);
230 // Notify our client of the changed policies.
231 if (!changed_policies
->empty()) {
232 policy_callback_
.Run(changed_policies
.Pass());
236 } // namespace policy_hack
237 } // namespace remoting