| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 // Most of this code is copied from: | 5 // Most of this code is copied from: |
| 6 // src/chrome/browser/policy/asynchronous_policy_loader.{h,cc} | 6 // src/chrome/browser/policy/asynchronous_policy_loader.{h,cc} |
| 7 | 7 |
| 8 #include "remoting/host/policy_watcher.h" | 8 #include "remoting/host/policy_watcher.h" |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| 11 #include "base/compiler_specific.h" | 11 #include "base/compiler_specific.h" |
| 12 #include "base/files/file_path.h" | 12 #include "base/files/file_path.h" |
| 13 #include "base/location.h" | 13 #include "base/location.h" |
| 14 #include "base/single_thread_task_runner.h" | 14 #include "base/single_thread_task_runner.h" |
| 15 #include "base/values.h" | 15 #include "base/values.h" |
| 16 #include "components/policy/core/common/async_policy_loader.h" | 16 #include "components/policy/core/common/async_policy_loader.h" |
| 17 #include "components/policy/core/common/async_policy_provider.h" | 17 #include "components/policy/core/common/async_policy_provider.h" |
| 18 #include "components/policy/core/common/policy_namespace.h" | 18 #include "components/policy/core/common/policy_namespace.h" |
| 19 #include "components/policy/core/common/policy_service_impl.h" | 19 #include "components/policy/core/common/policy_service_impl.h" |
| 20 #include "components/policy/core/common/schema.h" | 20 #include "components/policy/core/common/schema.h" |
| 21 #include "components/policy/core/common/schema_registry.h" | 21 #include "components/policy/core/common/schema_registry.h" |
| 22 #include "policy/policy_constants.h" | 22 #include "policy/policy_constants.h" |
| 23 #include "remoting/host/dns_blackhole_checker.h" | 23 #include "remoting/host/dns_blackhole_checker.h" |
| 24 #include "remoting/host/third_party_auth_config.h" |
| 25 #include "remoting/protocol/port_range.h" |
| 24 | 26 |
| 25 #if !defined(NDEBUG) | 27 #if !defined(NDEBUG) |
| 26 #include "base/json/json_reader.h" | 28 #include "base/json/json_reader.h" |
| 27 #endif | 29 #endif |
| 28 | 30 |
| 29 #if defined(OS_WIN) | 31 #if defined(OS_WIN) |
| 30 #include "components/policy/core/common/policy_loader_win.h" | 32 #include "components/policy/core/common/policy_loader_win.h" |
| 31 #elif defined(OS_MACOSX) | 33 #elif defined(OS_MACOSX) |
| 32 #include "components/policy/core/common/policy_loader_mac.h" | 34 #include "components/policy/core/common/policy_loader_mac.h" |
| 33 #include "components/policy/core/common/preferences_mac.h" | 35 #include "components/policy/core/common/preferences_mac.h" |
| 34 #elif defined(OS_POSIX) && !defined(OS_ANDROID) | 36 #elif defined(OS_POSIX) && !defined(OS_ANDROID) |
| 35 #include "components/policy/core/common/config_dir_policy_loader.h" | 37 #include "components/policy/core/common/config_dir_policy_loader.h" |
| 36 #endif | 38 #endif |
| 37 | 39 |
| 38 namespace remoting { | 40 namespace remoting { |
| 39 | 41 |
| 40 namespace key = ::policy::key; | 42 namespace key = ::policy::key; |
| 41 | 43 |
| 42 namespace { | 44 namespace { |
| 43 | 45 |
| 44 // Copies all policy values from one dictionary to another, using values from | 46 // Copies all policy values from one dictionary to another, using values from |
| 45 // |default_values| if they are not set in |from|. | 47 // |default_values| if they are not set in |from|. |
| 46 scoped_ptr<base::DictionaryValue> CopyValuesAndAddDefaults( | 48 scoped_ptr<base::DictionaryValue> CopyValuesAndAddDefaults( |
| 47 const base::DictionaryValue* from, | 49 const base::DictionaryValue& from, |
| 48 const base::DictionaryValue* default_values) { | 50 const base::DictionaryValue& default_values) { |
| 49 scoped_ptr<base::DictionaryValue> to(default_values->DeepCopy()); | 51 scoped_ptr<base::DictionaryValue> to(default_values.DeepCopy()); |
| 50 for (base::DictionaryValue::Iterator i(*default_values); !i.IsAtEnd(); | 52 for (base::DictionaryValue::Iterator i(default_values); !i.IsAtEnd(); |
| 51 i.Advance()) { | 53 i.Advance()) { |
| 52 const base::Value* value = nullptr; | 54 const base::Value* value = nullptr; |
| 53 | 55 |
| 54 // If the policy isn't in |from|, use the default. | 56 // If the policy isn't in |from|, use the default. |
| 55 if (!from->Get(i.key(), &value)) { | 57 if (!from.Get(i.key(), &value)) { |
| 56 continue; | 58 continue; |
| 57 } | 59 } |
| 58 | 60 |
| 59 CHECK(value->IsType(i.value().GetType())); | 61 CHECK(value->IsType(i.value().GetType())); |
| 60 to->Set(i.key(), value->DeepCopy()); | 62 to->Set(i.key(), value->DeepCopy()); |
| 61 } | 63 } |
| 62 | 64 |
| 63 #if !defined(NDEBUG) | 65 #if !defined(NDEBUG) |
| 64 // Replace values with those specified in DebugOverridePolicies, if present. | 66 // Replace values with those specified in DebugOverridePolicies, if present. |
| 65 std::string policy_overrides; | 67 std::string policy_overrides; |
| 66 if (from->GetString(key::kRemoteAccessHostDebugOverridePolicies, | 68 if (from.GetString(key::kRemoteAccessHostDebugOverridePolicies, |
| 67 &policy_overrides)) { | 69 &policy_overrides)) { |
| 68 scoped_ptr<base::Value> value(base::JSONReader::Read(policy_overrides)); | 70 scoped_ptr<base::Value> value(base::JSONReader::Read(policy_overrides)); |
| 69 const base::DictionaryValue* override_values; | 71 const base::DictionaryValue* override_values; |
| 70 if (value && value->GetAsDictionary(&override_values)) { | 72 if (value && value->GetAsDictionary(&override_values)) { |
| 71 to->MergeDictionary(override_values); | 73 to->MergeDictionary(override_values); |
| 72 } | 74 } |
| 73 } | 75 } |
| 74 #endif // defined(NDEBUG) | 76 #endif // defined(NDEBUG) |
| 75 | 77 |
| 76 return to.Pass(); | 78 return to.Pass(); |
| 77 } | 79 } |
| 78 | 80 |
| 79 policy::PolicyNamespace GetPolicyNamespace() { | 81 policy::PolicyNamespace GetPolicyNamespace() { |
| 80 return policy::PolicyNamespace(policy::POLICY_DOMAIN_CHROME, std::string()); | 82 return policy::PolicyNamespace(policy::POLICY_DOMAIN_CHROME, std::string()); |
| 81 } | 83 } |
| 82 | 84 |
| 83 scoped_ptr<policy::SchemaRegistry> CreateSchemaRegistry() { | 85 scoped_ptr<policy::SchemaRegistry> CreateSchemaRegistry() { |
| 84 // TODO(lukasza): Schema below should ideally only cover Chromoting-specific | 86 // TODO(lukasza): Schema below should ideally only cover Chromoting-specific |
| 85 // policies (expecting perf and maintanability improvement, but no functional | 87 // policies (expecting perf and maintanability improvement, but no functional |
| 86 // impact). | 88 // impact). |
| 87 policy::Schema schema = policy::Schema::Wrap(policy::GetChromeSchemaData()); | 89 policy::Schema schema = policy::Schema::Wrap(policy::GetChromeSchemaData()); |
| 88 | 90 |
| 89 scoped_ptr<policy::SchemaRegistry> schema_registry( | 91 scoped_ptr<policy::SchemaRegistry> schema_registry( |
| 90 new policy::SchemaRegistry()); | 92 new policy::SchemaRegistry()); |
| 91 schema_registry->RegisterComponent(GetPolicyNamespace(), schema); | 93 schema_registry->RegisterComponent(GetPolicyNamespace(), schema); |
| 92 return schema_registry.Pass(); | 94 return schema_registry.Pass(); |
| 93 } | 95 } |
| 94 | 96 |
| 97 scoped_ptr<base::DictionaryValue> CopyChromotingPoliciesIntoDictionary( |
| 98 const policy::PolicyMap& current) { |
| 99 const char kPolicyNameSubstring[] = "RemoteAccessHost"; |
| 100 scoped_ptr<base::DictionaryValue> policy_dict(new base::DictionaryValue()); |
| 101 for (auto it = current.begin(); it != current.end(); ++it) { |
| 102 const std::string& key = it->first; |
| 103 const base::Value* value = it->second.value; |
| 104 |
| 105 // Copying only Chromoting-specific policies helps avoid false alarms |
| 106 // raised by NormalizePolicies below (such alarms shutdown the host). |
| 107 // TODO(lukasza): Removing this somewhat brittle filtering will be possible |
| 108 // after having separate, Chromoting-specific schema. |
| 109 if (key.find(kPolicyNameSubstring) != std::string::npos) { |
| 110 policy_dict->Set(key, value->DeepCopy()); |
| 111 } |
| 112 } |
| 113 |
| 114 return policy_dict.Pass(); |
| 115 } |
| 116 |
| 117 // Takes a dictionary containing only 1) recognized policy names and 2) |
| 118 // well-typed policy values and further verifies policy contents. |
| 119 bool VerifyWellformedness(const base::DictionaryValue& changed_policies) { |
| 120 // Verify ThirdPartyAuthConfig policy. |
| 121 ThirdPartyAuthConfig not_used; |
| 122 switch (ThirdPartyAuthConfig::Parse(changed_policies, ¬_used)) { |
| 123 case ThirdPartyAuthConfig::NoPolicy: |
| 124 case ThirdPartyAuthConfig::ParsingSuccess: |
| 125 break; // Well-formed. |
| 126 case ThirdPartyAuthConfig::InvalidPolicy: |
| 127 return false; // Malformed. |
| 128 default: |
| 129 NOTREACHED(); |
| 130 return false; |
| 131 } |
| 132 |
| 133 // Verify UdpPortRange policy. |
| 134 std::string udp_port_range_string; |
| 135 PortRange udp_port_range; |
| 136 if (changed_policies.GetString(policy::key::kRemoteAccessHostUdpPortRange, |
| 137 &udp_port_range_string)) { |
| 138 if (!PortRange::Parse(udp_port_range_string, &udp_port_range)) { |
| 139 return false; |
| 140 } |
| 141 } |
| 142 |
| 143 // Report that all the policies were well-formed. |
| 144 return true; |
| 145 } |
| 146 |
| 95 } // namespace | 147 } // namespace |
| 96 | 148 |
| 97 void PolicyWatcher::StartWatching( | 149 void PolicyWatcher::StartWatching( |
| 98 const PolicyUpdatedCallback& policy_updated_callback, | 150 const PolicyUpdatedCallback& policy_updated_callback, |
| 99 const PolicyErrorCallback& policy_error_callback) { | 151 const PolicyErrorCallback& policy_error_callback) { |
| 100 DCHECK(CalledOnValidThread()); | 152 DCHECK(CalledOnValidThread()); |
| 101 DCHECK(!policy_updated_callback.is_null()); | 153 DCHECK(!policy_updated_callback.is_null()); |
| 102 DCHECK(!policy_error_callback.is_null()); | 154 DCHECK(!policy_error_callback.is_null()); |
| 103 DCHECK(policy_updated_callback_.is_null()); | 155 DCHECK(policy_updated_callback_.is_null()); |
| 104 | 156 |
| 105 policy_updated_callback_ = policy_updated_callback; | 157 policy_updated_callback_ = policy_updated_callback; |
| 106 policy_error_callback_ = policy_error_callback; | 158 policy_error_callback_ = policy_error_callback; |
| 107 | 159 |
| 108 // Listen for future policy changes. | 160 // Listen for future policy changes. |
| 109 policy_service_->AddObserver(policy::POLICY_DOMAIN_CHROME, this); | 161 policy_service_->AddObserver(policy::POLICY_DOMAIN_CHROME, this); |
| 110 | 162 |
| 111 // Process current policy state. | 163 // Process current policy state. |
| 112 if (policy_service_->IsInitializationComplete(policy::POLICY_DOMAIN_CHROME)) { | 164 if (policy_service_->IsInitializationComplete(policy::POLICY_DOMAIN_CHROME)) { |
| 113 OnPolicyServiceInitialized(policy::POLICY_DOMAIN_CHROME); | 165 OnPolicyServiceInitialized(policy::POLICY_DOMAIN_CHROME); |
| 114 } | 166 } |
| 115 } | 167 } |
| 116 | 168 |
| 117 void PolicyWatcher::UpdatePolicies( | |
| 118 const base::DictionaryValue* new_policies_raw) { | |
| 119 DCHECK(CalledOnValidThread()); | |
| 120 | |
| 121 // Use default values for any missing policies. | |
| 122 scoped_ptr<base::DictionaryValue> new_policies = | |
| 123 CopyValuesAndAddDefaults(new_policies_raw, default_values_.get()); | |
| 124 | |
| 125 // Find the changed policies. | |
| 126 scoped_ptr<base::DictionaryValue> changed_policies( | |
| 127 new base::DictionaryValue()); | |
| 128 base::DictionaryValue::Iterator iter(*new_policies); | |
| 129 while (!iter.IsAtEnd()) { | |
| 130 base::Value* old_policy; | |
| 131 if (!(old_policies_->Get(iter.key(), &old_policy) && | |
| 132 old_policy->Equals(&iter.value()))) { | |
| 133 changed_policies->Set(iter.key(), iter.value().DeepCopy()); | |
| 134 } | |
| 135 iter.Advance(); | |
| 136 } | |
| 137 | |
| 138 // Save the new policies. | |
| 139 old_policies_.swap(new_policies); | |
| 140 | |
| 141 // Notify our client of the changed policies. | |
| 142 if (!changed_policies->empty()) { | |
| 143 policy_updated_callback_.Run(changed_policies.Pass()); | |
| 144 } | |
| 145 } | |
| 146 | |
| 147 void PolicyWatcher::SignalPolicyError() { | 169 void PolicyWatcher::SignalPolicyError() { |
| 148 old_policies_->Clear(); | 170 old_policies_->Clear(); |
| 149 policy_error_callback_.Run(); | 171 policy_error_callback_.Run(); |
| 150 } | 172 } |
| 151 | 173 |
| 152 PolicyWatcher::PolicyWatcher( | 174 PolicyWatcher::PolicyWatcher( |
| 153 policy::PolicyService* policy_service, | 175 policy::PolicyService* policy_service, |
| 154 scoped_ptr<policy::PolicyService> owned_policy_service, | 176 scoped_ptr<policy::PolicyService> owned_policy_service, |
| 155 scoped_ptr<policy::ConfigurationPolicyProvider> owned_policy_provider, | 177 scoped_ptr<policy::ConfigurationPolicyProvider> owned_policy_provider, |
| 156 scoped_ptr<policy::SchemaRegistry> owned_schema_registry) | 178 scoped_ptr<policy::SchemaRegistry> owned_schema_registry) |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 194 | 216 |
| 195 if (owned_policy_provider_) { | 217 if (owned_policy_provider_) { |
| 196 owned_policy_provider_->Shutdown(); | 218 owned_policy_provider_->Shutdown(); |
| 197 } | 219 } |
| 198 } | 220 } |
| 199 | 221 |
| 200 const policy::Schema* PolicyWatcher::GetPolicySchema() const { | 222 const policy::Schema* PolicyWatcher::GetPolicySchema() const { |
| 201 return owned_schema_registry_->schema_map()->GetSchema(GetPolicyNamespace()); | 223 return owned_schema_registry_->schema_map()->GetSchema(GetPolicyNamespace()); |
| 202 } | 224 } |
| 203 | 225 |
| 204 void PolicyWatcher::OnPolicyUpdated(const policy::PolicyNamespace& ns, | 226 bool PolicyWatcher::NormalizePolicies(base::DictionaryValue* policy_dict) { |
| 205 const policy::PolicyMap& previous, | |
| 206 const policy::PolicyMap& current) { | |
| 207 const char kPolicyNamePrefix[] = "RemoteAccessHost"; | |
| 208 scoped_ptr<base::DictionaryValue> policy_dict(new base::DictionaryValue()); | |
| 209 for (auto it = current.begin(); it != current.end(); ++it) { | |
| 210 const std::string& key = it->first; | |
| 211 const base::Value* value = it->second.value; | |
| 212 | |
| 213 // Copying only Chromoting-specific policies helps avoid false alarms | |
| 214 // raised by Schema::Normalize below (such alarms shutdown the host). | |
| 215 // TODO(lukasza): Removing this somewhat brittle filtering will be possible | |
| 216 // after having separate, Chromoting-specific schema. | |
| 217 if (key.find(kPolicyNamePrefix) != std::string::npos) { | |
| 218 policy_dict->Set(key, value->DeepCopy()); | |
| 219 } | |
| 220 } | |
| 221 | |
| 222 // Allowing unrecognized policy names allows presence of | 227 // Allowing unrecognized policy names allows presence of |
| 223 // 1) comments (i.e. JSON of the form: { "_comment": "blah", ... }), | 228 // 1) comments (i.e. JSON of the form: { "_comment": "blah", ... }), |
| 224 // 2) policies intended for future/newer versions of the host, | 229 // 2) policies intended for future/newer versions of the host, |
| 225 // 3) policies not supported on all OS-s (i.e. RemoteAccessHostMatchUsername | 230 // 3) policies not supported on all OS-s (i.e. RemoteAccessHostMatchUsername |
| 226 // is not supported on Windows and therefore policy_templates.json omits | 231 // is not supported on Windows and therefore policy_templates.json omits |
| 227 // schema for this policy on this particular platform). | 232 // schema for this policy on this particular platform). |
| 228 auto strategy = policy::SCHEMA_ALLOW_UNKNOWN_TOPLEVEL; | 233 auto strategy = policy::SCHEMA_ALLOW_UNKNOWN_TOPLEVEL; |
| 229 | 234 |
| 230 std::string path; | 235 std::string path; |
| 231 std::string error; | 236 std::string error; |
| 232 bool changed = false; | 237 bool changed = false; |
| 233 const policy::Schema* schema = GetPolicySchema(); | 238 const policy::Schema* schema = GetPolicySchema(); |
| 234 if (schema->Normalize(policy_dict.get(), strategy, &path, &error, &changed)) { | 239 if (schema->Normalize(policy_dict, strategy, &path, &error, &changed)) { |
| 235 if (changed) { | 240 if (changed) { |
| 236 LOG(WARNING) << "Unknown (unrecognized or unsupported) policy: " << path | 241 LOG(WARNING) << "Unknown (unrecognized or unsupported) policy: " << path |
| 237 << ": " << error; | 242 << ": " << error; |
| 238 } | 243 } |
| 239 UpdatePolicies(policy_dict.get()); | 244 return true; |
| 240 } else { | 245 } else { |
| 241 LOG(ERROR) << "Invalid policy contents: " << path << ": " << error; | 246 LOG(ERROR) << "Invalid policy contents: " << path << ": " << error; |
| 242 SignalPolicyError(); | 247 return false; |
| 243 } | 248 } |
| 244 } | 249 } |
| 245 | 250 |
| 251 namespace { |
| 252 void CopyDictionaryValue(const base::DictionaryValue& from, |
| 253 base::DictionaryValue& to, |
| 254 std::string key) { |
| 255 const base::Value* value; |
| 256 if (from.Get(key, &value)) { |
| 257 to.Set(key, value->DeepCopy()); |
| 258 } |
| 259 } |
| 260 } // namespace |
| 261 |
| 262 scoped_ptr<base::DictionaryValue> |
| 263 PolicyWatcher::StoreNewAndReturnChangedPolicies( |
| 264 scoped_ptr<base::DictionaryValue> new_policies) { |
| 265 // Find the changed policies. |
| 266 scoped_ptr<base::DictionaryValue> changed_policies( |
| 267 new base::DictionaryValue()); |
| 268 base::DictionaryValue::Iterator iter(*new_policies); |
| 269 while (!iter.IsAtEnd()) { |
| 270 base::Value* old_policy; |
| 271 if (!(old_policies_->Get(iter.key(), &old_policy) && |
| 272 old_policy->Equals(&iter.value()))) { |
| 273 changed_policies->Set(iter.key(), iter.value().DeepCopy()); |
| 274 } |
| 275 iter.Advance(); |
| 276 } |
| 277 |
| 278 // If one of ThirdPartyAuthConfig policies changed, we need to include all. |
| 279 if (changed_policies->HasKey(key::kRemoteAccessHostTokenUrl) || |
| 280 changed_policies->HasKey(key::kRemoteAccessHostTokenValidationUrl) || |
| 281 changed_policies->HasKey( |
| 282 key::kRemoteAccessHostTokenValidationCertificateIssuer)) { |
| 283 CopyDictionaryValue(*new_policies, *changed_policies, |
| 284 key::kRemoteAccessHostTokenUrl); |
| 285 CopyDictionaryValue(*new_policies, *changed_policies, |
| 286 key::kRemoteAccessHostTokenValidationUrl); |
| 287 CopyDictionaryValue(*new_policies, *changed_policies, |
| 288 key::kRemoteAccessHostTokenValidationCertificateIssuer); |
| 289 } |
| 290 |
| 291 // Save the new policies. |
| 292 old_policies_.swap(new_policies); |
| 293 |
| 294 return changed_policies.Pass(); |
| 295 } |
| 296 |
| 297 void PolicyWatcher::OnPolicyUpdated(const policy::PolicyNamespace& ns, |
| 298 const policy::PolicyMap& previous, |
| 299 const policy::PolicyMap& current) { |
| 300 scoped_ptr<base::DictionaryValue> new_policies = |
| 301 CopyChromotingPoliciesIntoDictionary(current); |
| 302 |
| 303 // Check for mistyped values and get rid of unknown policies. |
| 304 if (!NormalizePolicies(new_policies.get())) { |
| 305 SignalPolicyError(); |
| 306 return; |
| 307 } |
| 308 |
| 309 // Use default values for any missing policies. |
| 310 scoped_ptr<base::DictionaryValue> filled_policies = |
| 311 CopyValuesAndAddDefaults(*new_policies, *default_values_); |
| 312 |
| 313 // Limit reporting to only the policies that were changed. |
| 314 scoped_ptr<base::DictionaryValue> changed_policies = |
| 315 StoreNewAndReturnChangedPolicies(filled_policies.Pass()); |
| 316 if (changed_policies->empty()) { |
| 317 return; |
| 318 } |
| 319 |
| 320 // Verify that we are calling the callback with valid policies. |
| 321 if (!VerifyWellformedness(*changed_policies)) { |
| 322 SignalPolicyError(); |
| 323 return; |
| 324 } |
| 325 |
| 326 // Notify our client of the changed policies. |
| 327 policy_updated_callback_.Run(changed_policies.Pass()); |
| 328 } |
| 329 |
| 246 void PolicyWatcher::OnPolicyServiceInitialized(policy::PolicyDomain domain) { | 330 void PolicyWatcher::OnPolicyServiceInitialized(policy::PolicyDomain domain) { |
| 247 policy::PolicyNamespace ns = GetPolicyNamespace(); | 331 policy::PolicyNamespace ns = GetPolicyNamespace(); |
| 248 const policy::PolicyMap& current = policy_service_->GetPolicies(ns); | 332 const policy::PolicyMap& current = policy_service_->GetPolicies(ns); |
| 249 OnPolicyUpdated(ns, current, current); | 333 OnPolicyUpdated(ns, current, current); |
| 250 } | 334 } |
| 251 | 335 |
| 252 scoped_ptr<PolicyWatcher> PolicyWatcher::CreateFromPolicyLoader( | 336 scoped_ptr<PolicyWatcher> PolicyWatcher::CreateFromPolicyLoader( |
| 253 scoped_ptr<policy::AsyncPolicyLoader> async_policy_loader) { | 337 scoped_ptr<policy::AsyncPolicyLoader> async_policy_loader) { |
| 254 scoped_ptr<policy::SchemaRegistry> schema_registry = CreateSchemaRegistry(); | 338 scoped_ptr<policy::SchemaRegistry> schema_registry = CreateSchemaRegistry(); |
| 255 scoped_ptr<policy::AsyncPolicyProvider> policy_provider( | 339 scoped_ptr<policy::AsyncPolicyProvider> policy_provider( |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 300 policy::POLICY_SCOPE_MACHINE)); | 384 policy::POLICY_SCOPE_MACHINE)); |
| 301 #else | 385 #else |
| 302 #error OS that is not yet supported by PolicyWatcher code. | 386 #error OS that is not yet supported by PolicyWatcher code. |
| 303 #endif | 387 #endif |
| 304 | 388 |
| 305 return PolicyWatcher::CreateFromPolicyLoader(policy_loader.Pass()); | 389 return PolicyWatcher::CreateFromPolicyLoader(policy_loader.Pass()); |
| 306 #endif // !(OS_CHROMEOS) | 390 #endif // !(OS_CHROMEOS) |
| 307 } | 391 } |
| 308 | 392 |
| 309 } // namespace remoting | 393 } // namespace remoting |
| OLD | NEW |