Index: remoting/host/policy_watcher.cc |
diff --git a/remoting/host/policy_watcher.cc b/remoting/host/policy_watcher.cc |
index 4026cdd008423f4d94385b5c9664e41e1fe9b444..2d16584c858967ae00a27e8bbb10a2e0a4544aaa 100644 |
--- a/remoting/host/policy_watcher.cc |
+++ b/remoting/host/policy_watcher.cc |
@@ -42,12 +42,10 @@ namespace key = ::policy::key; |
namespace { |
// Copies all policy values from one dictionary to another, using values from |
-// |default| if they are not set in |from|, or values from |bad_type_values| if |
-// the value in |from| has the wrong type. |
-scoped_ptr<base::DictionaryValue> CopyGoodValuesAndAddDefaults( |
+// |default_values| if they are not set in |from|. |
+scoped_ptr<base::DictionaryValue> CopyValuesAndAddDefaults( |
const base::DictionaryValue* from, |
- const base::DictionaryValue* default_values, |
- const base::DictionaryValue* bad_type_values) { |
+ const base::DictionaryValue* default_values) { |
scoped_ptr<base::DictionaryValue> to(default_values->DeepCopy()); |
for (base::DictionaryValue::Iterator i(*default_values); !i.IsAtEnd(); |
i.Advance()) { |
@@ -58,11 +56,7 @@ scoped_ptr<base::DictionaryValue> CopyGoodValuesAndAddDefaults( |
continue; |
} |
- // If the policy is the wrong type, use the value from |bad_type_values|. |
- if (!value->IsType(i.value().GetType())) { |
- CHECK(bad_type_values->Get(i.key(), &value)); |
- } |
- |
+ CHECK(value->IsType(i.value().GetType())); |
Sergey Ulanov
2015/02/12 19:22:58
Does this need to be a CHECK() instead of DCHECK()
Łukasz Anforowicz
2015/02/12 20:34:13
Good question. I was wondering about it myself.
|
to->Set(i.key(), value->DeepCopy()); |
} |
@@ -86,6 +80,18 @@ policy::PolicyNamespace GetPolicyNamespace() { |
return policy::PolicyNamespace(policy::POLICY_DOMAIN_CHROME, std::string()); |
} |
+scoped_ptr<policy::SchemaRegistry> CreateSchemaRegistry() { |
+ // TODO(lukasza): Schema below should ideally only cover Chromoting-specific |
+ // policies (expecting perf and maintanability improvement, but no functional |
+ // impact). |
+ policy::Schema schema = policy::Schema::Wrap(policy::GetChromeSchemaData()); |
+ |
+ scoped_ptr<policy::SchemaRegistry> schema_registry( |
+ new policy::SchemaRegistry()); |
+ schema_registry->RegisterComponent(GetPolicyNamespace(), schema); |
+ return schema_registry.Pass(); |
+} |
+ |
} // namespace |
void PolicyWatcher::StartWatching( |
@@ -112,11 +118,9 @@ void PolicyWatcher::UpdatePolicies( |
const base::DictionaryValue* new_policies_raw) { |
DCHECK(CalledOnValidThread()); |
- transient_policy_error_retry_counter_ = 0; |
- |
// Use default values for any missing policies. |
- scoped_ptr<base::DictionaryValue> new_policies = CopyGoodValuesAndAddDefaults( |
- new_policies_raw, default_values_.get(), bad_type_values_.get()); |
+ scoped_ptr<base::DictionaryValue> new_policies = |
+ CopyValuesAndAddDefaults(new_policies_raw, default_values_.get()); |
// Find the changed policies. |
scoped_ptr<base::DictionaryValue> changed_policies( |
@@ -141,30 +145,23 @@ void PolicyWatcher::UpdatePolicies( |
} |
void PolicyWatcher::SignalPolicyError() { |
- transient_policy_error_retry_counter_ = 0; |
policy_error_callback_.Run(); |
} |
-void PolicyWatcher::SignalTransientPolicyError() { |
- const int kMaxRetryCount = 5; |
- transient_policy_error_retry_counter_ += 1; |
- if (transient_policy_error_retry_counter_ >= kMaxRetryCount) { |
- SignalPolicyError(); |
- } |
-} |
- |
PolicyWatcher::PolicyWatcher( |
policy::PolicyService* policy_service, |
scoped_ptr<policy::PolicyService> owned_policy_service, |
scoped_ptr<policy::ConfigurationPolicyProvider> owned_policy_provider, |
scoped_ptr<policy::SchemaRegistry> owned_schema_registry) |
- : transient_policy_error_retry_counter_(0), |
- old_policies_(new base::DictionaryValue()), |
+ : old_policies_(new base::DictionaryValue()), |
default_values_(new base::DictionaryValue()), |
policy_service_(policy_service), |
owned_schema_registry_(owned_schema_registry.Pass()), |
owned_policy_provider_(owned_policy_provider.Pass()), |
owned_policy_service_(owned_policy_service.Pass()) { |
+ DCHECK(policy_service_); |
+ DCHECK(owned_schema_registry_); |
+ |
// Initialize the default values for each policy. |
default_values_->SetBoolean(key::kRemoteAccessHostFirewallTraversal, true); |
default_values_->SetBoolean(key::kRemoteAccessHostRequireCurtain, false); |
@@ -186,13 +183,6 @@ PolicyWatcher::PolicyWatcher( |
default_values_->SetString(key::kRemoteAccessHostDebugOverridePolicies, |
std::string()); |
#endif |
- |
- // Initialize the fall-back values to use for unreadable policies. |
- // For most policies these match the defaults. |
- bad_type_values_.reset(default_values_->DeepCopy()); |
- bad_type_values_->SetBoolean(key::kRemoteAccessHostFirewallTraversal, false); |
- bad_type_values_->SetBoolean(key::kRemoteAccessHostAllowRelayedConnection, |
- false); |
} |
PolicyWatcher::~PolicyWatcher() { |
@@ -206,15 +196,56 @@ PolicyWatcher::~PolicyWatcher() { |
} |
} |
+const policy::Schema* PolicyWatcher::GetPolicySchema() const { |
+ policy::PolicyNamespace ns = GetPolicyNamespace(); |
+ |
+ const scoped_refptr<policy::SchemaMap>& schema_map = |
+ owned_schema_registry_->schema_map(); |
+ const policy::Schema* schema = schema_map->GetSchema(ns); |
Sergey Ulanov
2015/02/12 19:22:59
nit: You can write this whole function in one line
Łukasz Anforowicz
2015/02/12 20:34:13
Thanks. I don't know why I did it this way...
|
+ |
+ return schema; |
+} |
+ |
void PolicyWatcher::OnPolicyUpdated(const policy::PolicyNamespace& ns, |
const policy::PolicyMap& previous, |
const policy::PolicyMap& current) { |
+ const std::string policy_name_prefix = "RemoteAccessHost"; |
Sergey Ulanov
2015/02/12 19:22:59
This doesn't need to be std::string. Style guide a
Łukasz Anforowicz
2015/02/12 20:34:13
Done.
BTW: I initially started replying that your
|
scoped_ptr<base::DictionaryValue> policy_dict(new base::DictionaryValue()); |
for (auto it = current.begin(); it != current.end(); ++it) { |
- // TODO(lukasza): Use policy::Schema::Normalize() for schema verification. |
- policy_dict->Set(it->first, it->second.value->DeepCopy()); |
+ const std::string& key = it->first; |
+ const base::Value* value = it->second.value; |
+ |
+ // Copying only Chromoting-specific policies helps avoid false alarms |
+ // raised by Schema::Normalize below (such alarms shutdown the host). |
+ // TODO(lukasza): Removing this somewhat brittle filtering will be possible |
+ // after having separate, Chromoting-specific schema. |
+ if (key.find(policy_name_prefix) != std::string::npos) { |
+ policy_dict->Set(key, value->DeepCopy()); |
+ } |
+ } |
+ |
+ // Allowing unrecognized policy names allows presence of |
+ // 1) comments, |
Sergey Ulanov
2015/02/12 19:22:58
Comments should be dropped by the parser, no?
Łukasz Anforowicz
2015/02/12 20:34:13
By "comments" I meant JSON entries like these:
{
|
+ // 2) policies intended for future/newer versions of the host, |
+ // 3) policies not supported on all OS-s (i.e. RemoteAccessHostMatchUsername |
+ // is not supported on Windows and therefore policy_templates.json omits |
+ // schema for this policy on this particular platform). |
+ auto strategy = policy::SCHEMA_ALLOW_UNKNOWN_TOPLEVEL; |
+ |
+ std::string path; |
+ std::string error; |
+ bool changed; |
+ const policy::Schema* schema = GetPolicySchema(); |
+ if (schema->Normalize(policy_dict.get(), strategy, &path, &error, &changed)) { |
+ if (changed) { |
+ LOG(WARNING) << "Unknown (unrecognized or unsupported) policy: " << path |
+ << ": " << error; |
+ } |
+ UpdatePolicies(policy_dict.get()); |
+ } else { |
+ LOG(ERROR) << "Invalid policy contents: " << path << ": " << error; |
+ SignalPolicyError(); |
} |
- UpdatePolicies(policy_dict.get()); |
} |
void PolicyWatcher::OnPolicyServiceInitialized(policy::PolicyDomain domain) { |
@@ -225,15 +256,7 @@ void PolicyWatcher::OnPolicyServiceInitialized(policy::PolicyDomain domain) { |
scoped_ptr<PolicyWatcher> PolicyWatcher::CreateFromPolicyLoader( |
scoped_ptr<policy::AsyncPolicyLoader> async_policy_loader) { |
- // TODO(lukasza): Schema below should ideally only cover Chromoting-specific |
- // policies (expecting perf and maintanability improvement, but no functional |
- // impact). |
- policy::Schema schema = policy::Schema::Wrap(policy::GetChromeSchemaData()); |
- |
- scoped_ptr<policy::SchemaRegistry> schema_registry( |
- new policy::SchemaRegistry()); |
- schema_registry->RegisterComponent(GetPolicyNamespace(), schema); |
- |
+ scoped_ptr<policy::SchemaRegistry> schema_registry = CreateSchemaRegistry(); |
scoped_ptr<policy::AsyncPolicyProvider> policy_provider( |
new policy::AsyncPolicyProvider(schema_registry.get(), |
async_policy_loader.Pass())); |
@@ -256,8 +279,8 @@ scoped_ptr<PolicyWatcher> PolicyWatcher::Create( |
#if defined(OS_CHROMEOS) |
// On Chrome OS the PolicyService is owned by the browser. |
DCHECK(policy_service); |
- return make_scoped_ptr( |
- new PolicyWatcher(policy_service, nullptr, nullptr, nullptr)); |
+ return make_scoped_ptr(new PolicyWatcher(policy_service, nullptr, nullptr, |
+ CreateSchemaRegistry())); |
#else // !defined(OS_CHROMEOS) |
DCHECK(!policy_service); |