Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(123)

Side by Side Diff: chrome/browser/policy/configuration_policy_provider_win.cc

Issue 6091002: Refactor the windows policy provider to use AsynchronousPolicyProvider. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fix windows tests Created 10 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 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 #include "chrome/browser/policy/configuration_policy_provider_win.h" 5 #include "chrome/browser/policy/configuration_policy_provider_win.h"
6 6
7 #include <userenv.h> 7 #include "chrome/browser/policy/asynchronous_policy_provider.h"
8 8 #include "chrome/browser/policy/configuration_policy_loader_win.h"
9 #include <algorithm> 9 #include "chrome/browser/policy/configuration_policy_provider_delegate_win.h"
10
11 #include "base/logging.h"
12 #include "base/object_watcher.h"
13 #include "base/scoped_ptr.h"
14 #include "base/string_number_conversions.h"
15 #include "base/string_piece.h"
16 #include "base/string_util.h"
17 #include "base/sys_string_conversions.h"
18 #include "base/thread_restrictions.h"
19 #include "base/utf_string_conversions.h"
20 #include "base/values.h"
21 #include "base/win/registry.h"
22 #include "chrome/common/policy_constants.h"
23
24 using base::win::RegKey;
25 10
26 namespace policy { 11 namespace policy {
27 12
28 namespace {
29
30 bool ReadRegistryStringValue(RegKey* key, const string16& name,
31 string16* result) {
32 DWORD value_size = 0;
33 DWORD key_type = 0;
34 scoped_array<uint8> buffer;
35
36 if (!key->ReadValue(name.c_str(), 0, &value_size, &key_type))
37 return false;
38 if (key_type != REG_SZ)
39 return false;
40
41 // According to the Microsoft documentation, the string
42 // buffer may not be explicitly 0-terminated. Allocate a
43 // slightly larger buffer and pre-fill to zeros to guarantee
44 // the 0-termination.
45 buffer.reset(new uint8[value_size + 2]);
46 memset(buffer.get(), 0, value_size + 2);
47 key->ReadValue(name.c_str(), buffer.get(), &value_size, NULL);
48 result->assign(reinterpret_cast<const wchar_t*>(buffer.get()));
49 return true;
50 }
51
52 } // namespace
53
54 // Period at which to run the reload task in case the group policy change 13 // Period at which to run the reload task in case the group policy change
55 // watchers fail. 14 // watchers fail.
56 const int kReloadIntervalMinutes = 15; 15 const int kReloadIntervalMinutes = 15;
57 16
58 ConfigurationPolicyProviderWin::GroupPolicyChangeWatcher::
59 GroupPolicyChangeWatcher(
60 base::WeakPtr<ConfigurationPolicyProviderWin> provider,
61 int reload_interval_minutes)
62 : provider_(provider),
63 user_policy_changed_event_(false, false),
64 machine_policy_changed_event_(false, false),
65 user_policy_watcher_failed_(false),
66 machine_policy_watcher_failed_(false),
67 reload_interval_minutes_(reload_interval_minutes),
68 reload_task_(NULL) {
69 if (!RegisterGPNotification(user_policy_changed_event_.handle(), false)) {
70 PLOG(WARNING) << "Failed to register user group policy notification";
71 user_policy_watcher_failed_ = true;
72 }
73 if (!RegisterGPNotification(machine_policy_changed_event_.handle(), true)) {
74 PLOG(WARNING) << "Failed to register machine group policy notification.";
75 machine_policy_watcher_failed_ = true;
76 }
77 }
78
79 ConfigurationPolicyProviderWin::GroupPolicyChangeWatcher::
80 ~GroupPolicyChangeWatcher() {
81 if (MessageLoop::current())
82 MessageLoop::current()->RemoveDestructionObserver(this);
83 DCHECK(!reload_task_);
84 }
85
86 void ConfigurationPolicyProviderWin::GroupPolicyChangeWatcher::Start() {
87 MessageLoop::current()->AddDestructionObserver(this);
88 SetupWatches();
89 }
90
91 void ConfigurationPolicyProviderWin::GroupPolicyChangeWatcher::Stop() {
92 user_policy_watcher_.StopWatching();
93 machine_policy_watcher_.StopWatching();
94 if (reload_task_) {
95 reload_task_->Cancel();
96 reload_task_ = NULL;
97 }
98 }
99
100 void ConfigurationPolicyProviderWin::GroupPolicyChangeWatcher::SetupWatches() {
101 if (reload_task_) {
102 reload_task_->Cancel();
103 reload_task_ = NULL;
104 }
105
106 if (!user_policy_watcher_failed_) {
107 if (!user_policy_watcher_.GetWatchedObject() &&
108 !user_policy_watcher_.StartWatching(
109 user_policy_changed_event_.handle(), this)) {
110 LOG(WARNING) << "Failed to start watch for user policy change event";
111 user_policy_watcher_failed_ = true;
112 }
113 }
114 if (!machine_policy_watcher_failed_) {
115 if (!machine_policy_watcher_.GetWatchedObject() &&
116 !machine_policy_watcher_.StartWatching(
117 machine_policy_changed_event_.handle(), this)) {
118 LOG(WARNING) << "Failed to start watch for machine policy change event";
119 machine_policy_watcher_failed_ = true;
120 }
121 }
122
123 if (user_policy_watcher_failed_ || machine_policy_watcher_failed_) {
124 reload_task_ =
125 NewRunnableMethod(this, &GroupPolicyChangeWatcher::ReloadFromTask);
126 int64 delay =
127 base::TimeDelta::FromMinutes(reload_interval_minutes_).InMilliseconds();
128 MessageLoop::current()->PostDelayedTask(FROM_HERE, reload_task_, delay);
129 }
130 }
131
132 void ConfigurationPolicyProviderWin::GroupPolicyChangeWatcher::Reload() {
133 if (provider_.get())
134 provider_->NotifyStoreOfPolicyChange();
135 SetupWatches();
136 }
137
138 void ConfigurationPolicyProviderWin::GroupPolicyChangeWatcher::
139 ReloadFromTask() {
140 // Make sure to not call Cancel() on the task, since it might hold the last
141 // reference that keeps this object alive.
142 reload_task_ = NULL;
143 Reload();
144 }
145
146 void ConfigurationPolicyProviderWin::GroupPolicyChangeWatcher::
147 OnObjectSignaled(HANDLE object) {
148 DCHECK(object == user_policy_changed_event_.handle() ||
149 object == machine_policy_changed_event_.handle())
150 << "unexpected object signaled policy reload, obj = "
151 << std::showbase << std::hex << object;
152 Reload();
153 }
154
155 void ConfigurationPolicyProviderWin::GroupPolicyChangeWatcher::
156 WillDestroyCurrentMessageLoop() {
157 reload_task_ = NULL;
158 MessageLoop::current()->RemoveDestructionObserver(this);
159 }
160
161 ConfigurationPolicyProviderWin::ConfigurationPolicyProviderWin( 17 ConfigurationPolicyProviderWin::ConfigurationPolicyProviderWin(
162 const PolicyDefinitionList* policy_list) 18 const PolicyDefinitionList* policy_list)
163 : ConfigurationPolicyProvider(policy_list) { 19 : AsynchronousPolicyProvider(
164 watcher_ = new GroupPolicyChangeWatcher(this->AsWeakPtr(), 20 policy_list,
165 kReloadIntervalMinutes); 21 new ConfigurationPolicyLoaderWin(
166 watcher_->Start(); 22 new ConfigurationPolicyProviderDelegateWin(policy_list),
167 } 23 kReloadIntervalMinutes)) {}
168
169 ConfigurationPolicyProviderWin::~ConfigurationPolicyProviderWin() {
170 watcher_->Stop();
171 }
172
173 bool ConfigurationPolicyProviderWin::GetRegistryPolicyString(
174 const string16& name, string16* result) const {
175 string16 path = string16(kRegistrySubKey);
176 RegKey policy_key;
177 // First try the global policy.
178 if (policy_key.Open(HKEY_LOCAL_MACHINE, path.c_str(), KEY_READ)) {
179 if (ReadRegistryStringValue(&policy_key, name, result))
180 return true;
181 policy_key.Close();
182 }
183 // Fall back on user-specific policy.
184 if (!policy_key.Open(HKEY_CURRENT_USER, path.c_str(), KEY_READ))
185 return false;
186 return ReadRegistryStringValue(&policy_key, name, result);
187 }
188
189 bool ConfigurationPolicyProviderWin::GetRegistryPolicyStringList(
190 const string16& key, ListValue* result) const {
191 string16 path = string16(kRegistrySubKey);
192 path += ASCIIToUTF16("\\") + key;
193 RegKey policy_key;
194 if (!policy_key.Open(HKEY_LOCAL_MACHINE, path.c_str(), KEY_READ)) {
195 policy_key.Close();
196 // Fall back on user-specific policy.
197 if (!policy_key.Open(HKEY_CURRENT_USER, path.c_str(), KEY_READ))
198 return false;
199 }
200 string16 policy_string;
201 int index = 0;
202 while (ReadRegistryStringValue(&policy_key, base::IntToString16(++index),
203 &policy_string)) {
204 result->Append(Value::CreateStringValue(policy_string));
205 }
206 return true;
207 }
208
209 bool ConfigurationPolicyProviderWin::GetRegistryPolicyBoolean(
210 const string16& value_name, bool* result) const {
211 DWORD value;
212 RegKey hkcu_policy_key(HKEY_LOCAL_MACHINE, kRegistrySubKey, KEY_READ);
213 if (hkcu_policy_key.ReadValueDW(value_name.c_str(), &value)) {
214 *result = value != 0;
215 return true;
216 }
217
218 RegKey hklm_policy_key(HKEY_CURRENT_USER, kRegistrySubKey, KEY_READ);
219 if (hklm_policy_key.ReadValueDW(value_name.c_str(), &value)) {
220 *result = value != 0;
221 return true;
222 }
223 return false;
224 }
225
226 bool ConfigurationPolicyProviderWin::GetRegistryPolicyInteger(
227 const string16& value_name, uint32* result) const {
228 DWORD value;
229 RegKey hkcu_policy_key(HKEY_LOCAL_MACHINE, kRegistrySubKey, KEY_READ);
230 if (hkcu_policy_key.ReadValueDW(value_name.c_str(), &value)) {
231 *result = value;
232 return true;
233 }
234
235 RegKey hklm_policy_key(HKEY_CURRENT_USER, kRegistrySubKey, KEY_READ);
236 if (hklm_policy_key.ReadValueDW(value_name.c_str(), &value)) {
237 *result = value;
238 return true;
239 }
240 return false;
241 }
242
243 bool ConfigurationPolicyProviderWin::Provide(
244 ConfigurationPolicyStoreInterface* store) {
245 // This function calls GetRegistryPolicy* which hit up the registry. Those
246 // are I/O functions not allowed to be called on the main thread.
247 // http://crbug.com/66453
248 base::ThreadRestrictions::ScopedAllowIO allow_io;
249 const PolicyDefinitionList* policy_list(policy_definition_list());
250 for (const PolicyDefinitionList::Entry* current = policy_list->begin;
251 current != policy_list->end; ++current) {
252 std::wstring name = UTF8ToWide(current->name);
253 switch (current->value_type) {
254 case Value::TYPE_STRING: {
255 std::wstring string_value;
256 if (GetRegistryPolicyString(name.c_str(), &string_value)) {
257 store->Apply(current->policy_type,
258 Value::CreateStringValue(string_value));
259 }
260 break;
261 }
262 case Value::TYPE_LIST: {
263 scoped_ptr<ListValue> list_value(new ListValue);
264 if (GetRegistryPolicyStringList(name.c_str(), list_value.get()))
265 store->Apply(current->policy_type, list_value.release());
266 break;
267 }
268 case Value::TYPE_BOOLEAN: {
269 bool bool_value;
270 if (GetRegistryPolicyBoolean(name.c_str(), &bool_value)) {
271 store->Apply(current->policy_type,
272 Value::CreateBooleanValue(bool_value));
273 }
274 break;
275 }
276 case Value::TYPE_INTEGER: {
277 uint32 int_value;
278 if (GetRegistryPolicyInteger(name.c_str(), &int_value)) {
279 store->Apply(current->policy_type,
280 Value::CreateIntegerValue(int_value));
281 }
282 break;
283 }
284 default:
285 NOTREACHED();
286 return false;
287 }
288 }
289
290 return true;
291 }
292 24
293 } // namespace policy 25 } // namespace policy
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698