Index: remoting/host/policy_hack/nat_policy.cc |
diff --git a/remoting/host/policy_hack/nat_policy.cc b/remoting/host/policy_hack/nat_policy.cc |
index 77f376a7da5da3704791cfc1eeb6629d4b8535ae..f6909da99110887fad5f59e1821a12b92d9bf7c2 100644 |
--- a/remoting/host/policy_hack/nat_policy.cc |
+++ b/remoting/host/policy_hack/nat_policy.cc |
@@ -24,87 +24,138 @@ namespace { |
// delegate never reports a change to the ReloadObserver. |
const int kFallbackReloadDelayMinutes = 15; |
+// Gets a boolean from a dictionary, or returns a default value if the boolean |
+// couldn't be read. |
+bool GetBooleanOrDefault(const base::DictionaryValue* dict, const char* key, |
+ bool default_if_value_missing, |
+ bool default_if_value_not_boolean) { |
+ if (!dict->HasKey(key)) { |
+ return default_if_value_missing; |
+ } |
+ base::Value* value; |
+ if (dict->Get(key, &value) && value->IsType(base::Value::TYPE_BOOLEAN)) { |
+ bool bool_value; |
+ CHECK(value->GetAsBoolean(&bool_value)); |
+ return bool_value; |
+ } |
+ return default_if_value_not_boolean; |
+} |
+ |
+// Copies a boolean from one dictionary to another, using a default value |
+// if the boolean couldn't be read from the first dictionary. |
+void CopyBooleanOrDefault(base::DictionaryValue* to, |
+ const base::DictionaryValue* from, const char* key, |
+ bool default_if_value_missing, |
+ bool default_if_value_not_boolean) { |
+ to->Set(key, base::Value::CreateBooleanValue( |
+ GetBooleanOrDefault(from, key, default_if_value_missing, |
+ default_if_value_not_boolean))); |
+} |
+ |
+// Copies all policy values from one dictionary to another, using default values |
+// when necessary. |
+scoped_ptr<base::DictionaryValue> AddDefaultValuesWhenNecessary( |
+ const base::DictionaryValue* from) { |
+ scoped_ptr<base::DictionaryValue> to(new base::DictionaryValue()); |
+ CopyBooleanOrDefault(to.get(), from, |
+ PolicyWatcher::kNatPolicyName, true, false); |
+ return to.Pass(); |
+} |
+ |
} // namespace |
-const char NatPolicy::kNatPolicyName[] = "RemoteAccessHostFirewallTraversal"; |
+const char PolicyWatcher::kNatPolicyName[] = |
+ "RemoteAccessHostFirewallTraversal"; |
+ |
+const char* const PolicyWatcher::kBooleanPolicyNames[] = |
garykac
2012/07/23 17:29:26
We'll have boolean, string and int policy types th
simonmorris
2012/07/23 19:34:55
The next CL will have a different policy type, so
|
+ { PolicyWatcher::kNatPolicyName }; |
-NatPolicy::NatPolicy(scoped_refptr<base::SingleThreadTaskRunner> task_runner) |
+const int PolicyWatcher::kBooleanPolicyNamesNum = |
+ arraysize(kBooleanPolicyNames); |
+ |
+PolicyWatcher::PolicyWatcher( |
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner) |
: task_runner_(task_runner), |
- current_nat_enabled_state_(false), |
- first_state_published_(false), |
+ old_policies_(new base::DictionaryValue()), |
ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) { |
} |
-NatPolicy::~NatPolicy() { |
+PolicyWatcher::~PolicyWatcher() { |
} |
-void NatPolicy::StartWatching(const NatEnabledCallback& nat_enabled_cb) { |
- if (!OnPolicyThread()) { |
+void PolicyWatcher::StartWatching(const PolicyCallback& policy_callback) { |
+ if (!OnPolicyWatcherThread()) { |
task_runner_->PostTask(FROM_HERE, |
- base::Bind(&NatPolicy::StartWatching, |
+ base::Bind(&PolicyWatcher::StartWatching, |
base::Unretained(this), |
- nat_enabled_cb)); |
+ policy_callback)); |
return; |
} |
- nat_enabled_cb_ = nat_enabled_cb; |
+ policy_callback_ = policy_callback; |
StartWatchingInternal(); |
} |
-void NatPolicy::StopWatching(base::WaitableEvent* done) { |
- if (!OnPolicyThread()) { |
+void PolicyWatcher::StopWatching(base::WaitableEvent* done) { |
+ if (!OnPolicyWatcherThread()) { |
task_runner_->PostTask(FROM_HERE, |
- base::Bind(&NatPolicy::StopWatching, |
+ base::Bind(&PolicyWatcher::StopWatching, |
base::Unretained(this), done)); |
return; |
} |
StopWatchingInternal(); |
weak_factory_.InvalidateWeakPtrs(); |
- nat_enabled_cb_.Reset(); |
+ policy_callback_.Reset(); |
done->Signal(); |
} |
-void NatPolicy::ScheduleFallbackReloadTask() { |
- DCHECK(OnPolicyThread()); |
+void PolicyWatcher::ScheduleFallbackReloadTask() { |
+ DCHECK(OnPolicyWatcherThread()); |
ScheduleReloadTask( |
base::TimeDelta::FromMinutes(kFallbackReloadDelayMinutes)); |
} |
-void NatPolicy::ScheduleReloadTask(const base::TimeDelta& delay) { |
- DCHECK(OnPolicyThread()); |
+void PolicyWatcher::ScheduleReloadTask(const base::TimeDelta& delay) { |
+ DCHECK(OnPolicyWatcherThread()); |
task_runner_->PostDelayedTask( |
FROM_HERE, |
- base::Bind(&NatPolicy::Reload, weak_factory_.GetWeakPtr()), |
+ base::Bind(&PolicyWatcher::Reload, weak_factory_.GetWeakPtr()), |
delay); |
} |
-bool NatPolicy::OnPolicyThread() const { |
+bool PolicyWatcher::OnPolicyWatcherThread() const { |
return task_runner_->BelongsToCurrentThread(); |
} |
-void NatPolicy::UpdateNatPolicy(base::DictionaryValue* new_policy) { |
- DCHECK(OnPolicyThread()); |
- bool new_nat_enabled_state = false; |
- if (!new_policy->HasKey(kNatPolicyName)) { |
- // If unspecified, the default value of this policy is true. |
- new_nat_enabled_state = true; |
- } else { |
- // Otherwise, try to parse the value and only change from false if we get |
- // a successful read. |
- base::Value* value; |
- if (new_policy->Get(kNatPolicyName, &value) && |
- value->IsType(base::Value::TYPE_BOOLEAN)) { |
- CHECK(value->GetAsBoolean(&new_nat_enabled_state)); |
+void PolicyWatcher::UpdatePolicies( |
+ const base::DictionaryValue* new_policies_raw) { |
+ DCHECK(OnPolicyWatcherThread()); |
+ |
+ // Use default values for any missing policies. |
+ scoped_ptr<base::DictionaryValue> new_policies = |
+ AddDefaultValuesWhenNecessary(new_policies_raw); |
+ |
+ // Find the changed policies. |
+ scoped_ptr<base::DictionaryValue> changed_policies( |
+ new base::DictionaryValue()); |
+ base::DictionaryValue::Iterator iter(*new_policies); |
+ while (iter.HasNext()) { |
+ base::Value* old_policy; |
+ if (!(old_policies_->Get(iter.key(), &old_policy) && |
+ old_policy->Equals(&iter.value()))) { |
+ changed_policies->Set(iter.key(), iter.value().DeepCopy()); |
} |
+ iter.Advance(); |
} |
- if (!first_state_published_ || |
- (new_nat_enabled_state != current_nat_enabled_state_)) { |
- first_state_published_ = true; |
- current_nat_enabled_state_ = new_nat_enabled_state; |
- nat_enabled_cb_.Run(current_nat_enabled_state_); |
+ // Save the new policies. |
+ old_policies_.swap(new_policies); |
+ |
+ // Notify our client of the changed policies. |
+ if (!changed_policies->empty()) { |
+ policy_callback_.Run(changed_policies.Pass()); |
} |
} |