| 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 <utility> | 10 #include <utility> |
| (...skipping 29 matching lines...) Expand all Loading... |
| 40 #elif defined(OS_POSIX) && !defined(OS_ANDROID) | 40 #elif defined(OS_POSIX) && !defined(OS_ANDROID) |
| 41 #include "components/policy/core/common/config_dir_policy_loader.h" | 41 #include "components/policy/core/common/config_dir_policy_loader.h" |
| 42 #endif | 42 #endif |
| 43 | 43 |
| 44 namespace remoting { | 44 namespace remoting { |
| 45 | 45 |
| 46 namespace key = ::policy::key; | 46 namespace key = ::policy::key; |
| 47 | 47 |
| 48 namespace { | 48 namespace { |
| 49 | 49 |
| 50 // Watches for changes to the managed remote access host policies. |
| 51 class PolicyWatcherImpl : public PolicyWatcher, |
| 52 private policy::PolicyService::Observer { |
| 53 public: |
| 54 // |policy_service_task_runner| is the task runner where it is safe |
| 55 // to call |policy_service_| methods and where we expect to get callbacks |
| 56 // from |policy_service_|. |
| 57 PolicyWatcherImpl( |
| 58 policy::PolicyService* policy_service, |
| 59 std::unique_ptr<policy::PolicyService> owned_policy_service, |
| 60 std::unique_ptr<policy::ConfigurationPolicyProvider> |
| 61 owned_policy_provider, |
| 62 std::unique_ptr<policy::SchemaRegistry> owned_schema_registry); |
| 63 |
| 64 ~PolicyWatcherImpl() override; |
| 65 |
| 66 void StartWatching(const PolicyUpdatedCallback& policy_updated_callback, |
| 67 const PolicyErrorCallback& policy_error_callback) override; |
| 68 |
| 69 private: |
| 70 friend class PolicyWatcherTest; |
| 71 |
| 72 const policy::Schema* GetPolicySchema() const override; |
| 73 const base::DictionaryValue* GetDefaultValues() const override; |
| 74 |
| 75 // Simplifying wrapper around Schema::Normalize. |
| 76 // - Returns false if |dict| is invalid (i.e. contains mistyped policy |
| 77 // values). |
| 78 // - Returns true if |dict| was valid or got normalized. |
| 79 bool NormalizePolicies(base::DictionaryValue* dict); |
| 80 |
| 81 // Stores |new_policies| into |old_policies_|. Returns dictionary with items |
| 82 // from |new_policies| that are different from the old |old_policies_|. |
| 83 std::unique_ptr<base::DictionaryValue> StoreNewAndReturnChangedPolicies( |
| 84 std::unique_ptr<base::DictionaryValue> new_policies); |
| 85 |
| 86 // Signals policy error to the registered |PolicyErrorCallback|. |
| 87 void SignalPolicyError(); |
| 88 |
| 89 // PolicyService::Observer interface. |
| 90 void OnPolicyUpdated(const policy::PolicyNamespace& ns, |
| 91 const policy::PolicyMap& previous, |
| 92 const policy::PolicyMap& current) override; |
| 93 void OnPolicyServiceInitialized(policy::PolicyDomain domain) override; |
| 94 |
| 95 PolicyUpdatedCallback policy_updated_callback_; |
| 96 PolicyErrorCallback policy_error_callback_; |
| 97 |
| 98 std::unique_ptr<base::DictionaryValue> old_policies_; |
| 99 std::unique_ptr<base::DictionaryValue> default_values_; |
| 100 |
| 101 policy::PolicyService* policy_service_; |
| 102 |
| 103 // Order of fields below is important to ensure destruction takes object |
| 104 // dependencies into account: |
| 105 // - |owned_policy_service_| uses |owned_policy_provider_| |
| 106 // - |owned_policy_provider_| uses |owned_schema_registry_| |
| 107 std::unique_ptr<policy::SchemaRegistry> owned_schema_registry_; |
| 108 std::unique_ptr<policy::ConfigurationPolicyProvider> owned_policy_provider_; |
| 109 std::unique_ptr<policy::PolicyService> owned_policy_service_; |
| 110 |
| 111 DISALLOW_COPY_AND_ASSIGN(PolicyWatcherImpl); |
| 112 }; |
| 113 |
| 50 // Copies all policy values from one dictionary to another, using values from | 114 // Copies all policy values from one dictionary to another, using values from |
| 51 // |default_values| if they are not set in |from|. | 115 // |default_values| if they are not set in |from|. |
| 52 std::unique_ptr<base::DictionaryValue> CopyValuesAndAddDefaults( | 116 std::unique_ptr<base::DictionaryValue> CopyValuesAndAddDefaults( |
| 53 const base::DictionaryValue& from, | 117 const base::DictionaryValue& from, |
| 54 const base::DictionaryValue& default_values) { | 118 const base::DictionaryValue& default_values) { |
| 55 std::unique_ptr<base::DictionaryValue> to(default_values.CreateDeepCopy()); | 119 std::unique_ptr<base::DictionaryValue> to(default_values.CreateDeepCopy()); |
| 56 for (base::DictionaryValue::Iterator i(default_values); !i.IsAtEnd(); | 120 for (base::DictionaryValue::Iterator i(default_values); !i.IsAtEnd(); |
| 57 i.Advance()) { | 121 i.Advance()) { |
| 58 const base::Value* value = nullptr; | 122 const base::Value* value = nullptr; |
| 59 | 123 |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 129 &udp_port_range_string)) { | 193 &udp_port_range_string)) { |
| 130 if (!PortRange::Parse(udp_port_range_string, &udp_port_range)) { | 194 if (!PortRange::Parse(udp_port_range_string, &udp_port_range)) { |
| 131 return false; | 195 return false; |
| 132 } | 196 } |
| 133 } | 197 } |
| 134 | 198 |
| 135 // Report that all the policies were well-formed. | 199 // Report that all the policies were well-formed. |
| 136 return true; | 200 return true; |
| 137 } | 201 } |
| 138 | 202 |
| 139 } // namespace | 203 void CopyDictionaryValue(const base::DictionaryValue& from, |
| 204 base::DictionaryValue& to, |
| 205 std::string key) { |
| 206 const base::Value* value; |
| 207 if (from.Get(key, &value)) { |
| 208 to.Set(key, value->CreateDeepCopy()); |
| 209 } |
| 210 } |
| 140 | 211 |
| 141 void PolicyWatcher::StartWatching( | 212 void PolicyWatcherImpl::StartWatching( |
| 142 const PolicyUpdatedCallback& policy_updated_callback, | 213 const PolicyUpdatedCallback& policy_updated_callback, |
| 143 const PolicyErrorCallback& policy_error_callback) { | 214 const PolicyErrorCallback& policy_error_callback) { |
| 144 DCHECK(CalledOnValidThread()); | 215 DCHECK(CalledOnValidThread()); |
| 145 DCHECK(!policy_updated_callback.is_null()); | 216 DCHECK(!policy_updated_callback.is_null()); |
| 146 DCHECK(!policy_error_callback.is_null()); | 217 DCHECK(!policy_error_callback.is_null()); |
| 147 DCHECK(policy_updated_callback_.is_null()); | 218 DCHECK(policy_updated_callback_.is_null()); |
| 148 | 219 |
| 149 policy_updated_callback_ = policy_updated_callback; | 220 policy_updated_callback_ = policy_updated_callback; |
| 150 policy_error_callback_ = policy_error_callback; | 221 policy_error_callback_ = policy_error_callback; |
| 151 | 222 |
| 152 // Listen for future policy changes. | 223 // Listen for future policy changes. |
| 153 policy_service_->AddObserver(policy::POLICY_DOMAIN_CHROME, this); | 224 policy_service_->AddObserver(policy::POLICY_DOMAIN_CHROME, this); |
| 154 | 225 |
| 155 // Process current policy state. | 226 // Process current policy state. |
| 156 if (policy_service_->IsInitializationComplete(policy::POLICY_DOMAIN_CHROME)) { | 227 if (policy_service_->IsInitializationComplete(policy::POLICY_DOMAIN_CHROME)) { |
| 157 OnPolicyServiceInitialized(policy::POLICY_DOMAIN_CHROME); | 228 OnPolicyServiceInitialized(policy::POLICY_DOMAIN_CHROME); |
| 158 } | 229 } |
| 159 } | 230 } |
| 160 | 231 |
| 161 void PolicyWatcher::SignalPolicyError() { | 232 void PolicyWatcherImpl::SignalPolicyError() { |
| 162 old_policies_->Clear(); | 233 old_policies_->Clear(); |
| 163 policy_error_callback_.Run(); | 234 policy_error_callback_.Run(); |
| 164 } | 235 } |
| 165 | 236 |
| 166 PolicyWatcher::PolicyWatcher( | 237 PolicyWatcherImpl::PolicyWatcherImpl( |
| 167 policy::PolicyService* policy_service, | 238 policy::PolicyService* policy_service, |
| 168 std::unique_ptr<policy::PolicyService> owned_policy_service, | 239 std::unique_ptr<policy::PolicyService> owned_policy_service, |
| 169 std::unique_ptr<policy::ConfigurationPolicyProvider> owned_policy_provider, | 240 std::unique_ptr<policy::ConfigurationPolicyProvider> owned_policy_provider, |
| 170 std::unique_ptr<policy::SchemaRegistry> owned_schema_registry) | 241 std::unique_ptr<policy::SchemaRegistry> owned_schema_registry) |
| 171 : old_policies_(new base::DictionaryValue()), | 242 : old_policies_(new base::DictionaryValue()), |
| 172 default_values_(new base::DictionaryValue()), | 243 default_values_(new base::DictionaryValue()), |
| 173 policy_service_(policy_service), | 244 policy_service_(policy_service), |
| 174 owned_schema_registry_(std::move(owned_schema_registry)), | 245 owned_schema_registry_(std::move(owned_schema_registry)), |
| 175 owned_policy_provider_(std::move(owned_policy_provider)), | 246 owned_policy_provider_(std::move(owned_policy_provider)), |
| 176 owned_policy_service_(std::move(owned_policy_service)) { | 247 owned_policy_service_(std::move(owned_policy_service)) { |
| (...skipping 15 matching lines...) Expand all Loading... |
| 192 key::kRemoteAccessHostTokenValidationCertificateIssuer, std::string()); | 263 key::kRemoteAccessHostTokenValidationCertificateIssuer, std::string()); |
| 193 default_values_->SetBoolean(key::kRemoteAccessHostAllowClientPairing, true); | 264 default_values_->SetBoolean(key::kRemoteAccessHostAllowClientPairing, true); |
| 194 default_values_->SetBoolean(key::kRemoteAccessHostAllowGnubbyAuth, true); | 265 default_values_->SetBoolean(key::kRemoteAccessHostAllowGnubbyAuth, true); |
| 195 default_values_->SetBoolean(key::kRemoteAccessHostAllowRelayedConnection, | 266 default_values_->SetBoolean(key::kRemoteAccessHostAllowRelayedConnection, |
| 196 true); | 267 true); |
| 197 default_values_->SetString(key::kRemoteAccessHostUdpPortRange, ""); | 268 default_values_->SetString(key::kRemoteAccessHostUdpPortRange, ""); |
| 198 default_values_->SetBoolean( | 269 default_values_->SetBoolean( |
| 199 key::kRemoteAccessHostAllowUiAccessForRemoteAssistance, false); | 270 key::kRemoteAccessHostAllowUiAccessForRemoteAssistance, false); |
| 200 } | 271 } |
| 201 | 272 |
| 202 PolicyWatcher::~PolicyWatcher() { | 273 PolicyWatcherImpl::~PolicyWatcherImpl() { |
| 203 // Stop observing |policy_service_| if StartWatching() has been called. | 274 // Stop observing |policy_service_| if StartWatching() has been called. |
| 204 if (!policy_updated_callback_.is_null()) { | 275 if (!policy_updated_callback_.is_null()) { |
| 205 policy_service_->RemoveObserver(policy::POLICY_DOMAIN_CHROME, this); | 276 policy_service_->RemoveObserver(policy::POLICY_DOMAIN_CHROME, this); |
| 206 } | 277 } |
| 207 | 278 |
| 208 if (owned_policy_provider_) { | 279 if (owned_policy_provider_) { |
| 209 owned_policy_provider_->Shutdown(); | 280 owned_policy_provider_->Shutdown(); |
| 210 } | 281 } |
| 211 } | 282 } |
| 212 | 283 |
| 213 const policy::Schema* PolicyWatcher::GetPolicySchema() const { | 284 const policy::Schema* PolicyWatcherImpl::GetPolicySchema() const { |
| 214 return owned_schema_registry_->schema_map()->GetSchema(GetPolicyNamespace()); | 285 return owned_schema_registry_->schema_map()->GetSchema(GetPolicyNamespace()); |
| 215 } | 286 } |
| 216 | 287 |
| 217 bool PolicyWatcher::NormalizePolicies(base::DictionaryValue* policy_dict) { | 288 const base::DictionaryValue* PolicyWatcherImpl::GetDefaultValues() const { |
| 289 return default_values_.get(); |
| 290 } |
| 291 |
| 292 bool PolicyWatcherImpl::NormalizePolicies(base::DictionaryValue* policy_dict) { |
| 218 // Allowing unrecognized policy names allows presence of | 293 // Allowing unrecognized policy names allows presence of |
| 219 // 1) comments (i.e. JSON of the form: { "_comment": "blah", ... }), | 294 // 1) comments (i.e. JSON of the form: { "_comment": "blah", ... }), |
| 220 // 2) policies intended for future/newer versions of the host, | 295 // 2) policies intended for future/newer versions of the host, |
| 221 // 3) policies not supported on all OS-s (i.e. RemoteAccessHostMatchUsername | 296 // 3) policies not supported on all OS-s (i.e. RemoteAccessHostMatchUsername |
| 222 // is not supported on Windows and therefore policy_templates.json omits | 297 // is not supported on Windows and therefore policy_templates.json omits |
| 223 // schema for this policy on this particular platform). | 298 // schema for this policy on this particular platform). |
| 224 auto strategy = policy::SCHEMA_ALLOW_UNKNOWN_TOPLEVEL; | 299 auto strategy = policy::SCHEMA_ALLOW_UNKNOWN_TOPLEVEL; |
| 225 | 300 |
| 226 std::string path; | 301 std::string path; |
| 227 std::string error; | 302 std::string error; |
| 228 bool changed = false; | 303 bool changed = false; |
| 229 const policy::Schema* schema = GetPolicySchema(); | 304 const policy::Schema* schema = GetPolicySchema(); |
| 230 if (schema->Normalize(policy_dict, strategy, &path, &error, &changed)) { | 305 if (schema->Normalize(policy_dict, strategy, &path, &error, &changed)) { |
| 231 if (changed) { | 306 if (changed) { |
| 232 LOG(WARNING) << "Unknown (unrecognized or unsupported) policy: " << path | 307 LOG(WARNING) << "Unknown (unrecognized or unsupported) policy: " << path |
| 233 << ": " << error; | 308 << ": " << error; |
| 234 } | 309 } |
| 235 return true; | 310 return true; |
| 236 } else { | 311 } else { |
| 237 LOG(ERROR) << "Invalid policy contents: " << path << ": " << error; | 312 LOG(ERROR) << "Invalid policy contents: " << path << ": " << error; |
| 238 return false; | 313 return false; |
| 239 } | 314 } |
| 240 } | 315 } |
| 241 | 316 |
| 242 namespace { | |
| 243 void CopyDictionaryValue(const base::DictionaryValue& from, | |
| 244 base::DictionaryValue& to, | |
| 245 std::string key) { | |
| 246 const base::Value* value; | |
| 247 if (from.Get(key, &value)) { | |
| 248 to.Set(key, value->CreateDeepCopy()); | |
| 249 } | |
| 250 } | |
| 251 } // namespace | |
| 252 | |
| 253 std::unique_ptr<base::DictionaryValue> | 317 std::unique_ptr<base::DictionaryValue> |
| 254 PolicyWatcher::StoreNewAndReturnChangedPolicies( | 318 PolicyWatcherImpl::StoreNewAndReturnChangedPolicies( |
| 255 std::unique_ptr<base::DictionaryValue> new_policies) { | 319 std::unique_ptr<base::DictionaryValue> new_policies) { |
| 256 // Find the changed policies. | 320 // Find the changed policies. |
| 257 std::unique_ptr<base::DictionaryValue> changed_policies( | 321 std::unique_ptr<base::DictionaryValue> changed_policies( |
| 258 new base::DictionaryValue()); | 322 new base::DictionaryValue()); |
| 259 base::DictionaryValue::Iterator iter(*new_policies); | 323 base::DictionaryValue::Iterator iter(*new_policies); |
| 260 while (!iter.IsAtEnd()) { | 324 while (!iter.IsAtEnd()) { |
| 261 base::Value* old_policy; | 325 base::Value* old_policy; |
| 262 if (!(old_policies_->Get(iter.key(), &old_policy) && | 326 if (!(old_policies_->Get(iter.key(), &old_policy) && |
| 263 old_policy->Equals(&iter.value()))) { | 327 old_policy->Equals(&iter.value()))) { |
| 264 changed_policies->Set(iter.key(), iter.value().CreateDeepCopy()); | 328 changed_policies->Set(iter.key(), iter.value().CreateDeepCopy()); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 278 CopyDictionaryValue(*new_policies, *changed_policies, | 342 CopyDictionaryValue(*new_policies, *changed_policies, |
| 279 key::kRemoteAccessHostTokenValidationCertificateIssuer); | 343 key::kRemoteAccessHostTokenValidationCertificateIssuer); |
| 280 } | 344 } |
| 281 | 345 |
| 282 // Save the new policies. | 346 // Save the new policies. |
| 283 old_policies_.swap(new_policies); | 347 old_policies_.swap(new_policies); |
| 284 | 348 |
| 285 return changed_policies; | 349 return changed_policies; |
| 286 } | 350 } |
| 287 | 351 |
| 288 void PolicyWatcher::OnPolicyUpdated(const policy::PolicyNamespace& ns, | 352 void PolicyWatcherImpl::OnPolicyUpdated(const policy::PolicyNamespace& ns, |
| 289 const policy::PolicyMap& previous, | 353 const policy::PolicyMap& previous, |
| 290 const policy::PolicyMap& current) { | 354 const policy::PolicyMap& current) { |
| 291 std::unique_ptr<base::DictionaryValue> new_policies = | 355 std::unique_ptr<base::DictionaryValue> new_policies = |
| 292 CopyChromotingPoliciesIntoDictionary(current); | 356 CopyChromotingPoliciesIntoDictionary(current); |
| 293 | 357 |
| 294 // Check for mistyped values and get rid of unknown policies. | 358 // Check for mistyped values and get rid of unknown policies. |
| 295 if (!NormalizePolicies(new_policies.get())) { | 359 if (!NormalizePolicies(new_policies.get())) { |
| 296 SignalPolicyError(); | 360 SignalPolicyError(); |
| 297 return; | 361 return; |
| 298 } | 362 } |
| 299 | 363 |
| 300 // Use default values for any missing policies. | 364 // Use default values for any missing policies. |
| (...skipping 10 matching lines...) Expand all Loading... |
| 311 // Verify that we are calling the callback with valid policies. | 375 // Verify that we are calling the callback with valid policies. |
| 312 if (!VerifyWellformedness(*changed_policies)) { | 376 if (!VerifyWellformedness(*changed_policies)) { |
| 313 SignalPolicyError(); | 377 SignalPolicyError(); |
| 314 return; | 378 return; |
| 315 } | 379 } |
| 316 | 380 |
| 317 // Notify our client of the changed policies. | 381 // Notify our client of the changed policies. |
| 318 policy_updated_callback_.Run(std::move(changed_policies)); | 382 policy_updated_callback_.Run(std::move(changed_policies)); |
| 319 } | 383 } |
| 320 | 384 |
| 321 void PolicyWatcher::OnPolicyServiceInitialized(policy::PolicyDomain domain) { | 385 void PolicyWatcherImpl::OnPolicyServiceInitialized( |
| 386 policy::PolicyDomain domain) { |
| 322 policy::PolicyNamespace ns = GetPolicyNamespace(); | 387 policy::PolicyNamespace ns = GetPolicyNamespace(); |
| 323 const policy::PolicyMap& current = policy_service_->GetPolicies(ns); | 388 const policy::PolicyMap& current = policy_service_->GetPolicies(ns); |
| 324 OnPolicyUpdated(ns, current, current); | 389 OnPolicyUpdated(ns, current, current); |
| 325 } | 390 } |
| 326 | 391 |
| 392 } // namespace |
| 393 |
| 394 PolicyWatcher::PolicyWatcher() {} |
| 395 PolicyWatcher::~PolicyWatcher() {} |
| 396 |
| 327 std::unique_ptr<PolicyWatcher> PolicyWatcher::CreateFromPolicyLoader( | 397 std::unique_ptr<PolicyWatcher> PolicyWatcher::CreateFromPolicyLoader( |
| 328 std::unique_ptr<policy::AsyncPolicyLoader> async_policy_loader) { | 398 std::unique_ptr<policy::AsyncPolicyLoader> async_policy_loader) { |
| 329 std::unique_ptr<policy::SchemaRegistry> schema_registry = | 399 std::unique_ptr<policy::SchemaRegistry> schema_registry = |
| 330 CreateSchemaRegistry(); | 400 CreateSchemaRegistry(); |
| 331 std::unique_ptr<policy::AsyncPolicyProvider> policy_provider( | 401 std::unique_ptr<policy::AsyncPolicyProvider> policy_provider( |
| 332 new policy::AsyncPolicyProvider(schema_registry.get(), | 402 new policy::AsyncPolicyProvider(schema_registry.get(), |
| 333 std::move(async_policy_loader))); | 403 std::move(async_policy_loader))); |
| 334 policy_provider->Init(schema_registry.get()); | 404 policy_provider->Init(schema_registry.get()); |
| 335 | 405 |
| 336 policy::PolicyServiceImpl::Providers providers; | 406 policy::PolicyServiceImpl::Providers providers; |
| 337 providers.push_back(policy_provider.get()); | 407 providers.push_back(policy_provider.get()); |
| 338 std::unique_ptr<policy::PolicyService> policy_service( | 408 std::unique_ptr<policy::PolicyService> policy_service( |
| 339 new policy::PolicyServiceImpl(providers)); | 409 new policy::PolicyServiceImpl(providers)); |
| 340 | 410 |
| 341 policy::PolicyService* borrowed_policy_service = policy_service.get(); | 411 policy::PolicyService* borrowed_policy_service = policy_service.get(); |
| 342 return base::WrapUnique(new PolicyWatcher( | 412 return base::WrapUnique(new PolicyWatcherImpl( |
| 343 borrowed_policy_service, std::move(policy_service), | 413 borrowed_policy_service, std::move(policy_service), |
| 344 std::move(policy_provider), std::move(schema_registry))); | 414 std::move(policy_provider), std::move(schema_registry))); |
| 345 } | 415 } |
| 346 | 416 |
| 347 std::unique_ptr<PolicyWatcher> PolicyWatcher::Create( | 417 std::unique_ptr<PolicyWatcher> PolicyWatcher::Create( |
| 348 policy::PolicyService* policy_service, | 418 policy::PolicyService* policy_service, |
| 349 const scoped_refptr<base::SingleThreadTaskRunner>& file_task_runner) { | 419 const scoped_refptr<base::SingleThreadTaskRunner>& file_task_runner) { |
| 350 #if defined(OS_CHROMEOS) | 420 #if defined(OS_CHROMEOS) |
| 351 // On Chrome OS the PolicyService is owned by the browser. | 421 // On Chrome OS the PolicyService is owned by the browser. |
| 352 DCHECK(policy_service); | 422 DCHECK(policy_service); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 384 CreateSchemaRegistry())); | 454 CreateSchemaRegistry())); |
| 385 #else | 455 #else |
| 386 #error OS that is not yet supported by PolicyWatcher code. | 456 #error OS that is not yet supported by PolicyWatcher code. |
| 387 #endif | 457 #endif |
| 388 | 458 |
| 389 return PolicyWatcher::CreateFromPolicyLoader(std::move(policy_loader)); | 459 return PolicyWatcher::CreateFromPolicyLoader(std::move(policy_loader)); |
| 390 #endif // !(OS_CHROMEOS) | 460 #endif // !(OS_CHROMEOS) |
| 391 } | 461 } |
| 392 | 462 |
| 393 } // namespace remoting | 463 } // namespace remoting |
| OLD | NEW |