15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Most of this code is copied from various classes in
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// src/chrome/browser/policy. In particular, look at
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   configuration_policy_provider_delegate_win.{h,cc}
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   configuration_policy_loader_win.{h,cc}
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This is a reduction of the functionality in those classes.
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/host/policy_hack/policy_watcher.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <userenv.h>
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/compiler_specific.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
19868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/message_loop/message_loop_proxy.h"
205e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/string16.h"
21868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/synchronization/waitable_event.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/object_watcher.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/registry.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// userenv.dll is required for RegisterGPNotification().
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#pragma comment(lib, "userenv.lib")
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::win::RegKey;
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace remoting {
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace policy_hack {
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const wchar_t kRegistrySubKey[] = L"SOFTWARE\\Policies\\Google\\Chrome";
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class PolicyWatcherWin :
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  public PolicyWatcher,
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  public base::win::ObjectWatcher::Delegate {
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit PolicyWatcherWin(
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      scoped_refptr<base::SingleThreadTaskRunner> task_runner)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : PolicyWatcher(task_runner),
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        user_policy_changed_event_(false, false),
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        machine_policy_changed_event_(false, false),
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        user_policy_watcher_failed_(false),
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        machine_policy_watcher_failed_(false) {
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~PolicyWatcherWin() {
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void StartWatchingInternal() OVERRIDE {
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(OnPolicyWatcherThread());
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!RegisterGPNotification(user_policy_changed_event_.handle(), false)) {
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PLOG(WARNING) << "Failed to register user group policy notification";
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      user_policy_watcher_failed_ = true;
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!RegisterGPNotification(machine_policy_changed_event_.handle(), true)) {
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PLOG(WARNING) << "Failed to register machine group policy notification.";
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      machine_policy_watcher_failed_ = true;
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Reload();
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void StopWatchingInternal() OVERRIDE {
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(OnPolicyWatcherThread());
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!UnregisterGPNotification(user_policy_changed_event_.handle())) {
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PLOG(WARNING) << "Failed to unregister user group policy notification";
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!UnregisterGPNotification(machine_policy_changed_event_.handle())) {
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PLOG(WARNING) <<
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          "Failed to unregister machine group policy notification.";
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    user_policy_watcher_.StopWatching();
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    machine_policy_watcher_.StopWatching();
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Updates the watchers and schedules the reload task if appropriate.
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SetupWatches() {
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(OnPolicyWatcherThread());
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!user_policy_watcher_failed_ &&
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        !user_policy_watcher_.GetWatchedObject() &&
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        !user_policy_watcher_.StartWatching(
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            user_policy_changed_event_.handle(), this)) {
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(WARNING) << "Failed to start watch for user policy change event";
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      user_policy_watcher_failed_ = true;
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!machine_policy_watcher_failed_ &&
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        !machine_policy_watcher_.GetWatchedObject() &&
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        !machine_policy_watcher_.StartWatching(
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            machine_policy_changed_event_.handle(), this)) {
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(WARNING) << "Failed to start watch for machine policy change event";
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      machine_policy_watcher_failed_ = true;
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     }
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (user_policy_watcher_failed_ || machine_policy_watcher_failed_) {
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ScheduleFallbackReloadTask();
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool GetRegistryPolicyString(const std::string& value_name,
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               std::string* result) const {
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // presubmit: allow wstring
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::wstring value_name_wide = UTF8ToWide(value_name);
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // presubmit: allow wstring
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::wstring value;
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RegKey policy_key(HKEY_LOCAL_MACHINE, kRegistrySubKey, KEY_READ);
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (policy_key.ReadValue(value_name_wide.c_str(), &value) ==
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ERROR_SUCCESS) {
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *result = WideToUTF8(value);
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (policy_key.Open(HKEY_CURRENT_USER, kRegistrySubKey, KEY_READ) ==
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ERROR_SUCCESS) {
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (policy_key.ReadValue(value_name_wide.c_str(), &value) ==
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          ERROR_SUCCESS) {
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        *result = WideToUTF8(value);
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return true;
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool GetRegistryPolicyInteger(const std::string& value_name,
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                uint32* result) const {
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // presubmit: allow wstring
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::wstring value_name_wide = UTF8ToWide(value_name);
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DWORD value = 0;
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RegKey policy_key(HKEY_LOCAL_MACHINE, kRegistrySubKey, KEY_READ);
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (policy_key.ReadValueDW(value_name_wide.c_str(), &value) ==
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ERROR_SUCCESS) {
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *result = value;
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (policy_key.Open(HKEY_CURRENT_USER, kRegistrySubKey, KEY_READ) ==
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ERROR_SUCCESS) {
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (policy_key.ReadValueDW(value_name_wide.c_str(), &value) ==
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          ERROR_SUCCESS) {
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        *result = value;
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return true;
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool GetRegistryPolicyBoolean(const std::string& value_name,
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                bool* result) const {
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint32 local_result = 0;
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool ret = GetRegistryPolicyInteger(value_name, &local_result);
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ret)
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *result = local_result != 0;
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ret;
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<base::DictionaryValue> Load() {
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<base::DictionaryValue> policy(new base::DictionaryValue());
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (base::DictionaryValue::Iterator i(Defaults());
175c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)         !i.IsAtEnd(); i.Advance()) {
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const std::string& policy_name = i.key();
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (i.value().GetType() == base::DictionaryValue::TYPE_BOOLEAN) {
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        bool bool_value;
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (GetRegistryPolicyBoolean(policy_name, &bool_value)) {
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          policy->SetBoolean(policy_name, bool_value);
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (i.value().GetType() == base::DictionaryValue::TYPE_STRING) {
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        std::string string_value;
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (GetRegistryPolicyString(policy_name, &string_value)) {
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          policy->SetString(policy_name, string_value);
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return policy.Pass();
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Post a reload notification and update the watch machinery.
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Reload() {
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(OnPolicyWatcherThread());
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SetupWatches();
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<DictionaryValue> new_policy(Load());
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UpdatePolicies(new_policy.get());
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ObjectWatcher::Delegate overrides:
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnObjectSignaled(HANDLE object) {
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(OnPolicyWatcherThread());
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(object == user_policy_changed_event_.handle() ||
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           object == machine_policy_changed_event_.handle())
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        << "unexpected object signaled policy reload, obj = "
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        << std::showbase << std::hex << object;
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Reload();
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::WaitableEvent user_policy_changed_event_;
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::WaitableEvent machine_policy_changed_event_;
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::win::ObjectWatcher user_policy_watcher_;
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::win::ObjectWatcher machine_policy_watcher_;
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool user_policy_watcher_failed_;
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool machine_policy_watcher_failed_;
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PolicyWatcher* PolicyWatcher::Create(
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return new PolicyWatcherWin(task_runner);
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace policy_hack
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace remoting
226