blob: a333911f9ad84b658a2cf167da2812887805c062 [file] [log] [blame]
[email protected]ddaf98a2012-02-16 00:13:561// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]c9927802011-08-15 23:54:572// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]f992585f2011-08-17 22:07:555// Most of this code is copied from various classes in
6// src/chrome/browser/policy. In particular, look at
7//
8// configuration_policy_provider_delegate_win.{h,cc}
9// configuration_policy_loader_win.{h,cc}
10//
11// This is a reduction of the functionality in those classes.
12
[email protected]000d1f62012-07-24 01:56:5413#include "remoting/host/policy_hack/policy_watcher.h"
[email protected]c9927802011-08-15 23:54:5714
[email protected]f992585f2011-08-17 22:07:5515#include <userenv.h>
16
[email protected]c9927802011-08-15 23:54:5717#include "base/compiler_specific.h"
[email protected]7f8f5562011-09-18 20:59:0618#include "base/memory/scoped_ptr.h"
[email protected]c9927802011-08-15 23:54:5719#include "base/message_loop_proxy.h"
[email protected]7f8f5562011-09-18 20:59:0620#include "base/string16.h"
[email protected]c9927802011-08-15 23:54:5721#include "base/synchronization/waitable_event.h"
[email protected]7f8f5562011-09-18 20:59:0622#include "base/utf_string_conversions.h"
[email protected]f992585f2011-08-17 22:07:5523#include "base/values.h"
24#include "base/win/object_watcher.h"
[email protected]7f8f5562011-09-18 20:59:0625#include "base/win/registry.h"
[email protected]f992585f2011-08-17 22:07:5526
27// userenv.dll is required for RegisterGPNotification().
28#pragma comment(lib, "userenv.lib")
29
30using base::win::RegKey;
[email protected]c9927802011-08-15 23:54:5731
32namespace remoting {
33namespace policy_hack {
34
[email protected]f992585f2011-08-17 22:07:5535namespace {
36
[email protected]f992585f2011-08-17 22:07:5537const wchar_t kRegistrySubKey[] = L"SOFTWARE\\Policies\\Google\\Chrome";
[email protected]f992585f2011-08-17 22:07:5538
39} // namespace
40
[email protected]000d1f62012-07-24 01:56:5441class PolicyWatcherWin :
42 public PolicyWatcher,
[email protected]f992585f2011-08-17 22:07:5543 public base::win::ObjectWatcher::Delegate {
[email protected]c9927802011-08-15 23:54:5744 public:
[email protected]000d1f62012-07-24 01:56:5445 explicit PolicyWatcherWin(
46 scoped_refptr<base::SingleThreadTaskRunner> task_runner)
47 : PolicyWatcher(task_runner),
[email protected]f992585f2011-08-17 22:07:5548 user_policy_changed_event_(false, false),
49 machine_policy_changed_event_(false, false),
50 user_policy_watcher_failed_(false),
51 machine_policy_watcher_failed_(false) {
[email protected]c9927802011-08-15 23:54:5752 }
53
[email protected]000d1f62012-07-24 01:56:5454 virtual ~PolicyWatcherWin() {
[email protected]c9927802011-08-15 23:54:5755 }
56
[email protected]f992585f2011-08-17 22:07:5557 virtual void StartWatchingInternal() OVERRIDE {
[email protected]000d1f62012-07-24 01:56:5458 DCHECK(OnPolicyWatcherThread());
[email protected]f992585f2011-08-17 22:07:5559
60 if (!RegisterGPNotification(user_policy_changed_event_.handle(), false)) {
61 PLOG(WARNING) << "Failed to register user group policy notification";
62 user_policy_watcher_failed_ = true;
63 }
64
65 if (!RegisterGPNotification(machine_policy_changed_event_.handle(), true)) {
66 PLOG(WARNING) << "Failed to register machine group policy notification.";
67 machine_policy_watcher_failed_ = true;
68 }
69
70 Reload();
[email protected]c9927802011-08-15 23:54:5771 }
72
[email protected]f992585f2011-08-17 22:07:5573 virtual void StopWatchingInternal() OVERRIDE {
[email protected]000d1f62012-07-24 01:56:5474 DCHECK(OnPolicyWatcherThread());
[email protected]f992585f2011-08-17 22:07:5575
76 if (!UnregisterGPNotification(user_policy_changed_event_.handle())) {
77 PLOG(WARNING) << "Failed to unregister user group policy notification";
78 }
79
80 if (!UnregisterGPNotification(machine_policy_changed_event_.handle())) {
81 PLOG(WARNING) <<
82 "Failed to unregister machine group policy notification.";
83 }
84
85 user_policy_watcher_.StopWatching();
86 machine_policy_watcher_.StopWatching();
[email protected]c9927802011-08-15 23:54:5787 }
88
89 private:
[email protected]f992585f2011-08-17 22:07:5590 // Updates the watchers and schedules the reload task if appropriate.
91 void SetupWatches() {
[email protected]000d1f62012-07-24 01:56:5492 DCHECK(OnPolicyWatcherThread());
[email protected]f992585f2011-08-17 22:07:5593
94 if (!user_policy_watcher_failed_ &&
95 !user_policy_watcher_.GetWatchedObject() &&
96 !user_policy_watcher_.StartWatching(
97 user_policy_changed_event_.handle(), this)) {
98 LOG(WARNING) << "Failed to start watch for user policy change event";
99 user_policy_watcher_failed_ = true;
100 }
101
102 if (!machine_policy_watcher_failed_ &&
103 !machine_policy_watcher_.GetWatchedObject() &&
104 !machine_policy_watcher_.StartWatching(
105 machine_policy_changed_event_.handle(), this)) {
106 LOG(WARNING) << "Failed to start watch for machine policy change event";
107 machine_policy_watcher_failed_ = true;
108 }
109
110 if (user_policy_watcher_failed_ || machine_policy_watcher_failed_) {
111 ScheduleFallbackReloadTask();
112 }
113 }
114
[email protected]5693a0212012-07-31 15:05:22115 bool GetRegistryPolicyString(const std::string& value_name,
116 std::string* result) const {
[email protected]a11dbe9b2012-08-07 01:32:58117 // presubmit: allow wstring
[email protected]5693a0212012-07-31 15:05:22118 std::wstring value_name_wide = UTF8ToWide(value_name);
[email protected]a11dbe9b2012-08-07 01:32:58119 // presubmit: allow wstring
[email protected]5693a0212012-07-31 15:05:22120 std::wstring value;
121 RegKey policy_key(HKEY_LOCAL_MACHINE, kRegistrySubKey, KEY_READ);
122 if (policy_key.ReadValue(value_name_wide.c_str(), &value) ==
123 ERROR_SUCCESS) {
124 *result = WideToUTF8(value);
125 return true;
126 }
127
128 if (policy_key.Open(HKEY_CURRENT_USER, kRegistrySubKey, KEY_READ) ==
129 ERROR_SUCCESS) {
130 if (policy_key.ReadValue(value_name_wide.c_str(), &value) ==
131 ERROR_SUCCESS) {
132 *result = WideToUTF8(value);
133 return true;
134 }
135 }
136 return false;
137 }
138
139 bool GetRegistryPolicyInteger(const std::string& value_name,
[email protected]f992585f2011-08-17 22:07:55140 uint32* result) const {
[email protected]a11dbe9b2012-08-07 01:32:58141 // presubmit: allow wstring
[email protected]5693a0212012-07-31 15:05:22142 std::wstring value_name_wide = UTF8ToWide(value_name);
[email protected]f992585f2011-08-17 22:07:55143 DWORD value = 0;
144 RegKey policy_key(HKEY_LOCAL_MACHINE, kRegistrySubKey, KEY_READ);
[email protected]5693a0212012-07-31 15:05:22145 if (policy_key.ReadValueDW(value_name_wide.c_str(), &value) ==
146 ERROR_SUCCESS) {
[email protected]f992585f2011-08-17 22:07:55147 *result = value;
148 return true;
149 }
150
151 if (policy_key.Open(HKEY_CURRENT_USER, kRegistrySubKey, KEY_READ) ==
152 ERROR_SUCCESS) {
[email protected]5693a0212012-07-31 15:05:22153 if (policy_key.ReadValueDW(value_name_wide.c_str(), &value) ==
154 ERROR_SUCCESS) {
[email protected]f992585f2011-08-17 22:07:55155 *result = value;
156 return true;
157 }
158 }
159 return false;
160 }
161
[email protected]5693a0212012-07-31 15:05:22162 bool GetRegistryPolicyBoolean(const std::string& value_name,
[email protected]f992585f2011-08-17 22:07:55163 bool* result) const {
164 uint32 local_result = 0;
165 bool ret = GetRegistryPolicyInteger(value_name, &local_result);
166 if (ret)
167 *result = local_result != 0;
168 return ret;
169 }
170
171 base::DictionaryValue* Load() {
172 base::DictionaryValue* policy = new base::DictionaryValue();
173
[email protected]000d1f62012-07-24 01:56:54174 for (int i = 0; i < kBooleanPolicyNamesNum; ++i) {
175 const char* policy_name = kBooleanPolicyNames[i];
176 bool bool_value;
[email protected]5693a0212012-07-31 15:05:22177 if (GetRegistryPolicyBoolean(policy_name, &bool_value)) {
[email protected]000d1f62012-07-24 01:56:54178 policy->SetBoolean(policy_name, bool_value);
179 }
[email protected]f992585f2011-08-17 22:07:55180 }
[email protected]5693a0212012-07-31 15:05:22181 for (int i = 0; i < kStringPolicyNamesNum; ++i) {
182 const char* policy_name = kStringPolicyNames[i];
183 std::string string_value;
184 if (GetRegistryPolicyString(policy_name, &string_value)) {
185 policy->SetString(policy_name, string_value);
186 }
187 }
[email protected]f992585f2011-08-17 22:07:55188 return policy;
189 }
190
191 // Post a reload notification and update the watch machinery.
192 void Reload() {
[email protected]000d1f62012-07-24 01:56:54193 DCHECK(OnPolicyWatcherThread());
[email protected]f992585f2011-08-17 22:07:55194 SetupWatches();
195 scoped_ptr<DictionaryValue> new_policy(Load());
[email protected]000d1f62012-07-24 01:56:54196 UpdatePolicies(new_policy.get());
[email protected]f992585f2011-08-17 22:07:55197 }
198
199 // ObjectWatcher::Delegate overrides:
200 virtual void OnObjectSignaled(HANDLE object) {
[email protected]000d1f62012-07-24 01:56:54201 DCHECK(OnPolicyWatcherThread());
[email protected]f992585f2011-08-17 22:07:55202 DCHECK(object == user_policy_changed_event_.handle() ||
203 object == machine_policy_changed_event_.handle())
204 << "unexpected object signaled policy reload, obj = "
205 << std::showbase << std::hex << object;
206 Reload();
207 }
208
209 base::WaitableEvent user_policy_changed_event_;
210 base::WaitableEvent machine_policy_changed_event_;
211 base::win::ObjectWatcher user_policy_watcher_;
212 base::win::ObjectWatcher machine_policy_watcher_;
213 bool user_policy_watcher_failed_;
214 bool machine_policy_watcher_failed_;
[email protected]c9927802011-08-15 23:54:57215};
216
[email protected]000d1f62012-07-24 01:56:54217PolicyWatcher* PolicyWatcher::Create(
[email protected]3c8cfbe72012-07-03 00:24:15218 scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
[email protected]000d1f62012-07-24 01:56:54219 return new PolicyWatcherWin(task_runner);
[email protected]c9927802011-08-15 23:54:57220}
221
222} // namespace policy_hack
223} // namespace remoting